From f911ba985aa7fe0096c386c5be385ac5825ea527 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 16 Jul 2005 00:30:23 +0000 Subject: Initial revision From-SVN: r102074 --- libjava/classpath/javax/swing/AbstractAction.java | 278 ++ libjava/classpath/javax/swing/AbstractButton.java | 2014 +++++++++++++ .../classpath/javax/swing/AbstractCellEditor.java | 191 ++ .../classpath/javax/swing/AbstractListModel.java | 179 ++ .../javax/swing/AbstractSpinnerModel.java | 117 + libjava/classpath/javax/swing/Action.java | 153 + libjava/classpath/javax/swing/ActionMap.java | 211 ++ libjava/classpath/javax/swing/BorderFactory.java | 451 +++ .../classpath/javax/swing/BoundedRangeModel.java | 171 ++ libjava/classpath/javax/swing/Box.java | 287 ++ libjava/classpath/javax/swing/BoxLayout.java | 746 +++++ libjava/classpath/javax/swing/ButtonGroup.java | 179 ++ libjava/classpath/javax/swing/ButtonModel.java | 85 + libjava/classpath/javax/swing/CellEditor.java | 96 + .../classpath/javax/swing/CellRendererPane.java | 251 ++ libjava/classpath/javax/swing/ComboBoxEditor.java | 96 + libjava/classpath/javax/swing/ComboBoxModel.java | 67 + .../classpath/javax/swing/ComponentInputMap.java | 130 + libjava/classpath/javax/swing/DebugGraphics.java | 885 ++++++ .../javax/swing/DefaultBoundedRangeModel.java | 443 +++ .../classpath/javax/swing/DefaultButtonModel.java | 575 ++++ .../classpath/javax/swing/DefaultCellEditor.java | 344 +++ .../javax/swing/DefaultComboBoxModel.java | 238 ++ .../javax/swing/DefaultDesktopManager.java | 629 ++++ .../classpath/javax/swing/DefaultFocusManager.java | 166 ++ .../javax/swing/DefaultListCellRenderer.java | 179 ++ .../classpath/javax/swing/DefaultListModel.java | 521 ++++ .../javax/swing/DefaultListSelectionModel.java | 706 +++++ .../javax/swing/DefaultSingleSelectionModel.java | 172 ++ libjava/classpath/javax/swing/DesktopManager.java | 177 ++ libjava/classpath/javax/swing/FocusManager.java | 161 + libjava/classpath/javax/swing/GrayFilter.java | 92 + libjava/classpath/javax/swing/Icon.java | 52 + libjava/classpath/javax/swing/ImageIcon.java | 361 +++ libjava/classpath/javax/swing/InputMap.java | 213 ++ libjava/classpath/javax/swing/InputVerifier.java | 75 + .../swing/InternalFrameFocusTraversalPolicy.java | 55 + libjava/classpath/javax/swing/JApplet.java | 213 ++ libjava/classpath/javax/swing/JButton.java | 155 + libjava/classpath/javax/swing/JCheckBox.java | 143 + .../classpath/javax/swing/JCheckBoxMenuItem.java | 251 ++ libjava/classpath/javax/swing/JColorChooser.java | 702 +++++ libjava/classpath/javax/swing/JComboBox.java | 1223 ++++++++ libjava/classpath/javax/swing/JComponent.java | 2680 +++++++++++++++++ libjava/classpath/javax/swing/JDesktopPane.java | 331 +++ libjava/classpath/javax/swing/JDialog.java | 588 ++++ libjava/classpath/javax/swing/JEditorPane.java | 333 +++ libjava/classpath/javax/swing/JFileChooser.java | 1190 ++++++++ .../classpath/javax/swing/JFormattedTextField.java | 347 +++ libjava/classpath/javax/swing/JFrame.java | 349 +++ libjava/classpath/javax/swing/JInternalFrame.java | 1754 +++++++++++ libjava/classpath/javax/swing/JLabel.java | 647 ++++ libjava/classpath/javax/swing/JLayeredPane.java | 622 ++++ libjava/classpath/javax/swing/JList.java | 1416 +++++++++ libjava/classpath/javax/swing/JMenu.java | 915 ++++++ libjava/classpath/javax/swing/JMenuBar.java | 459 +++ libjava/classpath/javax/swing/JMenuItem.java | 677 +++++ libjava/classpath/javax/swing/JOptionPane.java | 1547 ++++++++++ libjava/classpath/javax/swing/JPanel.java | 114 + libjava/classpath/javax/swing/JPasswordField.java | 270 ++ libjava/classpath/javax/swing/JPopupMenu.java | 1071 +++++++ libjava/classpath/javax/swing/JProgressBar.java | 661 +++++ libjava/classpath/javax/swing/JRadioButton.java | 259 ++ .../javax/swing/JRadioButtonMenuItem.java | 212 ++ libjava/classpath/javax/swing/JRootPane.java | 625 ++++ libjava/classpath/javax/swing/JScrollBar.java | 647 ++++ libjava/classpath/javax/swing/JScrollPane.java | 733 +++++ libjava/classpath/javax/swing/JSeparator.java | 197 ++ libjava/classpath/javax/swing/JSlider.java | 907 ++++++ libjava/classpath/javax/swing/JSpinner.java | 622 ++++ libjava/classpath/javax/swing/JSplitPane.java | 815 ++++++ libjava/classpath/javax/swing/JTabbedPane.java | 1478 ++++++++++ libjava/classpath/javax/swing/JTable.java | 2170 ++++++++++++++ libjava/classpath/javax/swing/JTextArea.java | 550 ++++ libjava/classpath/javax/swing/JTextField.java | 441 +++ libjava/classpath/javax/swing/JTextPane.java | 270 ++ libjava/classpath/javax/swing/JToggleButton.java | 323 ++ libjava/classpath/javax/swing/JToolBar.java | 779 +++++ libjava/classpath/javax/swing/JToolTip.java | 197 ++ libjava/classpath/javax/swing/JTree.java | 1829 ++++++++++++ libjava/classpath/javax/swing/JViewport.java | 490 ++++ libjava/classpath/javax/swing/JWindow.java | 245 ++ libjava/classpath/javax/swing/KeyStroke.java | 122 + .../javax/swing/LayoutFocusTraversalPolicy.java | 89 + .../classpath/javax/swing/ListCellRenderer.java | 52 + libjava/classpath/javax/swing/ListModel.java | 80 + .../classpath/javax/swing/ListSelectionModel.java | 86 + libjava/classpath/javax/swing/LookAndFeel.java | 236 ++ libjava/classpath/javax/swing/MenuElement.java | 93 + .../javax/swing/MenuSelectionManager.java | 387 +++ .../javax/swing/MutableComboBoxModel.java | 82 + libjava/classpath/javax/swing/OverlayLayout.java | 191 ++ libjava/classpath/javax/swing/Popup.java | 189 ++ libjava/classpath/javax/swing/PopupFactory.java | 139 + libjava/classpath/javax/swing/ProgressMonitor.java | 228 ++ .../javax/swing/ProgressMonitorInputStream.java | 160 + libjava/classpath/javax/swing/Renderer.java | 72 + libjava/classpath/javax/swing/RepaintManager.java | 568 ++++ .../classpath/javax/swing/RootPaneContainer.java | 100 + .../classpath/javax/swing/ScrollPaneConstants.java | 152 + .../classpath/javax/swing/ScrollPaneLayout.java | 484 +++ libjava/classpath/javax/swing/Scrollable.java | 56 + .../javax/swing/SingleSelectionModel.java | 91 + .../classpath/javax/swing/SizeRequirements.java | 329 +++ libjava/classpath/javax/swing/SizeSequence.java | 249 ++ .../javax/swing/SortingFocusTraversalPolicy.java | 333 +++ .../classpath/javax/swing/SpinnerDateModel.java | 237 ++ .../classpath/javax/swing/SpinnerListModel.java | 296 ++ libjava/classpath/javax/swing/SpinnerModel.java | 111 + .../classpath/javax/swing/SpinnerNumberModel.java | 298 ++ libjava/classpath/javax/swing/Spring.java | 580 ++++ libjava/classpath/javax/swing/SpringLayout.java | 657 +++++ libjava/classpath/javax/swing/SwingConstants.java | 77 + libjava/classpath/javax/swing/SwingUtilities.java | 1395 +++++++++ libjava/classpath/javax/swing/Timer.java | 485 +++ libjava/classpath/javax/swing/ToolTipManager.java | 646 ++++ libjava/classpath/javax/swing/TransferHandler.java | 190 ++ libjava/classpath/javax/swing/UIDefaults.java | 842 ++++++ libjava/classpath/javax/swing/UIManager.java | 491 ++++ .../swing/UnsupportedLookAndFeelException.java | 47 + libjava/classpath/javax/swing/ViewportLayout.java | 169 ++ libjava/classpath/javax/swing/WindowConstants.java | 73 + .../javax/swing/border/AbstractBorder.java | 192 ++ .../classpath/javax/swing/border/BevelBorder.java | 568 ++++ libjava/classpath/javax/swing/border/Border.java | 105 + .../javax/swing/border/CompoundBorder.java | 257 ++ .../classpath/javax/swing/border/EmptyBorder.java | 223 ++ .../classpath/javax/swing/border/EtchedBorder.java | 411 +++ .../classpath/javax/swing/border/LineBorder.java | 343 +++ .../classpath/javax/swing/border/MatteBorder.java | 404 +++ .../javax/swing/border/SoftBevelBorder.java | 329 +++ .../classpath/javax/swing/border/TitledBorder.java | 1155 ++++++++ .../javax/swing/border/doc-files/BevelBorder-1.png | Bin 0 -> 4440 bytes .../javax/swing/border/doc-files/BevelBorder-2.png | Bin 0 -> 3667 bytes .../javax/swing/border/doc-files/BevelBorder-3.png | Bin 0 -> 4981 bytes .../javax/swing/border/doc-files/EmptyBorder-1.png | Bin 0 -> 11522 bytes .../swing/border/doc-files/EtchedBorder-1.png | Bin 0 -> 4820 bytes .../swing/border/doc-files/EtchedBorder-2.png | Bin 0 -> 3850 bytes .../javax/swing/border/doc-files/LineBorder-1.png | Bin 0 -> 6133 bytes .../javax/swing/border/doc-files/MatteBorder-1.png | Bin 0 -> 5447 bytes .../javax/swing/border/doc-files/MatteBorder-2.png | Bin 0 -> 5099 bytes .../javax/swing/border/doc-files/MatteBorder-3.png | Bin 0 -> 5726 bytes .../javax/swing/border/doc-files/MatteBorder-4.png | Bin 0 -> 7220 bytes .../javax/swing/border/doc-files/MatteBorder-5.png | Bin 0 -> 7971 bytes .../javax/swing/border/doc-files/MatteBorder-6.png | Bin 0 -> 5511 bytes .../swing/border/doc-files/SoftBevelBorder-1.png | Bin 0 -> 4877 bytes .../swing/border/doc-files/SoftBevelBorder-2.png | Bin 0 -> 3860 bytes .../swing/border/doc-files/SoftBevelBorder-3.png | Bin 0 -> 5155 bytes libjava/classpath/javax/swing/border/package.html | 47 + .../colorchooser/AbstractColorChooserPanel.java | 162 + .../colorchooser/ColorChooserComponentFactory.java | 85 + .../swing/colorchooser/ColorSelectionModel.java | 81 + .../colorchooser/DefaultColorSelectionModel.java | 163 ++ .../swing/colorchooser/DefaultHSBChooserPanel.java | 891 ++++++ .../swing/colorchooser/DefaultPreviewPanel.java | 318 ++ .../swing/colorchooser/DefaultRGBChooserPanel.java | 402 +++ .../colorchooser/DefaultSwatchChooserPanel.java | 893 ++++++ .../javax/swing/colorchooser/package.html | 47 + .../classpath/javax/swing/event/AncestorEvent.java | 100 + .../javax/swing/event/AncestorListener.java | 69 + .../classpath/javax/swing/event/CaretEvent.java | 79 + .../classpath/javax/swing/event/CaretListener.java | 56 + .../javax/swing/event/CellEditorListener.java | 62 + .../classpath/javax/swing/event/ChangeEvent.java | 59 + .../javax/swing/event/ChangeListener.java | 57 + .../classpath/javax/swing/event/DocumentEvent.java | 166 ++ .../javax/swing/event/DocumentListener.java | 68 + .../javax/swing/event/EventListenerList.java | 302 ++ .../javax/swing/event/HyperlinkEvent.java | 162 + .../javax/swing/event/HyperlinkListener.java | 57 + .../javax/swing/event/InternalFrameAdapter.java | 113 + .../javax/swing/event/InternalFrameEvent.java | 115 + .../javax/swing/event/InternalFrameListener.java | 92 + .../classpath/javax/swing/event/ListDataEvent.java | 98 + .../javax/swing/event/ListDataListener.java | 69 + .../javax/swing/event/ListSelectionEvent.java | 126 + .../javax/swing/event/ListSelectionListener.java | 57 + .../javax/swing/event/MenuDragMouseEvent.java | 115 + .../javax/swing/event/MenuDragMouseListener.java | 74 + libjava/classpath/javax/swing/event/MenuEvent.java | 59 + .../classpath/javax/swing/event/MenuKeyEvent.java | 113 + .../javax/swing/event/MenuKeyListener.java | 68 + .../classpath/javax/swing/event/MenuListener.java | 68 + .../javax/swing/event/MouseInputAdapter.java | 119 + .../javax/swing/event/MouseInputListener.java | 52 + .../javax/swing/event/PopupMenuEvent.java | 58 + .../javax/swing/event/PopupMenuListener.java | 68 + .../swing/event/SwingPropertyChangeSupport.java | 255 ++ .../javax/swing/event/TableColumnModelEvent.java | 105 + .../swing/event/TableColumnModelListener.java | 80 + .../javax/swing/event/TableModelEvent.java | 220 ++ .../javax/swing/event/TableModelListener.java | 55 + .../javax/swing/event/TreeExpansionEvent.java | 89 + .../javax/swing/event/TreeExpansionListener.java | 62 + .../javax/swing/event/TreeModelEvent.java | 171 ++ .../javax/swing/event/TreeModelListener.java | 74 + .../javax/swing/event/TreeSelectionEvent.java | 199 ++ .../javax/swing/event/TreeSelectionListener.java | 56 + .../javax/swing/event/TreeWillExpandListener.java | 65 + .../javax/swing/event/UndoableEditEvent.java | 92 + .../javax/swing/event/UndoableEditListener.java | 56 + libjava/classpath/javax/swing/event/package.html | 47 + .../javax/swing/filechooser/FileFilter.java | 80 + .../javax/swing/filechooser/FileSystemView.java | 361 +++ .../javax/swing/filechooser/FileView.java | 114 + .../swing/filechooser/UnixFileSystemView.java | 144 + .../classpath/javax/swing/filechooser/package.html | 47 + libjava/classpath/javax/swing/package.html | 47 + .../javax/swing/plaf/ActionMapUIResource.java | 64 + .../javax/swing/plaf/BorderUIResource.java | 933 ++++++ libjava/classpath/javax/swing/plaf/ButtonUI.java | 52 + .../classpath/javax/swing/plaf/ColorChooserUI.java | 60 + .../javax/swing/plaf/ColorUIResource.java | 123 + libjava/classpath/javax/swing/plaf/ComboBoxUI.java | 96 + .../swing/plaf/ComponentInputMapUIResource.java | 70 + .../classpath/javax/swing/plaf/ComponentUI.java | 326 +++ .../classpath/javax/swing/plaf/DesktopIconUI.java | 56 + .../classpath/javax/swing/plaf/DesktopPaneUI.java | 59 + .../javax/swing/plaf/DimensionUIResource.java | 68 + .../classpath/javax/swing/plaf/FileChooserUI.java | 138 + .../classpath/javax/swing/plaf/FontUIResource.java | 101 + .../classpath/javax/swing/plaf/IconUIResource.java | 122 + .../javax/swing/plaf/InputMapUIResource.java | 63 + .../javax/swing/plaf/InsetsUIResource.java | 77 + .../javax/swing/plaf/InternalFrameUI.java | 59 + libjava/classpath/javax/swing/plaf/LabelUI.java | 59 + libjava/classpath/javax/swing/plaf/ListUI.java | 114 + libjava/classpath/javax/swing/plaf/MenuBarUI.java | 59 + libjava/classpath/javax/swing/plaf/MenuItemUI.java | 59 + .../classpath/javax/swing/plaf/OptionPaneUI.java | 75 + libjava/classpath/javax/swing/plaf/PanelUI.java | 58 + .../classpath/javax/swing/plaf/PopupMenuUI.java | 117 + .../classpath/javax/swing/plaf/ProgressBarUI.java | 59 + libjava/classpath/javax/swing/plaf/RootPaneUI.java | 58 + .../classpath/javax/swing/plaf/ScrollBarUI.java | 58 + .../classpath/javax/swing/plaf/ScrollPaneUI.java | 59 + .../classpath/javax/swing/plaf/SeparatorUI.java | 58 + libjava/classpath/javax/swing/plaf/SliderUI.java | 59 + libjava/classpath/javax/swing/plaf/SpinnerUI.java | 59 + .../classpath/javax/swing/plaf/SplitPaneUI.java | 133 + .../classpath/javax/swing/plaf/TabbedPaneUI.java | 111 + .../classpath/javax/swing/plaf/TableHeaderUI.java | 59 + libjava/classpath/javax/swing/plaf/TableUI.java | 59 + libjava/classpath/javax/swing/plaf/TextUI.java | 284 ++ libjava/classpath/javax/swing/plaf/ToolBarUI.java | 59 + libjava/classpath/javax/swing/plaf/ToolTipUI.java | 59 + libjava/classpath/javax/swing/plaf/TreeUI.java | 211 ++ libjava/classpath/javax/swing/plaf/UIResource.java | 55 + libjava/classpath/javax/swing/plaf/ViewportUI.java | 60 + .../javax/swing/plaf/basic/BasicArrowButton.java | 350 +++ .../javax/swing/plaf/basic/BasicBorders.java | 1814 ++++++++++++ .../swing/plaf/basic/BasicButtonListener.java | 231 ++ .../javax/swing/plaf/basic/BasicButtonUI.java | 421 +++ .../swing/plaf/basic/BasicCheckBoxMenuItemUI.java | 104 + .../javax/swing/plaf/basic/BasicCheckBoxUI.java | 73 + .../swing/plaf/basic/BasicColorChooserUI.java | 339 +++ .../swing/plaf/basic/BasicComboBoxEditor.java | 170 ++ .../swing/plaf/basic/BasicComboBoxRenderer.java | 142 + .../javax/swing/plaf/basic/BasicComboBoxUI.java | 1243 ++++++++ .../javax/swing/plaf/basic/BasicComboPopup.java | 1055 +++++++ .../javax/swing/plaf/basic/BasicDesktopIconUI.java | 590 ++++ .../javax/swing/plaf/basic/BasicDesktopPaneUI.java | 464 +++ .../swing/plaf/basic/BasicDirectoryModel.java | 313 ++ .../javax/swing/plaf/basic/BasicEditorPaneUI.java | 68 + .../javax/swing/plaf/basic/BasicFileChooserUI.java | 1921 ++++++++++++ .../plaf/basic/BasicFormattedTextFieldUI.java | 62 + .../javax/swing/plaf/basic/BasicGraphicsUtils.java | 641 ++++ .../javax/swing/plaf/basic/BasicIconFactory.java | 238 ++ .../plaf/basic/BasicInternalFrameTitlePane.java | 940 ++++++ .../swing/plaf/basic/BasicInternalFrameUI.java | 1719 +++++++++++ .../javax/swing/plaf/basic/BasicLabelUI.java | 425 +++ .../javax/swing/plaf/basic/BasicListUI.java | 1004 +++++++ .../javax/swing/plaf/basic/BasicLookAndFeel.java | 1058 +++++++ .../javax/swing/plaf/basic/BasicMenuBarUI.java | 304 ++ .../javax/swing/plaf/basic/BasicMenuItemUI.java | 1006 +++++++ .../javax/swing/plaf/basic/BasicMenuUI.java | 541 ++++ .../javax/swing/plaf/basic/BasicOptionPaneUI.java | 1329 +++++++++ .../javax/swing/plaf/basic/BasicPanelUI.java | 67 + .../swing/plaf/basic/BasicPasswordFieldUI.java | 67 + .../plaf/basic/BasicPopupMenuSeparatorUI.java | 114 + .../javax/swing/plaf/basic/BasicPopupMenuUI.java | 674 +++++ .../javax/swing/plaf/basic/BasicProgressBarUI.java | 827 ++++++ .../plaf/basic/BasicRadioButtonMenuItemUI.java | 102 + .../javax/swing/plaf/basic/BasicRadioButtonUI.java | 87 + .../javax/swing/plaf/basic/BasicRootPaneUI.java | 66 + .../javax/swing/plaf/basic/BasicScrollBarUI.java | 1271 ++++++++ .../javax/swing/plaf/basic/BasicScrollPaneUI.java | 130 + .../javax/swing/plaf/basic/BasicSeparatorUI.java | 269 ++ .../javax/swing/plaf/basic/BasicSliderUI.java | 2239 ++++++++++++++ .../javax/swing/plaf/basic/BasicSpinnerUI.java | 574 ++++ .../swing/plaf/basic/BasicSplitPaneDivider.java | 912 ++++++ .../javax/swing/plaf/basic/BasicSplitPaneUI.java | 1556 ++++++++++ .../javax/swing/plaf/basic/BasicTabbedPaneUI.java | 3084 ++++++++++++++++++++ .../javax/swing/plaf/basic/BasicTableHeaderUI.java | 224 ++ .../javax/swing/plaf/basic/BasicTableUI.java | 398 +++ .../javax/swing/plaf/basic/BasicTextAreaUI.java | 68 + .../javax/swing/plaf/basic/BasicTextFieldUI.java | 80 + .../javax/swing/plaf/basic/BasicTextPaneUI.java | 68 + .../javax/swing/plaf/basic/BasicTextUI.java | 635 ++++ .../swing/plaf/basic/BasicToggleButtonUI.java | 62 + .../swing/plaf/basic/BasicToolBarSeparatorUI.java | 127 + .../javax/swing/plaf/basic/BasicToolBarUI.java | 1435 +++++++++ .../javax/swing/plaf/basic/BasicToolTipUI.java | 288 ++ .../javax/swing/plaf/basic/BasicTreeUI.java | 2813 ++++++++++++++++++ .../javax/swing/plaf/basic/BasicViewportUI.java | 234 ++ .../javax/swing/plaf/basic/ComboPopup.java | 103 + .../javax/swing/plaf/basic/DefaultMenuLayout.java | 78 + .../swing/plaf/basic/doc-files/BasicBorders-1.png | Bin 0 -> 454 bytes .../swing/plaf/basic/doc-files/BasicBorders-2.png | Bin 0 -> 857 bytes .../doc-files/BasicBorders.ButtonBorder-1.png | Bin 0 -> 1787 bytes .../basic/doc-files/BasicBorders.FieldBorder-1.png | Bin 0 -> 5267 bytes .../doc-files/BasicBorders.MarginBorder-1.png | Bin 0 -> 14735 bytes .../doc-files/BasicBorders.MenuBarBorder-1.png | Bin 0 -> 3180 bytes .../doc-files/BasicBorders.RadioButtonBorder-1.png | Bin 0 -> 2667 bytes .../doc-files/BasicBorders.SplitPaneBorder-1.png | Bin 0 -> 8803 bytes .../doc-files/BasicBorders.SplitPaneBorder-2.png | Bin 0 -> 5976 bytes .../BasicBorders.SplitPaneDividerBorder-1.png | Bin 0 -> 7169 bytes .../BasicBorders.ToggleButtonBorder-1.png | Bin 0 -> 1874 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-1.png | Bin 0 -> 4844 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-2.png | Bin 0 -> 3771 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-3.png | Bin 0 -> 13480 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-4.png | Bin 0 -> 4832 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-5.png | Bin 0 -> 6884 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-6.png | Bin 0 -> 6816 bytes .../plaf/basic/doc-files/BasicGraphicsUtils-7.png | Bin 0 -> 3676 bytes .../classpath/javax/swing/plaf/basic/package.html | 46 + .../javax/swing/plaf/doc-files/ComponentUI-1.dia | Bin 0 -> 3085 bytes .../javax/swing/plaf/doc-files/ComponentUI-1.png | Bin 0 -> 32683 bytes .../javax/swing/plaf/doc-files/TreeUI-1.png | Bin 0 -> 8660 bytes .../javax/swing/plaf/metal/DefaultMetalTheme.java | 221 ++ .../javax/swing/plaf/metal/MetalBorders.java | 443 +++ .../javax/swing/plaf/metal/MetalButtonUI.java | 101 + .../javax/swing/plaf/metal/MetalCheckBoxIcon.java | 136 + .../javax/swing/plaf/metal/MetalCheckBoxUI.java | 74 + .../javax/swing/plaf/metal/MetalComboBoxIcon.java | 100 + .../javax/swing/plaf/metal/MetalComboBoxUI.java | 86 + .../javax/swing/plaf/metal/MetalDesktopIconUI.java | 74 + .../javax/swing/plaf/metal/MetalIconFactory.java | 672 +++++ .../swing/plaf/metal/MetalInternalFrameUI.java | 88 + .../javax/swing/plaf/metal/MetalLabelUI.java | 74 + .../javax/swing/plaf/metal/MetalLookAndFeel.java | 853 ++++++ .../plaf/metal/MetalPopupMenuSeparatorUI.java | 73 + .../javax/swing/plaf/metal/MetalProgressBarUI.java | 74 + .../javax/swing/plaf/metal/MetalRadioButtonUI.java | 74 + .../javax/swing/plaf/metal/MetalRootPaneUI.java | 74 + .../javax/swing/plaf/metal/MetalScrollBarUI.java | 146 + .../javax/swing/plaf/metal/MetalScrollPaneUI.java | 74 + .../javax/swing/plaf/metal/MetalSeparatorUI.java | 74 + .../javax/swing/plaf/metal/MetalSliderUI.java | 87 + .../swing/plaf/metal/MetalSplitPaneDivider.java | 84 + .../javax/swing/plaf/metal/MetalSplitPaneUI.java | 106 + .../javax/swing/plaf/metal/MetalTabbedPaneUI.java | 86 + .../javax/swing/plaf/metal/MetalTextFieldUI.java | 86 + .../javax/swing/plaf/metal/MetalTheme.java | 576 ++++ .../swing/plaf/metal/MetalToggleButtonUI.java | 74 + .../javax/swing/plaf/metal/MetalToolBarUI.java | 74 + .../javax/swing/plaf/metal/MetalToolTipUI.java | 74 + .../javax/swing/plaf/metal/MetalTreeUI.java | 86 + .../javax/swing/plaf/metal/MetalUtils.java | 87 + .../classpath/javax/swing/plaf/metal/package.html | 46 + libjava/classpath/javax/swing/plaf/package.html | 47 + .../javax/swing/table/AbstractTableModel.java | 301 ++ .../swing/table/DefaultTableCellRenderer.java | 234 ++ .../javax/swing/table/DefaultTableColumnModel.java | 563 ++++ .../javax/swing/table/DefaultTableModel.java | 588 ++++ .../classpath/javax/swing/table/JTableHeader.java | 668 +++++ .../javax/swing/table/TableCellEditor.java | 65 + .../javax/swing/table/TableCellRenderer.java | 66 + .../classpath/javax/swing/table/TableColumn.java | 573 ++++ .../javax/swing/table/TableColumnModel.java | 187 ++ .../classpath/javax/swing/table/TableModel.java | 134 + libjava/classpath/javax/swing/table/package.html | 47 + .../javax/swing/text/AbstractDocument.java | 912 ++++++ .../classpath/javax/swing/text/AttributeSet.java | 72 + .../javax/swing/text/BadLocationException.java | 65 + libjava/classpath/javax/swing/text/Caret.java | 81 + .../javax/swing/text/ChangedCharSetException.java | 100 + .../classpath/javax/swing/text/ComponentView.java | 103 + .../classpath/javax/swing/text/DateFormatter.java | 85 + .../classpath/javax/swing/text/DefaultCaret.java | 315 ++ .../javax/swing/text/DefaultEditorKit.java | 418 +++ .../javax/swing/text/DefaultFormatter.java | 429 +++ .../javax/swing/text/DefaultHighlighter.java | 257 ++ .../javax/swing/text/DefaultStyledDocument.java | 202 ++ libjava/classpath/javax/swing/text/Document.java | 221 ++ .../classpath/javax/swing/text/DocumentFilter.java | 83 + libjava/classpath/javax/swing/text/EditorKit.java | 96 + libjava/classpath/javax/swing/text/Element.java | 54 + libjava/classpath/javax/swing/text/FieldView.java | 176 ++ libjava/classpath/javax/swing/text/GapContent.java | 356 +++ .../classpath/javax/swing/text/Highlighter.java | 79 + .../javax/swing/text/InternationalFormatter.java | 354 +++ .../classpath/javax/swing/text/JTextComponent.java | 1674 +++++++++++ libjava/classpath/javax/swing/text/Keymap.java | 60 + .../javax/swing/text/LayeredHighlighter.java | 57 + .../javax/swing/text/MutableAttributeSet.java | 85 + .../javax/swing/text/NavigationFilter.java | 71 + .../classpath/javax/swing/text/PasswordView.java | 170 ++ .../classpath/javax/swing/text/PlainDocument.java | 166 ++ libjava/classpath/javax/swing/text/PlainView.java | 241 ++ libjava/classpath/javax/swing/text/Position.java | 62 + libjava/classpath/javax/swing/text/Segment.java | 176 ++ .../javax/swing/text/SimpleAttributeSet.java | 193 ++ .../classpath/javax/swing/text/StringContent.java | 307 ++ libjava/classpath/javax/swing/text/Style.java | 64 + .../classpath/javax/swing/text/StyleConstants.java | 443 +++ .../classpath/javax/swing/text/StyleContext.java | 730 +++++ .../classpath/javax/swing/text/StyledDocument.java | 145 + .../javax/swing/text/StyledEditorKit.java | 503 ++++ .../classpath/javax/swing/text/TabExpander.java | 43 + libjava/classpath/javax/swing/text/TabSet.java | 102 + libjava/classpath/javax/swing/text/TabStop.java | 133 + .../classpath/javax/swing/text/TabableView.java | 44 + libjava/classpath/javax/swing/text/TextAction.java | 111 + libjava/classpath/javax/swing/text/Utilities.java | 198 ++ libjava/classpath/javax/swing/text/View.java | 463 +++ .../classpath/javax/swing/text/ViewFactory.java | 50 + libjava/classpath/javax/swing/text/html/HTML.java | 1309 +++++++++ .../javax/swing/text/html/HTMLDocument.java | 53 + .../javax/swing/text/html/HTMLEditorKit.java | 249 ++ .../swing/text/html/HTMLFrameHyperlinkEvent.java | 132 + .../classpath/javax/swing/text/html/package.html | 50 + .../swing/text/html/parser/AttributeList.java | 294 ++ .../javax/swing/text/html/parser/ContentModel.java | 218 ++ .../javax/swing/text/html/parser/DTD.java | 607 ++++ .../javax/swing/text/html/parser/DTDConstants.java | 290 ++ .../swing/text/html/parser/DocumentParser.java | 261 ++ .../javax/swing/text/html/parser/Element.java | 317 ++ .../javax/swing/text/html/parser/Entity.java | 185 ++ .../javax/swing/text/html/parser/Parser.java | 436 +++ .../swing/text/html/parser/ParserDelegator.java | 210 ++ .../javax/swing/text/html/parser/TagElement.java | 142 + .../javax/swing/text/html/parser/package.html | 50 + libjava/classpath/javax/swing/text/package.html | 46 + .../javax/swing/text/rtf/ControlWordToken.java | 86 + .../javax/swing/text/rtf/RTFEditorKit.java | 114 + .../javax/swing/text/rtf/RTFParseException.java | 65 + .../classpath/javax/swing/text/rtf/RTFParser.java | 195 ++ .../classpath/javax/swing/text/rtf/RTFScanner.java | 268 ++ .../classpath/javax/swing/text/rtf/TextToken.java | 65 + libjava/classpath/javax/swing/text/rtf/Token.java | 91 + .../javax/swing/tree/AbstractLayoutCache.java | 409 +++ .../javax/swing/tree/DefaultMutableTreeNode.java | 1112 +++++++ .../javax/swing/tree/DefaultTreeCellEditor.java | 516 ++++ .../javax/swing/tree/DefaultTreeCellRenderer.java | 591 ++++ .../javax/swing/tree/DefaultTreeModel.java | 455 +++ .../swing/tree/DefaultTreeSelectionModel.java | 754 +++++ .../javax/swing/tree/ExpandVetoException.java | 83 + .../javax/swing/tree/FixedHeightLayoutCache.java | 244 ++ .../javax/swing/tree/MutableTreeNode.java | 104 + libjava/classpath/javax/swing/tree/RowMapper.java | 54 + .../classpath/javax/swing/tree/TreeCellEditor.java | 65 + .../javax/swing/tree/TreeCellRenderer.java | 67 + libjava/classpath/javax/swing/tree/TreeModel.java | 109 + libjava/classpath/javax/swing/tree/TreeNode.java | 99 + libjava/classpath/javax/swing/tree/TreePath.java | 299 ++ .../javax/swing/tree/TreeSelectionModel.java | 84 + .../swing/tree/VariableHeightLayoutCache.java | 253 ++ libjava/classpath/javax/swing/tree/package.html | 47 + .../javax/swing/undo/AbstractUndoableEdit.java | 323 ++ .../javax/swing/undo/CannotRedoException.java | 56 + .../javax/swing/undo/CannotUndoException.java | 57 + .../classpath/javax/swing/undo/CompoundEdit.java | 400 +++ libjava/classpath/javax/swing/undo/StateEdit.java | 263 ++ .../classpath/javax/swing/undo/StateEditable.java | 112 + .../classpath/javax/swing/undo/UndoManager.java | 625 ++++ .../classpath/javax/swing/undo/UndoableEdit.java | 114 + .../javax/swing/undo/UndoableEditSupport.java | 271 ++ libjava/classpath/javax/swing/undo/package.html | 46 + 469 files changed, 141866 insertions(+) create mode 100644 libjava/classpath/javax/swing/AbstractAction.java create mode 100644 libjava/classpath/javax/swing/AbstractButton.java create mode 100644 libjava/classpath/javax/swing/AbstractCellEditor.java create mode 100644 libjava/classpath/javax/swing/AbstractListModel.java create mode 100644 libjava/classpath/javax/swing/AbstractSpinnerModel.java create mode 100644 libjava/classpath/javax/swing/Action.java create mode 100644 libjava/classpath/javax/swing/ActionMap.java create mode 100644 libjava/classpath/javax/swing/BorderFactory.java create mode 100644 libjava/classpath/javax/swing/BoundedRangeModel.java create mode 100644 libjava/classpath/javax/swing/Box.java create mode 100644 libjava/classpath/javax/swing/BoxLayout.java create mode 100644 libjava/classpath/javax/swing/ButtonGroup.java create mode 100644 libjava/classpath/javax/swing/ButtonModel.java create mode 100644 libjava/classpath/javax/swing/CellEditor.java create mode 100644 libjava/classpath/javax/swing/CellRendererPane.java create mode 100644 libjava/classpath/javax/swing/ComboBoxEditor.java create mode 100644 libjava/classpath/javax/swing/ComboBoxModel.java create mode 100644 libjava/classpath/javax/swing/ComponentInputMap.java create mode 100644 libjava/classpath/javax/swing/DebugGraphics.java create mode 100644 libjava/classpath/javax/swing/DefaultBoundedRangeModel.java create mode 100644 libjava/classpath/javax/swing/DefaultButtonModel.java create mode 100644 libjava/classpath/javax/swing/DefaultCellEditor.java create mode 100644 libjava/classpath/javax/swing/DefaultComboBoxModel.java create mode 100644 libjava/classpath/javax/swing/DefaultDesktopManager.java create mode 100644 libjava/classpath/javax/swing/DefaultFocusManager.java create mode 100644 libjava/classpath/javax/swing/DefaultListCellRenderer.java create mode 100644 libjava/classpath/javax/swing/DefaultListModel.java create mode 100644 libjava/classpath/javax/swing/DefaultListSelectionModel.java create mode 100644 libjava/classpath/javax/swing/DefaultSingleSelectionModel.java create mode 100644 libjava/classpath/javax/swing/DesktopManager.java create mode 100644 libjava/classpath/javax/swing/FocusManager.java create mode 100644 libjava/classpath/javax/swing/GrayFilter.java create mode 100644 libjava/classpath/javax/swing/Icon.java create mode 100644 libjava/classpath/javax/swing/ImageIcon.java create mode 100644 libjava/classpath/javax/swing/InputMap.java create mode 100644 libjava/classpath/javax/swing/InputVerifier.java create mode 100644 libjava/classpath/javax/swing/InternalFrameFocusTraversalPolicy.java create mode 100644 libjava/classpath/javax/swing/JApplet.java create mode 100644 libjava/classpath/javax/swing/JButton.java create mode 100644 libjava/classpath/javax/swing/JCheckBox.java create mode 100644 libjava/classpath/javax/swing/JCheckBoxMenuItem.java create mode 100644 libjava/classpath/javax/swing/JColorChooser.java create mode 100644 libjava/classpath/javax/swing/JComboBox.java create mode 100644 libjava/classpath/javax/swing/JComponent.java create mode 100644 libjava/classpath/javax/swing/JDesktopPane.java create mode 100644 libjava/classpath/javax/swing/JDialog.java create mode 100644 libjava/classpath/javax/swing/JEditorPane.java create mode 100644 libjava/classpath/javax/swing/JFileChooser.java create mode 100644 libjava/classpath/javax/swing/JFormattedTextField.java create mode 100644 libjava/classpath/javax/swing/JFrame.java create mode 100644 libjava/classpath/javax/swing/JInternalFrame.java create mode 100644 libjava/classpath/javax/swing/JLabel.java create mode 100644 libjava/classpath/javax/swing/JLayeredPane.java create mode 100644 libjava/classpath/javax/swing/JList.java create mode 100644 libjava/classpath/javax/swing/JMenu.java create mode 100644 libjava/classpath/javax/swing/JMenuBar.java create mode 100644 libjava/classpath/javax/swing/JMenuItem.java create mode 100644 libjava/classpath/javax/swing/JOptionPane.java create mode 100644 libjava/classpath/javax/swing/JPanel.java create mode 100644 libjava/classpath/javax/swing/JPasswordField.java create mode 100644 libjava/classpath/javax/swing/JPopupMenu.java create mode 100644 libjava/classpath/javax/swing/JProgressBar.java create mode 100644 libjava/classpath/javax/swing/JRadioButton.java create mode 100644 libjava/classpath/javax/swing/JRadioButtonMenuItem.java create mode 100644 libjava/classpath/javax/swing/JRootPane.java create mode 100644 libjava/classpath/javax/swing/JScrollBar.java create mode 100644 libjava/classpath/javax/swing/JScrollPane.java create mode 100644 libjava/classpath/javax/swing/JSeparator.java create mode 100644 libjava/classpath/javax/swing/JSlider.java create mode 100644 libjava/classpath/javax/swing/JSpinner.java create mode 100644 libjava/classpath/javax/swing/JSplitPane.java create mode 100644 libjava/classpath/javax/swing/JTabbedPane.java create mode 100644 libjava/classpath/javax/swing/JTable.java create mode 100644 libjava/classpath/javax/swing/JTextArea.java create mode 100644 libjava/classpath/javax/swing/JTextField.java create mode 100644 libjava/classpath/javax/swing/JTextPane.java create mode 100644 libjava/classpath/javax/swing/JToggleButton.java create mode 100644 libjava/classpath/javax/swing/JToolBar.java create mode 100644 libjava/classpath/javax/swing/JToolTip.java create mode 100644 libjava/classpath/javax/swing/JTree.java create mode 100644 libjava/classpath/javax/swing/JViewport.java create mode 100644 libjava/classpath/javax/swing/JWindow.java create mode 100644 libjava/classpath/javax/swing/KeyStroke.java create mode 100644 libjava/classpath/javax/swing/LayoutFocusTraversalPolicy.java create mode 100644 libjava/classpath/javax/swing/ListCellRenderer.java create mode 100644 libjava/classpath/javax/swing/ListModel.java create mode 100644 libjava/classpath/javax/swing/ListSelectionModel.java create mode 100644 libjava/classpath/javax/swing/LookAndFeel.java create mode 100644 libjava/classpath/javax/swing/MenuElement.java create mode 100644 libjava/classpath/javax/swing/MenuSelectionManager.java create mode 100644 libjava/classpath/javax/swing/MutableComboBoxModel.java create mode 100644 libjava/classpath/javax/swing/OverlayLayout.java create mode 100644 libjava/classpath/javax/swing/Popup.java create mode 100644 libjava/classpath/javax/swing/PopupFactory.java create mode 100644 libjava/classpath/javax/swing/ProgressMonitor.java create mode 100644 libjava/classpath/javax/swing/ProgressMonitorInputStream.java create mode 100644 libjava/classpath/javax/swing/Renderer.java create mode 100644 libjava/classpath/javax/swing/RepaintManager.java create mode 100644 libjava/classpath/javax/swing/RootPaneContainer.java create mode 100644 libjava/classpath/javax/swing/ScrollPaneConstants.java create mode 100644 libjava/classpath/javax/swing/ScrollPaneLayout.java create mode 100644 libjava/classpath/javax/swing/Scrollable.java create mode 100644 libjava/classpath/javax/swing/SingleSelectionModel.java create mode 100644 libjava/classpath/javax/swing/SizeRequirements.java create mode 100644 libjava/classpath/javax/swing/SizeSequence.java create mode 100644 libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java create mode 100644 libjava/classpath/javax/swing/SpinnerDateModel.java create mode 100644 libjava/classpath/javax/swing/SpinnerListModel.java create mode 100644 libjava/classpath/javax/swing/SpinnerModel.java create mode 100644 libjava/classpath/javax/swing/SpinnerNumberModel.java create mode 100644 libjava/classpath/javax/swing/Spring.java create mode 100644 libjava/classpath/javax/swing/SpringLayout.java create mode 100644 libjava/classpath/javax/swing/SwingConstants.java create mode 100644 libjava/classpath/javax/swing/SwingUtilities.java create mode 100644 libjava/classpath/javax/swing/Timer.java create mode 100644 libjava/classpath/javax/swing/ToolTipManager.java create mode 100644 libjava/classpath/javax/swing/TransferHandler.java create mode 100644 libjava/classpath/javax/swing/UIDefaults.java create mode 100644 libjava/classpath/javax/swing/UIManager.java create mode 100644 libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java create mode 100644 libjava/classpath/javax/swing/ViewportLayout.java create mode 100644 libjava/classpath/javax/swing/WindowConstants.java create mode 100644 libjava/classpath/javax/swing/border/AbstractBorder.java create mode 100644 libjava/classpath/javax/swing/border/BevelBorder.java create mode 100644 libjava/classpath/javax/swing/border/Border.java create mode 100644 libjava/classpath/javax/swing/border/CompoundBorder.java create mode 100644 libjava/classpath/javax/swing/border/EmptyBorder.java create mode 100644 libjava/classpath/javax/swing/border/EtchedBorder.java create mode 100644 libjava/classpath/javax/swing/border/LineBorder.java create mode 100644 libjava/classpath/javax/swing/border/MatteBorder.java create mode 100644 libjava/classpath/javax/swing/border/SoftBevelBorder.java create mode 100644 libjava/classpath/javax/swing/border/TitledBorder.java create mode 100644 libjava/classpath/javax/swing/border/doc-files/BevelBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/BevelBorder-2.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/BevelBorder-3.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/EmptyBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/EtchedBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/EtchedBorder-2.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/LineBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-2.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-3.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-4.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-5.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/MatteBorder-6.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-1.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-2.png create mode 100644 libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-3.png create mode 100644 libjava/classpath/javax/swing/border/package.html create mode 100644 libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java create mode 100644 libjava/classpath/javax/swing/colorchooser/ColorSelectionModel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/DefaultColorSelectionModel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/DefaultHSBChooserPanel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/DefaultPreviewPanel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/DefaultRGBChooserPanel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java create mode 100644 libjava/classpath/javax/swing/colorchooser/package.html create mode 100644 libjava/classpath/javax/swing/event/AncestorEvent.java create mode 100644 libjava/classpath/javax/swing/event/AncestorListener.java create mode 100644 libjava/classpath/javax/swing/event/CaretEvent.java create mode 100644 libjava/classpath/javax/swing/event/CaretListener.java create mode 100644 libjava/classpath/javax/swing/event/CellEditorListener.java create mode 100644 libjava/classpath/javax/swing/event/ChangeEvent.java create mode 100644 libjava/classpath/javax/swing/event/ChangeListener.java create mode 100644 libjava/classpath/javax/swing/event/DocumentEvent.java create mode 100644 libjava/classpath/javax/swing/event/DocumentListener.java create mode 100644 libjava/classpath/javax/swing/event/EventListenerList.java create mode 100644 libjava/classpath/javax/swing/event/HyperlinkEvent.java create mode 100644 libjava/classpath/javax/swing/event/HyperlinkListener.java create mode 100644 libjava/classpath/javax/swing/event/InternalFrameAdapter.java create mode 100644 libjava/classpath/javax/swing/event/InternalFrameEvent.java create mode 100644 libjava/classpath/javax/swing/event/InternalFrameListener.java create mode 100644 libjava/classpath/javax/swing/event/ListDataEvent.java create mode 100644 libjava/classpath/javax/swing/event/ListDataListener.java create mode 100644 libjava/classpath/javax/swing/event/ListSelectionEvent.java create mode 100644 libjava/classpath/javax/swing/event/ListSelectionListener.java create mode 100644 libjava/classpath/javax/swing/event/MenuDragMouseEvent.java create mode 100644 libjava/classpath/javax/swing/event/MenuDragMouseListener.java create mode 100644 libjava/classpath/javax/swing/event/MenuEvent.java create mode 100644 libjava/classpath/javax/swing/event/MenuKeyEvent.java create mode 100644 libjava/classpath/javax/swing/event/MenuKeyListener.java create mode 100644 libjava/classpath/javax/swing/event/MenuListener.java create mode 100644 libjava/classpath/javax/swing/event/MouseInputAdapter.java create mode 100644 libjava/classpath/javax/swing/event/MouseInputListener.java create mode 100644 libjava/classpath/javax/swing/event/PopupMenuEvent.java create mode 100644 libjava/classpath/javax/swing/event/PopupMenuListener.java create mode 100644 libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java create mode 100644 libjava/classpath/javax/swing/event/TableColumnModelEvent.java create mode 100644 libjava/classpath/javax/swing/event/TableColumnModelListener.java create mode 100644 libjava/classpath/javax/swing/event/TableModelEvent.java create mode 100644 libjava/classpath/javax/swing/event/TableModelListener.java create mode 100644 libjava/classpath/javax/swing/event/TreeExpansionEvent.java create mode 100644 libjava/classpath/javax/swing/event/TreeExpansionListener.java create mode 100644 libjava/classpath/javax/swing/event/TreeModelEvent.java create mode 100644 libjava/classpath/javax/swing/event/TreeModelListener.java create mode 100644 libjava/classpath/javax/swing/event/TreeSelectionEvent.java create mode 100644 libjava/classpath/javax/swing/event/TreeSelectionListener.java create mode 100644 libjava/classpath/javax/swing/event/TreeWillExpandListener.java create mode 100644 libjava/classpath/javax/swing/event/UndoableEditEvent.java create mode 100644 libjava/classpath/javax/swing/event/UndoableEditListener.java create mode 100644 libjava/classpath/javax/swing/event/package.html create mode 100644 libjava/classpath/javax/swing/filechooser/FileFilter.java create mode 100644 libjava/classpath/javax/swing/filechooser/FileSystemView.java create mode 100644 libjava/classpath/javax/swing/filechooser/FileView.java create mode 100644 libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java create mode 100644 libjava/classpath/javax/swing/filechooser/package.html create mode 100644 libjava/classpath/javax/swing/package.html create mode 100644 libjava/classpath/javax/swing/plaf/ActionMapUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/BorderUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/ButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ColorChooserUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ColorUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/ComboBoxUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/ComponentUI.java create mode 100644 libjava/classpath/javax/swing/plaf/DesktopIconUI.java create mode 100644 libjava/classpath/javax/swing/plaf/DesktopPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/DimensionUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/FileChooserUI.java create mode 100644 libjava/classpath/javax/swing/plaf/FontUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/IconUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/InputMapUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/InsetsUIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/InternalFrameUI.java create mode 100644 libjava/classpath/javax/swing/plaf/LabelUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ListUI.java create mode 100644 libjava/classpath/javax/swing/plaf/MenuBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/MenuItemUI.java create mode 100644 libjava/classpath/javax/swing/plaf/OptionPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/PanelUI.java create mode 100644 libjava/classpath/javax/swing/plaf/PopupMenuUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ProgressBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/RootPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ScrollBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ScrollPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/SeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/SliderUI.java create mode 100644 libjava/classpath/javax/swing/plaf/SpinnerUI.java create mode 100644 libjava/classpath/javax/swing/plaf/SplitPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/TabbedPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/TableHeaderUI.java create mode 100644 libjava/classpath/javax/swing/plaf/TableUI.java create mode 100644 libjava/classpath/javax/swing/plaf/TextUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ToolBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/ToolTipUI.java create mode 100644 libjava/classpath/javax/swing/plaf/TreeUI.java create mode 100644 libjava/classpath/javax/swing/plaf/UIResource.java create mode 100644 libjava/classpath/javax/swing/plaf/ViewportUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicBorders.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicListUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/ComboPopup.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png create mode 100644 libjava/classpath/javax/swing/plaf/basic/package.html create mode 100644 libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia create mode 100644 libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png create mode 100644 libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png create mode 100644 libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalBorders.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalTheme.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/MetalUtils.java create mode 100644 libjava/classpath/javax/swing/plaf/metal/package.html create mode 100644 libjava/classpath/javax/swing/plaf/package.html create mode 100644 libjava/classpath/javax/swing/table/AbstractTableModel.java create mode 100644 libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java create mode 100644 libjava/classpath/javax/swing/table/DefaultTableColumnModel.java create mode 100644 libjava/classpath/javax/swing/table/DefaultTableModel.java create mode 100644 libjava/classpath/javax/swing/table/JTableHeader.java create mode 100644 libjava/classpath/javax/swing/table/TableCellEditor.java create mode 100644 libjava/classpath/javax/swing/table/TableCellRenderer.java create mode 100644 libjava/classpath/javax/swing/table/TableColumn.java create mode 100644 libjava/classpath/javax/swing/table/TableColumnModel.java create mode 100644 libjava/classpath/javax/swing/table/TableModel.java create mode 100644 libjava/classpath/javax/swing/table/package.html create mode 100644 libjava/classpath/javax/swing/text/AbstractDocument.java create mode 100644 libjava/classpath/javax/swing/text/AttributeSet.java create mode 100644 libjava/classpath/javax/swing/text/BadLocationException.java create mode 100644 libjava/classpath/javax/swing/text/Caret.java create mode 100644 libjava/classpath/javax/swing/text/ChangedCharSetException.java create mode 100644 libjava/classpath/javax/swing/text/ComponentView.java create mode 100644 libjava/classpath/javax/swing/text/DateFormatter.java create mode 100644 libjava/classpath/javax/swing/text/DefaultCaret.java create mode 100644 libjava/classpath/javax/swing/text/DefaultEditorKit.java create mode 100644 libjava/classpath/javax/swing/text/DefaultFormatter.java create mode 100644 libjava/classpath/javax/swing/text/DefaultHighlighter.java create mode 100644 libjava/classpath/javax/swing/text/DefaultStyledDocument.java create mode 100644 libjava/classpath/javax/swing/text/Document.java create mode 100644 libjava/classpath/javax/swing/text/DocumentFilter.java create mode 100644 libjava/classpath/javax/swing/text/EditorKit.java create mode 100644 libjava/classpath/javax/swing/text/Element.java create mode 100644 libjava/classpath/javax/swing/text/FieldView.java create mode 100644 libjava/classpath/javax/swing/text/GapContent.java create mode 100644 libjava/classpath/javax/swing/text/Highlighter.java create mode 100644 libjava/classpath/javax/swing/text/InternationalFormatter.java create mode 100644 libjava/classpath/javax/swing/text/JTextComponent.java create mode 100644 libjava/classpath/javax/swing/text/Keymap.java create mode 100644 libjava/classpath/javax/swing/text/LayeredHighlighter.java create mode 100644 libjava/classpath/javax/swing/text/MutableAttributeSet.java create mode 100644 libjava/classpath/javax/swing/text/NavigationFilter.java create mode 100644 libjava/classpath/javax/swing/text/PasswordView.java create mode 100644 libjava/classpath/javax/swing/text/PlainDocument.java create mode 100644 libjava/classpath/javax/swing/text/PlainView.java create mode 100644 libjava/classpath/javax/swing/text/Position.java create mode 100644 libjava/classpath/javax/swing/text/Segment.java create mode 100644 libjava/classpath/javax/swing/text/SimpleAttributeSet.java create mode 100644 libjava/classpath/javax/swing/text/StringContent.java create mode 100644 libjava/classpath/javax/swing/text/Style.java create mode 100644 libjava/classpath/javax/swing/text/StyleConstants.java create mode 100644 libjava/classpath/javax/swing/text/StyleContext.java create mode 100644 libjava/classpath/javax/swing/text/StyledDocument.java create mode 100644 libjava/classpath/javax/swing/text/StyledEditorKit.java create mode 100644 libjava/classpath/javax/swing/text/TabExpander.java create mode 100644 libjava/classpath/javax/swing/text/TabSet.java create mode 100644 libjava/classpath/javax/swing/text/TabStop.java create mode 100644 libjava/classpath/javax/swing/text/TabableView.java create mode 100644 libjava/classpath/javax/swing/text/TextAction.java create mode 100644 libjava/classpath/javax/swing/text/Utilities.java create mode 100644 libjava/classpath/javax/swing/text/View.java create mode 100644 libjava/classpath/javax/swing/text/ViewFactory.java create mode 100644 libjava/classpath/javax/swing/text/html/HTML.java create mode 100644 libjava/classpath/javax/swing/text/html/HTMLDocument.java create mode 100644 libjava/classpath/javax/swing/text/html/HTMLEditorKit.java create mode 100644 libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java create mode 100644 libjava/classpath/javax/swing/text/html/package.html create mode 100644 libjava/classpath/javax/swing/text/html/parser/AttributeList.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/ContentModel.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/DTD.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/DTDConstants.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/DocumentParser.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/Element.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/Entity.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/Parser.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/ParserDelegator.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/TagElement.java create mode 100644 libjava/classpath/javax/swing/text/html/parser/package.html create mode 100644 libjava/classpath/javax/swing/text/package.html create mode 100644 libjava/classpath/javax/swing/text/rtf/ControlWordToken.java create mode 100644 libjava/classpath/javax/swing/text/rtf/RTFEditorKit.java create mode 100644 libjava/classpath/javax/swing/text/rtf/RTFParseException.java create mode 100644 libjava/classpath/javax/swing/text/rtf/RTFParser.java create mode 100644 libjava/classpath/javax/swing/text/rtf/RTFScanner.java create mode 100644 libjava/classpath/javax/swing/text/rtf/TextToken.java create mode 100644 libjava/classpath/javax/swing/text/rtf/Token.java create mode 100644 libjava/classpath/javax/swing/tree/AbstractLayoutCache.java create mode 100644 libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java create mode 100644 libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java create mode 100644 libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java create mode 100644 libjava/classpath/javax/swing/tree/DefaultTreeModel.java create mode 100644 libjava/classpath/javax/swing/tree/DefaultTreeSelectionModel.java create mode 100644 libjava/classpath/javax/swing/tree/ExpandVetoException.java create mode 100644 libjava/classpath/javax/swing/tree/FixedHeightLayoutCache.java create mode 100644 libjava/classpath/javax/swing/tree/MutableTreeNode.java create mode 100644 libjava/classpath/javax/swing/tree/RowMapper.java create mode 100644 libjava/classpath/javax/swing/tree/TreeCellEditor.java create mode 100644 libjava/classpath/javax/swing/tree/TreeCellRenderer.java create mode 100644 libjava/classpath/javax/swing/tree/TreeModel.java create mode 100644 libjava/classpath/javax/swing/tree/TreeNode.java create mode 100644 libjava/classpath/javax/swing/tree/TreePath.java create mode 100644 libjava/classpath/javax/swing/tree/TreeSelectionModel.java create mode 100644 libjava/classpath/javax/swing/tree/VariableHeightLayoutCache.java create mode 100644 libjava/classpath/javax/swing/tree/package.html create mode 100644 libjava/classpath/javax/swing/undo/AbstractUndoableEdit.java create mode 100644 libjava/classpath/javax/swing/undo/CannotRedoException.java create mode 100644 libjava/classpath/javax/swing/undo/CannotUndoException.java create mode 100644 libjava/classpath/javax/swing/undo/CompoundEdit.java create mode 100644 libjava/classpath/javax/swing/undo/StateEdit.java create mode 100644 libjava/classpath/javax/swing/undo/StateEditable.java create mode 100644 libjava/classpath/javax/swing/undo/UndoManager.java create mode 100644 libjava/classpath/javax/swing/undo/UndoableEdit.java create mode 100644 libjava/classpath/javax/swing/undo/UndoableEditSupport.java create mode 100644 libjava/classpath/javax/swing/undo/package.html (limited to 'libjava/classpath/javax/swing') diff --git a/libjava/classpath/javax/swing/AbstractAction.java b/libjava/classpath/javax/swing/AbstractAction.java new file mode 100644 index 0000000..6bb42339 --- /dev/null +++ b/libjava/classpath/javax/swing/AbstractAction.java @@ -0,0 +1,278 @@ +/* AbstractAction.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; + +import javax.swing.event.SwingPropertyChangeSupport; + +/** + * A base class for implementing the {@link Action} interface. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class AbstractAction + implements Action, Cloneable, Serializable +{ + private static final long serialVersionUID = -6803159439231523484L; + + /** + * A flag that indicates whether or not the action is enabled. + */ + protected boolean enabled = true; + + /** + * Provides support for property change event notification. + */ + protected SwingPropertyChangeSupport changeSupport = + new SwingPropertyChangeSupport(this); + + /** + * store + */ + private transient HashMap store = new HashMap(); + + /** + * Creates a new action with an empty string for the name. All other + * properties are initialised to null + */ + public AbstractAction() + { + this(""); // TODO: default name + } + + /** + * Creates a new action with the specified name. All other properties are + * initialised to null. + * + * @param name the name (null permitted). + */ + public AbstractAction(String name) + { + this(name, null); // TODO: default icon?? + } + + /** + * Creates a new action with the specified name and icon. All other + * properties are initialised to null. + * + * @param name the name (null permitted). + * @param icon the icon (null permitted). + */ + public AbstractAction(String name, Icon icon) + { + putValue(NAME, name); + putValue(SMALL_ICON, icon); + } + + /** + * readObject + * + * @param stream the stream to read from + * + * @exception ClassNotFoundException TODO + * @exception IOException if an error occurs + */ + private void readObject(ObjectInputStream stream) + throws ClassNotFoundException, IOException + { + // TODO + } + + /** + * writeObject + * + * @param stream the stream to write to + * + * @exception IOException if an error occurs + */ + private void writeObject(ObjectOutputStream stream) throws IOException + { + // TODO + } + + /** + * clone + * + * @return Object + * + * @exception CloneNotSupportedException TODO + */ + protected Object clone() throws CloneNotSupportedException + { + AbstractAction copy = (AbstractAction) super.clone(); + copy.store = (HashMap) store.clone(); + return copy; + } + + /** + * Returns the value associated with the specified key. + * + * @param key the key (not null). + * + * @return The value associated with the specified key, or + * null if the key is not found. + */ + public Object getValue(String key) + { + return store.get(key); + } + + /** + * Sets the value associated with the specified key and sends a + * {@link java.beans.PropertyChangeEvent} to all registered listeners. + * The standard keys are: {@link #NAME}, {@link #SHORT_DESCRIPTION}, + * {@link #LONG_DESCRIPTION}, {@link #SMALL_ICON}, + * {@link #ACTION_COMMAND_KEY}, {@link #ACCELERATOR_KEY} and + * {@link #MNEMONIC_KEY}. Any existing value associated with the key will be + * overwritten. + * + * @param key the key (not null). + * @param value the value (null permitted). + */ + public void putValue(String key, Object value) + { + Object old = getValue(key); + if (old != value) + { + store.put(key, value); + firePropertyChange(key, old, value); + } + } + + /** + * Returns the flag that indicates whether or not the action is enabled. + * + * @return The flag. + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * Sets the flag that indicates whether or not the action is enabled and, if + * the value of the flag changed from the previous setting, sends a + * {@link java.beans.PropertyChangeEvent} to all registered listeners. + * + * @param enabled the new flag value. + */ + public void setEnabled(boolean enabled) + { + if (enabled != this.enabled) + { + this.enabled = enabled; + firePropertyChange("enabled", !this.enabled, this.enabled); + } + } + + /** + * getKeys + * @returns Object[] + */ + public Object[] getKeys() + { + return store.keySet().toArray(); + } + + /** + * This method fires a PropertyChangeEvent given the propertyName + * and the old and new values. + * + * @param propertyName The property that changed. + * @param oldValue The old value of the property. + * @param newValue The new value of the property. + */ + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * This convenience method fires a PropertyChangeEvent given + * the propertyName and the old and new values. + * + * @param propertyName The property that changed. + * @param oldValue The old value of the property. + * @param newValue The new value of the property. + */ + private void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) + { + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * addPropertyChangeListener + * + * @param listener the listener to add + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * removePropertyChangeListener + * + * @param listener the listener to remove + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns all registered listeners. + * + * @return array of listeners. + * + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return changeSupport.getPropertyChangeListeners(); + } +} diff --git a/libjava/classpath/javax/swing/AbstractButton.java b/libjava/classpath/javax/swing/AbstractButton.java new file mode 100644 index 0000000..0b5859b --- /dev/null +++ b/libjava/classpath/javax/swing/AbstractButton.java @@ -0,0 +1,2014 @@ +/* AbstractButton.java -- Provides basic button functionality. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.ItemSelectable; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.Serializable; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleIcon; +import javax.accessibility.AccessibleRelationSet; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleText; +import javax.accessibility.AccessibleValue; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ButtonUI; +import javax.swing.text.AttributeSet; + + +/** + *

The purpose of this class is to serve as a facade over a number of + * classes which collectively represent the semantics of a button: the + * button's model, its listeners, its action, and its look and feel. Some + * parts of a button's state are stored explicitly in this class, other + * parts are delegates to the model. Some methods related to buttons are + * implemented in this class, other methods pass through to the current + * model or look and feel.

+ * + *

Furthermore this class is supposed to serve as a base class for + * several kinds of buttons with similar but non-identical semantics: + * toggle buttons (radio buttons and checkboxes), simple "push" buttons, + * menu items.

+ * + *

Buttons have many properties, some of which are stored in this class + * while others are delegated to the button's model. The following properties + * are available:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Property Stored inBound?
action button no
actionCommand model no
borderPainted button yes
contentAreaFilled button yes
disabledIcon button yes
disabledSelectedIcon button yes
displayedMnemonicIndex button no
enabled model no
focusPainted button yes
horizontalAlignment button yes
horizontalTextPosition button yes
icon button yes
iconTextGap button no
label (same as text) model yes
margin button yes
multiClickThreshold button no
pressedIcon button yes
rolloverEnabled button yes
rolloverIcon button yes
rolloverSelectedIcon button yes
selected model no
selectedIcon button yes
selectedObjects button no
text model yes
UI button yes
verticalAlignment button yes
verticalTextPosition button yes
+ * + *

The various behavioral aspects of these properties follows:

+ * + * + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Graydon Hoare (graydon@redhat.com) + */ + +public abstract class AbstractButton extends JComponent + implements ItemSelectable, SwingConstants +{ + private static final long serialVersionUID = -937921345538462020L; + + /** + * An extension of ChangeListener to be serializable. + */ + protected class ButtonChangeListener + implements ChangeListener, Serializable + { + private static final long serialVersionUID = 1471056094226600578L; + + /** + * Notified when the target of the listener changes its state. + * + * @param ev the ChangeEvent describing the change + */ + public void stateChanged(ChangeEvent ev) + { + } + } + + /** The icon displayed by default. */ + Icon default_icon; + + /** The icon displayed when the button is pressed. */ + Icon pressed_icon; + + /** The icon displayed when the button is disabled. */ + Icon disabeldIcon; + + /** The icon displayed when the button is selected. */ + Icon selectedIcon; + + /** The icon displayed when the button is selected but disabled. */ + Icon disabledSelectedIcon; + + /** The icon displayed when the button is rolled over. */ + Icon rolloverIcon; + + /** The icon displayed when the button is selected and rolled over. */ + Icon rolloverSelectedIcon; + + /** The icon currently displayed. */ + Icon current_icon; + + /** The text displayed in the button. */ + String text; + + /** + * The gap between icon and text, if both icon and text are + * non-null. + */ + int iconTextGap; + + /** The vertical alignment of the button's text and icon. */ + int verticalAlignment; + + /** The horizontal alignment of the button's text and icon. */ + int horizontalAlignment; + + /** The horizontal position of the button's text relative to its icon. */ + int horizontalTextPosition; + + /** The vertical position of the button's text relative to its icon. */ + int verticalTextPosition; + + /** Whether or not the button paints its border. */ + boolean borderPainted; + + /** Whether or not the button paints its focus state. */ + boolean focusPainted; + + /** Whether or not the button fills its content area. */ + boolean contentAreaFilled; + + /** Whether rollover is enabled. */ + boolean rollOverEnabled; + + /** The action taken when the button is clicked. */ + Action action; + + /** The button's current state. */ + protected ButtonModel model; + + /** The margin between the button's border and its label. */ + Insets margin; + + /** + * A hint to the look and feel class, suggesting which character in the + * button's label should be underlined when drawing the label. + */ + int mnemonicIndex; + + /** Listener the button uses to receive ActionEvents from its model. */ + protected ActionListener actionListener; + + /** Listener the button uses to receive ItemEvents from its model. */ + protected ItemListener itemListener; + + /** Listener the button uses to receive ChangeEvents from its model. */ + protected ChangeListener changeListener; + + /** + * The time in miliseconds in which clicks get coalesced into a single + * ActionEvent. + */ + long multiClickThreshhold; + + /** + * Listener the button uses to receive PropertyChangeEvents from its + * Action. + */ + PropertyChangeListener actionPropertyChangeListener; + + /** ChangeEvent that is fired to button's ChangeEventListeners */ + protected ChangeEvent changeEvent = new ChangeEvent(this); + + /** + * Fired in a PropertyChangeEvent when the "borderPainted" property changes. + */ + public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted"; + + /** + * Fired in a PropertyChangeEvent when the "contentAreaFilled" property + * changes. + */ + public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY = + "contentAreaFilled"; + + /** + * Fired in a PropertyChangeEvent when the "disabledIcon" property changes. + */ + public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon"; + + /** + * Fired in a PropertyChangeEvent when the "disabledSelectedIcon" property + * changes. + */ + public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = + "disabledSelectedIcon"; + + /** + * Fired in a PropertyChangeEvent when the "focusPainted" property changes. + */ + public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted"; + + /** + * Fired in a PropertyChangeEvent when the "horizontalAlignment" property + * changes. + */ + public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = + "horizontalAlignment"; + + /** + * Fired in a PropertyChangeEvent when the "horizontalTextPosition" property + * changes. + */ + public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = + "horizontalTextPosition"; + + /** + * Fired in a PropertyChangeEvent when the "icon" property changes. */ + public static final String ICON_CHANGED_PROPERTY = "icon"; + + /** Fired in a PropertyChangeEvent when the "margin" property changes. */ + public static final String MARGIN_CHANGED_PROPERTY = "margin"; + + /** Fired in a PropertyChangeEvent when the "mnemonic" property changes. */ + public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic"; + + /** Fired in a PropertyChangeEvent when the "model" property changes. */ + public static final String MODEL_CHANGED_PROPERTY = "model"; + + /** Fired in a PropertyChangeEvent when the "pressedIcon" property changes. */ + public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon"; + + /** + * Fired in a PropertyChangeEvent when the "rolloverEnabled" property + * changes. + */ + public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY = + "rolloverEnabled"; + + /** + * Fired in a PropertyChangeEvent when the "rolloverIcon" property changes. + */ + public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon"; + + /** + * Fired in a PropertyChangeEvent when the "rolloverSelectedIcon" property + * changes. + */ + public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = + "rolloverSelectedIcon"; + + /** + * Fired in a PropertyChangeEvent when the "selectedIcon" property changes. + */ + public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon"; + + /** Fired in a PropertyChangeEvent when the "text" property changes. */ + public static final String TEXT_CHANGED_PROPERTY = "text"; + + /** + * Fired in a PropertyChangeEvent when the "verticalAlignment" property + * changes. + */ + public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = + "verticalAlignment"; + + /** + * Fired in a PropertyChangeEvent when the "verticalTextPosition" property + * changes. + */ + public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = + "verticalTextPosition"; + + /** + * A Java Accessibility extension of the AbstractButton. + */ + protected abstract class AccessibleAbstractButton + extends AccessibleJComponent implements AccessibleAction, AccessibleValue, + AccessibleText + { + private static final long serialVersionUID = -5673062525319836790L; + + protected AccessibleAbstractButton() + { + } + + public AccessibleStateSet getAccessibleStateSet() + { + return null; // TODO + } + + public String getAccessibleName() + { + return null; // TODO + } + + public AccessibleIcon[] getAccessibleIcon() + { + return null; // TODO + } + + public AccessibleRelationSet getAccessibleRelationSet() + { + return null; // TODO + } + + public AccessibleAction getAccessibleAction() + { + return null; // TODO + } + + public AccessibleValue getAccessibleValue() + { + return null; // TODO + } + + public int getAccessibleActionCount() + { + return 0; // TODO + } + + public String getAccessibleActionDescription(int value0) + { + return null; // TODO + } + + public boolean doAccessibleAction(int value0) + { + return false; // TODO + } + + public Number getCurrentAccessibleValue() + { + return null; // TODO + } + + public boolean setCurrentAccessibleValue(Number value0) + { + return false; // TODO + } + + public Number getMinimumAccessibleValue() + { + return null; // TODO + } + + public Number getMaximumAccessibleValue() + { + return null; // TODO + } + + public AccessibleText getAccessibleText() + { + return null; // TODO + } + + public int getIndexAtPoint(Point value0) + { + return 0; // TODO + } + + public Rectangle getCharacterBounds(int value0) + { + return null; // TODO + } + + public int getCharCount() + { + return 0; // TODO + } + + public int getCaretPosition() + { + return 0; // TODO + } + + public String getAtIndex(int value0, int value1) + { + return null; // TODO + } + + public String getAfterIndex(int value0, int value1) + { + return null; // TODO + } + + public String getBeforeIndex(int value0, int value1) + { + return null; // TODO + } + + public AttributeSet getCharacterAttribute(int value0) + { + return null; // TODO + } + + public int getSelectionStart() + { + return 0; // TODO + } + + public int getSelectionEnd() + { + return 0; // TODO + } + + public String getSelectedText() + { + return null; // TODO + } + + private Rectangle getTextRectangle() + { + return null; // TODO + } + } + + /** + * Creates a new AbstractButton object. + */ + public AbstractButton() + { + init("", null); + updateUI(); + } + + /** + * Get the model the button is currently using. + * + * @return The current model + */ + public ButtonModel getModel() + { + return model; + } + + /** + * Set the model the button is currently using. This un-registers all + * listeners associated with the current model, and re-registers them + * with the new model. + * + * @param newModel The new model + */ + public void setModel(ButtonModel newModel) + { + if (newModel == model) + return; + + if (model != null) + { + model.removeActionListener(actionListener); + model.removeChangeListener(changeListener); + model.removeItemListener(itemListener); + } + ButtonModel old = model; + model = newModel; + if (model != null) + { + model.addActionListener(actionListener); + model.addChangeListener(changeListener); + model.addItemListener(itemListener); + } + firePropertyChange(MODEL_CHANGED_PROPERTY, old, model); + revalidate(); + repaint(); + } + + protected void init(String text, Icon icon) + { + // If text is null, we fall back to the empty + // string (which is set using AbstractButton's + // constructor). + // This way the behavior of the JDK is matched. + if(text != null) + this.text = text; + + 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); + } + + /** + *

Returns the action command string for this button's model.

+ * + *

If the action command was set to null, the button's + * text (label) is returned instead.

+ * + * @return The current action command string from the button's model + */ + public String getActionCommand() + { + String ac = model.getActionCommand(); + if (ac != null) + return ac; + else + return text; + } + + /** + * Sets the action command string for this button's model. + * + * @param actionCommand The new action command string to set in the button's + * model. + */ + public void setActionCommand(String actionCommand) + { + model.setActionCommand(actionCommand); + } + + /** + * Adds an ActionListener to the button's listener list. When the + * button's model is clicked it fires an ActionEvent, and these + * listeners will be called. + * + * @param l The new listener to add + */ + public void addActionListener(ActionListener l) + { + listenerList.add(ActionListener.class, l); + } + + /** + * Removes an ActionListener from the button's listener list. + * + * @param l The listener to remove + */ + public void removeActionListener(ActionListener l) + { + listenerList.remove(ActionListener.class, l); + } + + /** + * Returns all added ActionListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) listenerList.getListeners(ActionListener.class); + } + + /** + * Adds an ItemListener to the button's listener list. When the button's + * model changes state (between any of ARMED, ENABLED, PRESSED, ROLLOVER + * or SELECTED) it fires an ItemEvent, and these listeners will be + * called. + * + * @param l The new listener to add + */ + public void addItemListener(ItemListener l) + { + listenerList.add(ItemListener.class, l); + } + + /** + * Removes an ItemListener from the button's listener list. + * + * @param l The listener to remove + */ + public void removeItemListener(ItemListener l) + { + listenerList.remove(ItemListener.class, l); + } + + /** + * Returns all added ItemListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public ItemListener[] getItemListeners() + { + return (ItemListener[]) listenerList.getListeners(ItemListener.class); + } + + /** + * Adds a ChangeListener to the button's listener list. When the button's + * model changes any of its (non-bound) properties, these listeners will be + * called. + * + * @param l The new listener to add + */ + public void addChangeListener(ChangeListener l) + { + listenerList.add(ChangeListener.class, l); + } + + /** + * Removes a ChangeListener from the button's listener list. + * + * @param l The listener to remove + */ + public void removeChangeListener(ChangeListener l) + { + listenerList.remove(ChangeListener.class, l); + } + + /** + * Returns all added ChangeListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Calls {@link ItemListener.itemStateChanged} on each ItemListener in + * the button's listener list. + * + * @param e The event signifying that the button's model changed state + */ + protected void fireItemStateChanged(ItemEvent e) + { + e.setSource(this); + ItemListener[] listeners = getItemListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].itemStateChanged(e); + } + + /** + * Calls {@link ActionListener.actionPerformed} on each {@link + * ActionListener} in the button's listener list. + * + * @param e The event signifying that the button's model was clicked + */ + protected void fireActionPerformed(ActionEvent e) + { + // Dispatch a copy of the given ActionEvent in order to + // set the source and action command correctly. + ActionEvent ae = new ActionEvent( + this, + e.getID(), + getActionCommand(), + e.getWhen(), + e.getModifiers()); + + ActionListener[] listeners = getActionListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].actionPerformed(ae); + } + + /** + * Calls {@link ChangeEvent.stateChanged} on each {@link ChangeListener} + * in the button's listener list. + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].stateChanged(changeEvent); + } + + /** + * Get the current keyboard mnemonic value. This value corresponds to a + * single key code (one of the {@link java.awt.event.KeyEvent} VK_* + * codes) and is used to activate the button when pressed in conjunction + * with the "mouseless modifier" of the button's look and feel class, and + * when focus is in one of the button's ancestors. + * + * @return The button's current keyboard mnemonic + */ + public int getMnemonic() + { + return getModel().getMnemonic(); + } + + /** + * Set the current keyboard mnemonic value. This value corresponds to a + * single key code (one of the {@link java.awt.event.KeyEvent} VK_* + * codes) and is used to activate the button when pressed in conjunction + * with the "mouseless modifier" of the button's look and feel class, and + * when focus is in one of the button's ancestors. + * + * @param mne A new mnemonic to use for the button + */ + public void setMnemonic(char mne) + { + setMnemonic((int) mne); + } + + /** + * Set the current keyboard mnemonic value. This value corresponds to a + * single key code (one of the {@link java.awt.event.KeyEvent} VK_* + * codes) and is used to activate the button when pressed in conjunction + * with the "mouseless modifier" of the button's look and feel class, and + * when focus is in one of the button's ancestors. + * + * @param mne A new mnemonic to use for the button + */ + public void setMnemonic(int mne) + { + int old = getModel().getMnemonic(); + + if (old != mne) + { + getModel().setMnemonic(mne); + + if (text != null && !text.equals("")) + { + // Since lower case char = upper case char for + // mnemonic, we will convert both text and mnemonic + // to upper case before checking if mnemonic character occurs + // in the menu item text. + int upperCaseMne = Character.toUpperCase((char) mne); + String upperCaseText = text.toUpperCase(); + setDisplayedMnemonicIndex(upperCaseText.indexOf(upperCaseMne)); + } + + firePropertyChange(MNEMONIC_CHANGED_PROPERTY, old, mne); + revalidate(); + repaint(); + } + } + + /** + * Sets the button's mnemonic index. The mnemonic index is a hint to the + * look and feel class, suggesting which character in the button's label + * should be underlined when drawing the label. If the mnemonic index is + * -1, no mnemonic will be displayed. + * + * If no mnemonic index is set, the button will choose a mnemonic index + * by default, which will be the first occurrence of the mnemonic + * character in the button's text. + * + * @param index An offset into the "text" property of the button + * @throws IllegalArgumentException If index is not within the + * range of legal offsets for the "text" property of the button. + * @since 1.4 + */ + + public void setDisplayedMnemonicIndex(int index) + { + if (index < -1 || (text != null && index >= text.length())) + throw new IllegalArgumentException(); + + mnemonicIndex = index; + } + + /** + * Get the button's mnemonic index, which is an offset into the button's + * "text" property. The character specified by this offset should be + * underlined when the look and feel class draws this button. + * + * @return An index into the button's "text" property + */ + public int getDisplayedMnemonicIndex() + { + return mnemonicIndex; + } + + + /** + * Set the "rolloverEnabled" property. When rollover is enabled, and the + * look and feel supports it, the button will change its icon to + * rolloverIcon, when the mouse passes over it. + * + * @param r Whether or not to enable rollover icon changes + */ + public void setRolloverEnabled(boolean r) + { + if (rollOverEnabled != r) + { + rollOverEnabled = r; + firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, !r, r); + revalidate(); + repaint(); + } + } + + /** + * Returns whether or not rollover icon changes are enabled on the + * button. + * + * @return The state of the "rolloverEnabled" property + */ + public boolean isRolloverEnabled() + { + return rollOverEnabled; + } + + /** + * Set the value of the button's "selected" property. Selection is only + * meaningful for toggle-type buttons (check boxes, radio buttons). + * + * @param s New value for the property + */ + public void setSelected(boolean s) + { + getModel().setSelected(s); + } + + /** + * Get the value of the button's "selected" property. Selection is only + * meaningful for toggle-type buttons (check boxes, radio buttons). + * + * @return The value of the property + */ + public boolean isSelected() + { + return getModel().isSelected(); + } + + /** + * Enables or disables the button. A button will neither be selectable + * nor preform any actions unless it is enabled. + * + * @param b Whether or not to enable the button + */ + public void setEnabled(boolean b) + { + super.setEnabled(b); + getModel().setEnabled(b); + } + + /** + * Set the horizontal alignment of the button's text and icon. The + * alignment is a numeric constant from {@link SwingConstants}. It must + * be one of: RIGHT, LEFT, CENTER, + * LEADING or TRAILING. The default is + * RIGHT. + * + * @return The current horizontal alignment + */ + public int getHorizontalAlignment() + { + return horizontalAlignment; + } + + /** + * Set the horizontal alignment of the button's text and icon. The + * alignment is a numeric constant from {@link SwingConstants}. It must + * be one of: RIGHT, LEFT, CENTER, + * LEADING or TRAILING. The default is + * RIGHT. + * + * @param a The new horizontal alignment + * @throws IllegalArgumentException If alignment is not one of the legal + * constants. + */ + public void setHorizontalAlignment(int a) + { + if (horizontalAlignment == a) + return; + + int old = horizontalAlignment; + horizontalAlignment = a; + firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY, old, a); + revalidate(); + repaint(); + } + + /** + * Get the horizontal position of the button's text relative to its + * icon. The position is a numeric constant from {@link + * SwingConstants}. It must be one of: RIGHT, + * LEFT, CENTER, LEADING or + * TRAILING. The default is TRAILING. + * + * @return The current horizontal text position + */ + public int getHorizontalTextPosition() + { + return horizontalTextPosition; + } + + /** + * Set the horizontal position of the button's text relative to its + * icon. The position is a numeric constant from {@link + * SwingConstants}. It must be one of: RIGHT, + * LEFT, CENTER, LEADING or + * TRAILING. The default is TRAILING. + * + * @param t The new horizontal text position + * @throws IllegalArgumentException If position is not one of the legal + * constants. + */ + public void setHorizontalTextPosition(int t) + { + if (horizontalTextPosition == t) + return; + + int old = horizontalTextPosition; + horizontalTextPosition = t; + firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY, old, t); + revalidate(); + repaint(); + } + + /** + * Get the vertical alignment of the button's text and icon. The + * alignment is a numeric constant from {@link SwingConstants}. It must + * be one of: CENTER, TOP, or + * BOTTOM. The default is CENTER. + * + * @return The current vertical alignment + */ + public int getVerticalAlignment() + { + return verticalAlignment; + } + + /** + * Set the vertical alignment of the button's text and icon. The + * alignment is a numeric constant from {@link SwingConstants}. It must + * be one of: CENTER, TOP, or + * BOTTOM. The default is CENTER. + * + * @param a The new vertical alignment + * @throws IllegalArgumentException If alignment is not one of the legal + * constants. + */ + public void setVerticalAlignment(int a) + { + if (verticalAlignment == a) + return; + + int old = verticalAlignment; + verticalAlignment = a; + firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, old, a); + revalidate(); + repaint(); + } + + /** + * Get the vertical position of the button's text relative to its + * icon. The alignment is a numeric constant from {@link + * SwingConstants}. It must be one of: CENTER, + * TOP, or BOTTOM. The default is + * CENTER. + * + * @return The current vertical position + */ + public int getVerticalTextPosition() + { + return verticalTextPosition; + } + + /** + * Set the vertical position of the button's text relative to its + * icon. The alignment is a numeric constant from {@link + * SwingConstants}. It must be one of: CENTER, + * TOP, or BOTTOM. The default is + * CENTER. + * + * @param t The new vertical position + * @throws IllegalArgumentException If position is not one of the legal + * constants. + */ + public void setVerticalTextPosition(int t) + { + if (verticalTextPosition == t) + return; + + int old = verticalTextPosition; + verticalTextPosition = t; + firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, old, t); + revalidate(); + repaint(); + } + + /** + * Set the value of the "borderPainted" property. If set to + * false, the button's look and feel class should not paint + * a border for the button. The default is true. + * + * @return The current value of the property. + */ + public boolean isBorderPainted() + { + return borderPainted; + } + + /** + * Set the value of the "borderPainted" property. If set to + * false, the button's look and feel class should not paint + * a border for the button. The default is true. + * + * @param b The new value of the property. + */ + public void setBorderPainted(boolean b) + { + if (borderPainted == b) + return; + + boolean old = borderPainted; + borderPainted = b; + firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, old, b); + revalidate(); + repaint(); + } + + /** + * Get the value of the "action" property. + * + * @return The current value of the "action" property + */ + public Action getAction() + { + return action; + } + + /** + *

Set the button's "action" property, subscribing the new action to the + * button, as an ActionListener, if it is not already subscribed. The old + * Action, if it exists, is unsubscribed, and the button is unsubscribed + * from the old Action if it was previously subscribed as a + * PropertyChangeListener.

+ * + *

This method also configures several of the button's properties from + * the Action, by calling {@link configurePropertiesFromAction}, and + * subscribes the button to the Action as a PropertyChangeListener. + * Subsequent changes to the Action will thus reconfigure the button + * automatically.

+ * + * @param a The new value of the "action" property + */ + public void setAction(Action a) + { + if (action != null) + { + action.removePropertyChangeListener(actionPropertyChangeListener); + removeActionListener(action); + if (actionPropertyChangeListener != null) + { + action.removePropertyChangeListener(actionPropertyChangeListener); + actionPropertyChangeListener = null; + } + } + + Action old = action; + action = a; + configurePropertiesFromAction(action); + if (action != null) + { + actionPropertyChangeListener = createActionPropertyChangeListener(a); + action.addPropertyChangeListener(actionPropertyChangeListener); + addActionListener(action); + } + } + + /** + * Return the button's default "icon" property. + * + * @return The current default icon + */ + public Icon getIcon() + { + return default_icon; + } + + /** + * Set the button's default "icon" property. This icon is used as a basis + * for the pressed and disabled icons, if none are explicitly set. + * + * @param i The new default icon + */ + public void setIcon(Icon i) + { + if (default_icon == i) + return; + + Icon old = default_icon; + default_icon = i; + firePropertyChange(ICON_CHANGED_PROPERTY, old, i); + revalidate(); + repaint(); + } + + /** + * Return the button's "text" property. This property is synonymous with + * the "label" property. + * + * @return The current "text" property + */ + public String getText() + { + return text; + } + + /** + * Set the button's "label" property. This property is synonymous with the + * "text" property. + * + * @param label The new "label" property + * + * @deprecated use setText(text) + */ + public void setLabel(String label) + { + setText(label); + } + + /** + * Return the button's "label" property. This property is synonymous with + * the "text" property. + * + * @return The current "label" property + * + * @deprecated use getText() + */ + public String getLabel() + { + return getText(); + } + + /** + * Set the button's "text" property. This property is synonymous with the + * "label" property. + * + * @param t The new "text" property + */ + public void setText(String t) + { + if (text == t) + return; + + String old = text; + text = t; + firePropertyChange(TEXT_CHANGED_PROPERTY, old, t); + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #iconTextGap} property. + * + * @param i The new value of the property + */ + public void setIconTextGap(int i) + { + if (iconTextGap == i) + return; + + int old = iconTextGap; + iconTextGap = i; + fireStateChanged(); + revalidate(); + repaint(); + } + + /** + * Get the value of the {@link #iconTextGap} property. + * + * @return The current value of the property + */ + public int getIconTextGap() + { + return iconTextGap; + } + + /** + * Return the button's "margin" property, which is an {@link Insets} object + * describing the distance between the button's border and its text and + * icon. + * + * @return The current "margin" property + */ + public Insets getMargin() + { + return margin; + } + + /** + * Set the button's "margin" property, which is an {@link Insets} object + * describing the distance between the button's border and its text and + * icon. + * + * @param m The new "margin" property + */ + public void setMargin(Insets m) + { + if (margin == m) + return; + + Insets old = margin; + margin = m; + firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m); + revalidate(); + repaint(); + } + + /** + * Return the button's "pressedIcon" property. The look and feel class + * should paint this icon when the "pressed" property of the button's + * {@link ButtonModel} is true. This property may be + * null, in which case the default icon is used. + * + * @return The current "pressedIcon" property + */ + public Icon getPressedIcon() + { + return pressed_icon; + } + + /** + * Set the button's "pressedIcon" property. The look and feel class + * should paint this icon when the "pressed" property of the button's + * {@link ButtonModel} is true. This property may be + * null, in which case the default icon is used. + * + * @param pressedIcon The new "pressedIcon" property + */ + public void setPressedIcon(Icon pressedIcon) + { + if (pressed_icon == pressedIcon) + return; + + Icon old = pressed_icon; + pressed_icon = pressedIcon; + firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, old, pressed_icon); + revalidate(); + repaint(); + } + + /** + * Return the button's "disabledIcon" property. The look and feel class + * should paint this icon when the "enabled" property of the button's + * {@link ButtonModel} is false. This property may be + * null, in which case an icon is constructed, based on the + * default icon. + * + * @return The current "disabledIcon" property + */ + public Icon getDisabledIcon() + { + if (disabeldIcon == null && default_icon instanceof ImageIcon) + { + Image iconImage = ((ImageIcon) default_icon).getImage(); + Image grayImage = GrayFilter.createDisabledImage(iconImage); + disabeldIcon = new ImageIcon(grayImage); + } + + return disabeldIcon; + } + + /** + * Set the button's "disabledIcon" property. The look and feel class should + * paint this icon when the "enabled" property of the button's {@link + * ButtonModel} is false. This property may be + * null, in which case an icon is constructed, based on the + * default icon. + * + * @param disabledIcon The new "disabledIcon" property + */ + public void setDisabledIcon(Icon d) + { + disabeldIcon = d; + revalidate(); + repaint(); + } + + /** + * Return the button's "paintFocus" property. This property controls + * whether or not the look and feel class will paint a special indicator + * of focus state for the button. If it is false, the button still paints + * when focused, but no special decoration is painted to indicate the + * presence of focus. + * + * @return The current "paintFocus" property + */ + public boolean isFocusPainted() + { + return focusPainted; + } + + /** + * Set the button's "paintFocus" property. This property controls whether + * or not the look and feel class will paint a special indicator of focus + * state for the button. If it is false, the button still paints when + * focused, but no special decoration is painted to indicate the presence + * of focus. + * + * @param b The new "paintFocus" property + */ + public void setFocusPainted(boolean p) + { + if (focusPainted == p) + return; + + boolean old = focusPainted; + focusPainted = p; + firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, old, p); + revalidate(); + repaint(); + } + + /** + * Verifies that a particular key is one of the valid constants used for + * describing horizontal alignment and positioning. The valid constants + * are the following members of {@link SwingConstants}: + * RIGHT, LEFT, CENTER, + * LEADING or TRAILING. + * + * @param key The key to check + * @param exception A message to include in an IllegalArgumentException + * + * @return the value of key + * + * @throws IllegalArgumentException If key is not one of the valid constants + * + * @see setHorizontalTextPosition() + * @see setHorizontalAlignment() + */ + protected int checkHorizontalKey(int key, String exception) + { + switch (key) + { + case SwingConstants.RIGHT: + case SwingConstants.LEFT: + case SwingConstants.CENTER: + case SwingConstants.LEADING: + case SwingConstants.TRAILING: + break; + default: + throw new IllegalArgumentException(exception); + } + return key; + } + + /** + * Verifies that a particular key is one of the valid constants used for + * describing vertical alignment and positioning. The valid constants are + * the following members of {@link SwingConstants}: TOP, + * BOTTOM or CENTER. + * + * @param key The key to check + * @param exception A message to include in an IllegalArgumentException + * + * @return the value of key + * + * @throws IllegalArgumentException If key is not one of the valid constants + * + * @see setVerticalTextPosition() + * @see setVerticalAlignment() + */ + protected int checkVerticalKey(int key, String exception) + { + switch (key) + { + case SwingConstants.TOP: + case SwingConstants.BOTTOM: + case SwingConstants.CENTER: + break; + default: + throw new IllegalArgumentException(exception); + } + return key; + } + + /** + * Configure various properties of the button by reading properties + * of an {@link Action}. The mapping of properties is as follows: + * + * + * + * + * + * + * + * + * + * + * + *
Action keyed property AbstractButton property
NAME text
SMALL_ICON icon
SHORT_DESCRIPTION toolTipText
MNEMONIC_KEY mnemonic
ACTION_COMMAND_KEY actionCommand
+ * + *

In addition, this method always sets the button's "enabled" property to + * the value of the Action's "enabled" property.

+ * + *

If the provided Action is null, the text, icon, and + * toolTipText properties of the button are set to null, and + * the "enabled" property is set to true; the mnemonic and + * actionCommand properties are unchanged.

+ * + * @param a An Action to configure the button from + */ + protected void configurePropertiesFromAction(Action a) + { + if (a == null) + { + setText(null); + setIcon(null); + setEnabled(true); + setToolTipText(null); + } + else + { + setText((String) (a.getValue(Action.NAME))); + setIcon((Icon) (a.getValue(Action.SMALL_ICON))); + setEnabled(a.isEnabled()); + setToolTipText((String) (a.getValue(Action.SHORT_DESCRIPTION))); + if (a.getValue(Action.MNEMONIC_KEY) != null) + setMnemonic(((Integer) (a.getValue(Action.MNEMONIC_KEY))).intValue()); + String actionCommand = (String) (a.getValue(Action.ACTION_COMMAND_KEY)); + + // Set actionCommand to button's text by default if it is not specified + if (actionCommand != null) + setActionCommand((String) (a.getValue(Action.ACTION_COMMAND_KEY))); + else + setActionCommand(getText()); + } + } + + /** + *

A factory method which should return an {@link ActionListener} that + * propagates events from the button's {@link ButtonModel} to any of the + * button's ActionListeners. By default, this is an inner class which + * calls {@link AbstractButton.fireActionPerformed} with a modified copy + * of the incoming model {@link ActionEvent}.

+ * + *

The button calls this method during construction, stores the + * resulting ActionListener in its actionListener member + * field, and subscribes it to the button's model. If the button's model + * is changed, this listener is unsubscribed from the old model and + * subscribed to the new one.

+ * + * @return A new ActionListener + */ + protected ActionListener createActionListener() + { + return new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + AbstractButton.this.fireActionPerformed(e); + } + }; + } + + /** + *

A factory method which should return a {@link PropertyChangeListener} + * that accepts changes to the specified {@link Action} and reconfigure + * the {@link AbstractButton}, by default using the {@link + * configurePropertiesFromAction} method.

+ * + *

The button calls this method whenever a new Action is assigned to + * the button's "action" property, via {@link setAction}, and stores the + * resulting PropertyChangeListener in its + * actionPropertyChangeListener member field. The button + * then subscribes the listener to the button's new action. If the + * button's action is changed subsequently, the listener is unsubscribed + * from the old action and subscribed to the new one.

+ * + * @param a The Action which will be listened to, and which should be + * the same as the source of any PropertyChangeEvents received by the + * new listener returned from this method. + * + * @return A new PropertyChangeListener + */ + protected PropertyChangeListener createActionPropertyChangeListener(Action a) + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + Action act = (Action) (e.getSource()); + if (e.getPropertyName().equals("enabled")) + setEnabled(act.isEnabled()); + else if (e.getPropertyName().equals(Action.NAME)) + setText((String) (act.getValue(Action.NAME))); + else if (e.getPropertyName().equals(Action.SMALL_ICON)) + setIcon((Icon) (act.getValue(Action.SMALL_ICON))); + else if (e.getPropertyName().equals(Action.SHORT_DESCRIPTION)) + setToolTipText((String) (act.getValue(Action.SHORT_DESCRIPTION))); + else if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) + if (act.getValue(Action.MNEMONIC_KEY) != null) + setMnemonic(((Integer) (act.getValue(Action.MNEMONIC_KEY))) + .intValue()); + else if (e.getPropertyName().equals(Action.ACTION_COMMAND_KEY)) + setActionCommand((String) (act.getValue(Action.ACTION_COMMAND_KEY))); + } + }; + } + + /** + *

Factory method which creates a {@link ChangeListener}, used to + * subscribe to ChangeEvents from the button's model. Subclasses of + * AbstractButton may wish to override the listener used to subscribe to + * such ChangeEvents. By default, the listener just propagates the + * {@link ChangeEvent} to the button's ChangeListeners, via the {@link + * AbstractButton.fireStateChanged} method.

+ * + *

The button calls this method during construction, stores the + * resulting ChangeListener in its changeListener member + * field, and subscribes it to the button's model. If the button's model + * is changed, this listener is unsubscribed from the old model and + * subscribed to the new one.

+ * + * @return The new ChangeListener + */ + protected ChangeListener createChangeListener() + { + return new ChangeListener() + { + public void stateChanged(ChangeEvent e) + { + AbstractButton.this.fireStateChanged(); + AbstractButton.this.repaint(); + } + }; + } + + /** + *

Factory method which creates a {@link ItemListener}, used to + * subscribe to ItemEvents from the button's model. Subclasses of + * AbstractButton may wish to override the listener used to subscribe to + * such ItemEvents. By default, the listener just propagates the + * {@link ItemEvent} to the button's ItemListeners, via the {@link + * AbstractButton.fireItemStateChanged} method.

+ * + *

The button calls this method during construction, stores the + * resulting ItemListener in its changeListener member + * field, and subscribes it to the button's model. If the button's model + * is changed, this listener is unsubscribed from the old model and + * subscribed to the new one.

+ * + *

Note that ItemEvents are only generated from the button's model + * when the model's selected property changes. If you want to + * subscribe to other properties of the model, you must subscribe to + * ChangeEvents. + * + * @return The new ItemListener + */ + protected ItemListener createItemListener() + { + return new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + AbstractButton.this.fireItemStateChanged(e); + } + }; + } + + /** + * Programmatically perform a "click" on the button: arming, pressing, + * waiting, un-pressing, and disarming the model. + */ + public void doClick() + { + doClick(100); + } + + /** + * Programmatically perform a "click" on the button: arming, pressing, + * waiting, un-pressing, and disarming the model. + * + * @param pressTime The number of milliseconds to wait in the pressed state + */ + public void doClick(int pressTime) + { + getModel().setArmed(true); + getModel().setPressed(true); + try + { + java.lang.Thread.sleep(pressTime); + } + catch (java.lang.InterruptedException e) + { + // probably harmless + } + getModel().setPressed(false); + getModel().setArmed(false); + } + + /** + * Return the button's disabled selected icon. The look and feel class + * should paint this icon when the "enabled" property of the button's model + * is false and its "selected" property is + * true. This icon can be null, in which case + * it is synthesized from the button's selected icon. + * + * @return The current disabled selected icon + */ + public Icon getDisabledSelectedIcon() + { + return disabledSelectedIcon; + } + + /** + * Set the button's disabled selected icon. The look and feel class + * should paint this icon when the "enabled" property of the button's model + * is false and its "selected" property is + * true. This icon can be null, in which case + * it is synthesized from the button's selected icon. + * + * @param icon The new disabled selected icon + */ + public void setDisabledSelectedIcon(Icon icon) + { + if (disabledSelectedIcon == icon) + return; + + Icon old = disabledSelectedIcon; + disabledSelectedIcon = icon; + firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, old, icon); + revalidate(); + repaint(); + } + + /** + * Return the button's rollover icon. The look and feel class should + * paint this icon when the "rolloverEnabled" property of the button is + * true and the mouse rolls over the button. + * + * @return The current rollover icon + */ + public Icon getRolloverIcon() + { + return rolloverIcon; + } + + /** + * Set the button's rollover icon. The look and feel class should + * paint this icon when the "rolloverEnabled" property of the button is + * true and the mouse rolls over the button. + * + * @param rolloverIcon The new rollover icon + */ + public void setRolloverIcon(Icon r) + { + if (rolloverIcon == r) + return; + + Icon old = rolloverIcon; + rolloverIcon = r; + firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, old, rolloverIcon); + revalidate(); + repaint(); + } + + /** + * Return the button's rollover selected icon. The look and feel class + * should paint this icon when the "rolloverEnabled" property of the button + * is true, the "selected" property of the button's model is + * true, and the mouse rolls over the button. + * + * @return The current rollover selected icon + */ + public Icon getRolloverSelectedIcon() + { + return rolloverSelectedIcon; + } + + /** + * Set the button's rollover selected icon. The look and feel class + * should paint this icon when the "rolloverEnabled" property of the button + * is true, the "selected" property of the button's model is + * true, and the mouse rolls over the button. + * + * @param rolloverSelectedIcon The new rollover selected icon + */ + public void setRolloverSelectedIcon(Icon r) + { + if (rolloverSelectedIcon == r) + return; + + Icon old = rolloverSelectedIcon; + rolloverSelectedIcon = r; + firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, old, r); + revalidate(); + repaint(); + } + + /** + * Return the button's selected icon. The look and feel class should + * paint this icon when the "selected" property of the button's model is + * true, and either the "rolloverEnabled" property of the + * button is false or the mouse is not currently rolled + * over the button. + * + * @return The current selected icon + */ + public Icon getSelectedIcon() + { + return selectedIcon; + } + + /** + * Set the button's selected icon. The look and feel class should + * paint this icon when the "selected" property of the button's model is + * true, and either the "rolloverEnabled" property of the + * button is false or the mouse is not currently rolled + * over the button. + * + * @param selectedIcon The new selected icon + */ + public void setSelectedIcon(Icon s) + { + if (selectedIcon == s) + return; + + Icon old = selectedIcon; + selectedIcon = s; + firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, old, s); + revalidate(); + repaint(); + } + + /** + * Returns an single-element array containing the "text" property of the + * button if the "selected" property of the button's model is + * true, otherwise returns null. + * + * @return The button's "selected object" array + */ + public Object[] getSelectedObjects() + { + if (isSelected()) + { + Object[] objs = new Object[1]; + objs[0] = getText(); + return objs; + } + else + { + return null; + } + } + + /** + * Called when image data becomes available for one of the button's icons. + * + * @param img The image being updated + * @param infoflags One of the constant codes in {@link ImageObserver} used + * to describe updated portions of an image. + * @param x X coordinate of the region being updated + * @param y Y coordinate of the region being updated + * @param w Width of the region beign updated + * @param h Height of the region being updated + * + * @return true if img is equal to the button's current icon, + * otherwise false + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, + int h) + { + return current_icon == img; + } + + /** + * Returns the value of the button's "contentAreaFilled" property. This + * property indicates whether the area surrounding the text and icon of + * the button should be filled by the look and feel class. If this + * property is false, the look and feel class should leave + * the content area transparent. + * + * @return The current value of the "contentAreaFilled" property + */ + public boolean isContentAreaFilled() + { + return contentAreaFilled; + } + + /** + * Sets the value of the button's "contentAreaFilled" property. This + * property indicates whether the area surrounding the text and icon of + * the button should be filled by the look and feel class. If this + * property is false, the look and feel class should leave + * the content area transparent. + * + * @param b The new value of the "contentAreaFilled" property + */ + public void setContentAreaFilled(boolean b) + { + if (contentAreaFilled == b) + return; + + boolean old = contentAreaFilled; + contentAreaFilled = b; + firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, old, b); + // The JDK sets the opaque property to the value of the contentAreaFilled + // property, so should we do. + setOpaque(b); + } + + /** + * Paints the button's border, if the button's "borderPainted" property is + * true, by out calling to the button's look and feel class. + * + * @param g The graphics context used to paint the border + */ + protected void paintBorder(Graphics g) + { + if (isBorderPainted()) + super.paintBorder(g); + } + + /** + * Returns a string, used only for debugging, which identifies or somehow + * represents this button. The exact value is implementation-defined. + * + * @return A string representation of the button + */ + protected String paramString() + { + StringBuffer sb = new StringBuffer(); + sb.append(super.paramString()); + sb.append(",defaultIcon="); + if (getIcon() != null) + sb.append(getIcon()); + sb.append(",disabledIcon="); + if (getDisabledIcon() != null) + sb.append(getDisabledIcon()); + sb.append(",disabledSelectedIcon="); + if (getDisabledSelectedIcon() != null) + sb.append(getDisabledSelectedIcon()); + sb.append(",margin="); + if (getMargin() != null) + sb.append(getMargin()); + sb.append(",paintBorder=").append(isBorderPainted()); + sb.append(",paintFocus=").append(isFocusPainted()); + sb.append(",pressedIcon="); + if (getPressedIcon() != null) + sb.append(getPressedIcon()); + sb.append(",rolloverEnabled=").append(isRolloverEnabled()); + sb.append(",rolloverIcon="); + if (getRolloverIcon() != null) + sb.append(getRolloverIcon()); + sb.append(",rolloverSelected="); + if (getRolloverSelectedIcon() != null) + sb.append(getRolloverSelectedIcon()); + sb.append(",selectedIcon="); + if (getSelectedIcon() != null) + sb.append(getSelectedIcon()); + sb.append(",text="); + if (getText() != null) + sb.append(getText()); + return sb.toString(); + } + + /** + * Set the "UI" property of the button, which is a look and feel class + * responsible for handling the button's input events and painting it. + * + * @param ui The new "UI" property + */ + public void setUI(ButtonUI ui) + { + super.setUI(ui); + } + + /** + * Set the "UI" property of the button, which is a look and feel class + * responsible for handling the button's input events and painting it. + * + * @return The current "UI" property + */ + public ButtonUI getUI() + { + return (ButtonUI) ui; + } + + /** + * Set the "UI" property to a class constructed, via the {@link + * UIManager}, from the current look and feel. This should be overridden + * for each subclass of AbstractButton, to retrieve a suitable {@link + * ButtonUI} look and feel class. + */ + public void updateUI() + { + } + + /** + * Returns the current time in milliseconds in which clicks gets coalesced + * into a single ActionEvent. + * + * @return the time in milliseconds + * + * @since 1.4 + */ + public long getMultiClickThreshhold() + { + return multiClickThreshhold; + } + + /** + * Sets the time in milliseconds in which clicks gets coalesced into a single + * ActionEvent. + * + * @param threshhold the time in milliseconds + * + * @since 1.4 + */ + public void setMultiClickThreshhold(long threshhold) + { + if (threshhold < 0) + throw new IllegalArgumentException(); + + multiClickThreshhold = threshhold; + } +} diff --git a/libjava/classpath/javax/swing/AbstractCellEditor.java b/libjava/classpath/javax/swing/AbstractCellEditor.java new file mode 100644 index 0000000..86d3017 --- /dev/null +++ b/libjava/classpath/javax/swing/AbstractCellEditor.java @@ -0,0 +1,191 @@ +/* AbstractCellEditor.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.EventObject; + +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.EventListenerList; + +/** + * The abstract superclass for table and tree cells. This provides some + * common shared functionality. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class AbstractCellEditor + implements CellEditor, Serializable +{ + private static final long serialVersionUID = -1048006551406220959L; + + /** + * Our Swing event listeners. + */ + protected EventListenerList listenerList; + + /** + * The cached ChangeEvent. + */ + protected transient ChangeEvent changeEvent; + + /** + * Creates a new instance of AbstractCellEditor. + */ + public AbstractCellEditor() { + listenerList = new EventListenerList(); + changeEvent = new ChangeEvent(this); + } // AbstractCellEditor() + + /** + * Returns true if the cell is editable using + * event, false + * if it's not. The default behaviour is to return true. + * + * @param event an event + * + * @return true if the cell is editable using + * event, false if it's not + */ + public boolean isCellEditable(EventObject event) { + return true; + } // isCellEditable() + + /** + * Returns true if the editing cell should be selected, + * false otherwise. This is usually returning true, + * but in some special cases it might be useful not to switch cell selection + * when editing one cell. + * + * @param event an event + * + * @return true if the editing cell should be selected, + * false otherwise + */ + public boolean shouldSelectCell(EventObject event) { + return true; + } // shouldSelectCell() + + /** + * Stop editing the cell and accept any partial value that has been entered + * into the cell. + * + * @returns true if editing has been stopped successfully, + * falseotherwise + */ + public boolean stopCellEditing() { + fireEditingStopped(); + return true; + } // stopCellEditing() + + /** + * Stop editing the cell and do not accept any partial value that has + * been entered into the cell. + */ + public void cancelCellEditing() { + fireEditingCanceled(); + } // cancelCellEditing() + + /** + * Adds a CellEditorListener to the list of CellEditorListeners of this + * CellEditor. + * + * @param listener the CellEditorListener to add + */ + public void addCellEditorListener (CellEditorListener listener) + { + listenerList.add (CellEditorListener.class, listener); + } + + /** + * Removes the specified CellEditorListener from the list of the + * CellEditorListeners of this CellEditor. + * + * @param listener the CellEditorListener to remove + */ + public void removeCellEditorListener (CellEditorListener listener) + { + listenerList.remove (CellEditorListener.class, listener); + } + + /** + * Returns the list of CellEditorListeners that have been registered + * in this CellEditor. + * + * @return the list of CellEditorListeners that have been registered + * in this CellEditor + * + * @since 1.4 + */ + public CellEditorListener[] getCellEditorListeners() + { + return (CellEditorListener[]) listenerList.getListeners + (CellEditorListener.class); + } + + /** + * Notifies all registered listeners that the editing of the cell has has been + * stopped. + */ + protected void fireEditingStopped() + { + CellEditorListener[] listeners = getCellEditorListeners(); + + for (int index = 0; index < listeners.length; index++) + { + listeners[index].editingStopped(changeEvent); + } + } + + /** + * Notifies all registered listeners that the editing of the cell has + * has been canceled. + */ + protected void fireEditingCanceled() + { + CellEditorListener[] listeners = getCellEditorListeners(); + + for (int index = 0; index < listeners.length; index++) + { + listeners[index].editingCanceled(changeEvent); + } + } +} diff --git a/libjava/classpath/javax/swing/AbstractListModel.java b/libjava/classpath/javax/swing/AbstractListModel.java new file mode 100644 index 0000000..a924b73 --- /dev/null +++ b/libjava/classpath/javax/swing/AbstractListModel.java @@ -0,0 +1,179 @@ +/* AbstractListModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/** + * AbstractListModel + * + * @author Ronald Veldema + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class AbstractListModel implements ListModel, Serializable +{ + private static final long serialVersionUID = -3285184064379168730L; + + /** List of ListDataListeners called for each change to the list. */ + protected EventListenerList listenerList; + + public AbstractListModel() + { + listenerList = new EventListenerList(); + } + + /** + * Add a listener object to this model. The listener will be called + * any time the set of elements in the model is changed. + * + * @param listener The listener to add + */ + public void addListDataListener(ListDataListener listener) + { + listenerList.add(ListDataListener.class, listener); + } + + /** + * Add a listener object to this model. The listener will no longer be + * called when the set of elements in the model is changed. + * + * @param listener The listener to remove + */ + public void removeListDataListener(ListDataListener listener) + { + listenerList.remove(ListDataListener.class, listener); + } + + /** + * Call {@link ListDataListener#contentsChanged} on each element of the + * {@link listenerList} which is a {@link ListDataListener}. The event + * fired has type {@ListDataEvent.CONTENTS_CHANGED} and represents a + * change to the data elements in the range [startIndex, endIndex] + * inclusive. + * + * @param source The source of the change, typically this + * @param startIndex The index of the first element which changed + * @param endIndex The index of the last element which changed + */ + protected void fireContentsChanged(Object source, int startIndex, + int endIndex) + { + ListDataEvent event = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, + startIndex, endIndex); + ListDataListener[] listeners = getListDataListeners(); + + for (int index = 0; index < listeners.length; index++) + listeners[index].contentsChanged(event); + } + + /** + * Call {@link ListDataListener#intervalAdded} on each element of the + * {@link listenerList} which is a {@link ListDataListener}. The event + * fired has type {@ListDataEvent.INTERVAL_ADDED} and represents an + * addition of the data elements in the range [startIndex, endIndex] + * inclusive. + * + * @param source The source of the change, typically this + * @param startIndex The index of the first new element + * @param endIndex The index of the last new element + */ + protected void fireIntervalAdded(Object source, int startIndex, int endIndex) + { + ListDataEvent event = + new ListDataEvent(source, ListDataEvent.INTERVAL_ADDED, + startIndex, endIndex); + ListDataListener[] listeners = getListDataListeners(); + + for (int index = 0; index < listeners.length; index++) + listeners[index].intervalAdded(event); + } + + /** + * Call {@link ListDataListener#intervalRemoved} on each element of the + * {@link listenerList} which is a {@link ListDataListener}. The event + * fired has type {@ListDataEvent.INTERVAL_REMOVED} and represents a + * removal of the data elements in the range [startIndex, endIndex] + * inclusive. + * + * @param source The source of the change, typically this + * @param startIndex The index of the first element removed + * @param endIndex The index of the last element removed + */ + protected void fireIntervalRemoved(Object source, int startIndex, + int endIndex) + { + ListDataEvent event = + new ListDataEvent(source, ListDataEvent.INTERVAL_REMOVED, + startIndex, endIndex); + ListDataListener[] listeners = getListDataListeners(); + + for (int index = 0; index < listeners.length; index++) + listeners[index].intervalRemoved(event); + } + + /** + * Return the subset of {@link EventListener} objects found in this + * object's {@link listenerList} which are elements of the specified + * type. + * + * @param listenerType The type of listeners to select + * + * @return The set of listeners of the specified type + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * A synonym for getListeners(ListDataListener.class). + * + * @return The set of ListDataListeners found in the {@link listenerList} + */ + public ListDataListener[] getListDataListeners() + { + return (ListDataListener[]) getListeners(ListDataListener.class); + } +} diff --git a/libjava/classpath/javax/swing/AbstractSpinnerModel.java b/libjava/classpath/javax/swing/AbstractSpinnerModel.java new file mode 100644 index 0000000..05a9892 --- /dev/null +++ b/libjava/classpath/javax/swing/AbstractSpinnerModel.java @@ -0,0 +1,117 @@ +/* AbstractSpinnerModel.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.util.EventListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * AbstractSpinnerModel + * @author Ka-Hing Cheung + * @version 1.0 + */ +public abstract class AbstractSpinnerModel implements SpinnerModel +{ + private ChangeEvent changeEvent = new ChangeEvent(this); + + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Creates an AbstractSpinnerModel. + */ + public AbstractSpinnerModel() + { + } + + /** + * Adds a ChangeListener. + * + * @param listener the listener to add + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * Gets all the listeners that are of a particular type. + * + * @param c the type of listener + * @return the listeners that are of the specific type + */ + public EventListener[] getListeners(Class c) + { + return listenerList.getListeners(c); + } + + /** + * Gets all the ChangeListeners. + * + * @return all the ChangeListeners + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Remove a particular listener. + * + * @param listener the listener to remove + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * Fires a ChangeEvent to all the ChangeListeners + * added to this model + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for(int i = 0; i < listeners.length; ++i) + listeners[i].stateChanged(changeEvent); + } +} diff --git a/libjava/classpath/javax/swing/Action.java b/libjava/classpath/javax/swing/Action.java new file mode 100644 index 0000000..17168c3 --- /dev/null +++ b/libjava/classpath/javax/swing/Action.java @@ -0,0 +1,153 @@ +/* Action.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.event.ActionListener; +import java.beans.PropertyChangeListener; + +/** + * An action provides a convenient central point of control for some task + * that can be triggered by more than one control in a Swing user interface + * (for example, a menu item and a toolbar button). + * + * @see AbstractButton#setAction(Action) + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Andrew Selkirk + */ +public interface Action extends ActionListener { + + /** + * A key to access the default property for the action (this is not used). + */ + String DEFAULT = "Default"; + + /** + * A key to access the long description for the action. + */ + String LONG_DESCRIPTION = "LongDescription"; + + /** + * A key to access the name for the action. + */ + String NAME = "Name"; + + /** + * A key to access the short description for the action (the short + * description is typically used as the tool tip text). + */ + String SHORT_DESCRIPTION = "ShortDescription"; + + /** + * A key to access the icon for the action. + */ + String SMALL_ICON = "SmallIcon"; + + /** + * A key to access the {@link KeyStroke} used as the accelerator for the + * action. + */ + String ACCELERATOR_KEY = "AcceleratorKey"; + + /** + * A key to access the action command string for the action. + */ + String ACTION_COMMAND_KEY = "ActionCommandKey"; + + /** + * A key to access the mnemonic for the action. + */ + String MNEMONIC_KEY = "MnemonicKey"; + + /** + * Returns the value associated with the specified key. + * + * @param key the key (not null). + * + * @return The value associated with the specified key, or + * null if the key is not found. + */ + Object getValue(String key); + + /** + * Sets the value associated with the specified key and sends a + * {@link java.beans.PropertyChangeEvent} to all registered listeners. + * The standard keys are defined in this interface: {@link #NAME}, + * {@link #SHORT_DESCRIPTION}, {@link #LONG_DESCRIPTION}, + * {@link #SMALL_ICON}, {@link #ACTION_COMMAND_KEY}, + * {@link #ACCELERATOR_KEY} and {@link #MNEMONIC_KEY}. Any existing value + * associated with the key will be overwritten. + * + * @param key the key (not null). + * @param value the value (null permitted). + */ + void putValue(String key, Object value); + + /** + * Returns the flag that indicates whether or not this action is enabled. + * + * @return The flag. + */ + boolean isEnabled(); + + /** + * Sets the flag that indicates whether or not this action is enabled. If + * the value changes, a {@link java.beans.PropertyChangeEvent} is sent to + * all registered listeners. + * + * @param b the new value of the flag. + */ + void setEnabled(boolean b); + + /** + * Registers a listener to receive notification whenever one of the + * action's properties is modified. + * + * @param listener the listener. + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Deregisters a listener so that it no longer receives notification of + * changes to the action's properties. + * + * @param listener the listener. + */ + void removePropertyChangeListener(PropertyChangeListener listener); + +} // Action diff --git a/libjava/classpath/javax/swing/ActionMap.java b/libjava/classpath/javax/swing/ActionMap.java new file mode 100644 index 0000000..c609257 --- /dev/null +++ b/libjava/classpath/javax/swing/ActionMap.java @@ -0,0 +1,211 @@ +/* ActionMap.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +/** + * @author Andrew Selkirk + * @author Michael Koch + */ +public class ActionMap + implements Serializable +{ + private static final long serialVersionUID = -6277518704513986346L; + + /** + * actionMap + */ + private Map actionMap = new HashMap(); + + /** + * parent + */ + private ActionMap parent; + + /** + * Creates a new ActionMap instance. + */ + public ActionMap() + { + } + + /** + * Returns an action associated with an object. + * + * @param key the key of the enty + * + * @return the action associated with key, may be null + */ + public Action get(Object key) + { + Object result = actionMap.get(key); + + if (result == null && parent != null) + result = parent.get(key); + + return (Action) result; + } + + /** + * Puts a new Action into the ActionMap. + * If action is null an existing entry will be removed. + * + * @param key the key for the entry + * @param action the action. + */ + public void put(Object key, Action action) + { + if (action == null) + actionMap.remove(key); + else + actionMap.put(key, action); + } + + /** + * Remove an entry from the ActionMap. + * + * @param key the key of the entry to remove + */ + public void remove(Object key) + { + actionMap.remove(key); + } + + /** + * Returns the parent of this ActionMap. + * + * @return the parent, may be null. + */ + public ActionMap getParent() + { + return parent; + } + + /** + * Sets a parent for this ActionMap. + * + * @param parentMap the new parent + */ + public void setParent(ActionMap parentMap) + { + if (parentMap != this) + parent = parentMap; + } + + /** + * Returns the number of entries in this ActionMap. + * + * @return the number of entries + */ + public int size() + { + return actionMap.size(); + } + + /** + * Clears the ActionMap. + */ + public void clear() + { + actionMap.clear(); + } + + /** + * Returns all keys of entries in this ActionMap. + * + * @return an array of keys + */ + public Object[] keys() + { + return actionMap.keySet().toArray(); + } + + /** + * Returns all keys of entries in this ActionMap + * and all its parents. + * + * @return an array of keys + */ + public Object[] allKeys() + { + Set set = new HashSet(); + + if (parent != null) + set.addAll(Arrays.asList(parent.allKeys())); + + set.addAll(actionMap.keySet()); + return set.toArray(); + } + + /** + * writeObject + * + * @param stream the stream to write to + * + * @exception IOException If an error occurs + */ + private void writeObject(ObjectOutputStream stream) + throws IOException + { + // TODO + } + + /** + * readObject + * + * @param stream the stream to read from + * + * @exception ClassNotFoundException If the serialized class cannot be found + * @exception IOException If an error occurs + */ + private void readObject(ObjectInputStream stream) + throws ClassNotFoundException, IOException + { + // TODO + } +} diff --git a/libjava/classpath/javax/swing/BorderFactory.java b/libjava/classpath/javax/swing/BorderFactory.java new file mode 100644 index 0000000..b084b61 --- /dev/null +++ b/libjava/classpath/javax/swing/BorderFactory.java @@ -0,0 +1,451 @@ +/* BorderFactory.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Font; + +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.MatteBorder; +import javax.swing.border.TitledBorder; + +public class BorderFactory +{ + private BorderFactory() + { + // Do nothing. + } + + /** + * Creates a line border withe the specified color. + * + * @param color A color to use for the line. + * + * @return The Border object + */ + public static Border createLineBorder(Color color) + { + return null; + } + + /** + * Creates a line border withe the specified color and width. The width + * applies to all 4 sides of the border. To specify widths individually for + * the top, bottom, left, and right, use + * createMatteBorder(int,int,int,int,Color). + * + * @param color A color to use for the line. + * @param thickness An int specifying the width in pixels. + * + * @return The Border object + */ + public static Border createLineBorder(Color color, int thickness) + { + return new LineBorder(color, thickness); + } + + /** + * Created a border with a raised beveled edge, using brighter shades of + * the component's current background color for highlighting, and darker + * shading for shadows. (In a raised border, highlights are on top and + * shadows are underneath.) + * + * @return The Border object + */ + public static Border createRaisedBevelBorder() + { + return new BevelBorder(BevelBorder.RAISED); + } + + /** + * Created a border with a lowered beveled edge, using brighter shades of + * the component's current background color for highlighting, and darker + * shading for shadows. (In a lowered border, shadows are on top and + * highlights are underneath.) + * + * @return The Border object + */ + public static Border createLoweredBevelBorder() + { + return new BevelBorder(BevelBorder.LOWERED); + } + + /** + * Create a beveled border of the specified type, using brighter shades of + * the component's current background color for highlighting, and darker + * shading for shadows. (In a lowered border, shadows are on top and + * highlights are underneath.). + * + * @param type An int specifying either BevelBorder.LOWERED or + * BevelBorder.RAISED + * + * @return The Border object + */ + public static Border createBevelBorder(int type) + { + return new BevelBorder(type); + } + + /** + * Create a beveled border of the specified type, using the specified + * highlighting and shadowing. The outer edge of the highlighted area uses + * a brighter shade of the highlight color. The inner edge of the shadow + * area uses a brighter shade of the shadaw color. + * + * @param type An int specifying either BevelBorder.LOWERED or + * BevelBorder.RAISED + * @param highlight A Color object for highlights + * @param shadow A Color object for shadows + * + * @return The Border object + */ + public static Border createBevelBorder(int type, Color highlight, Color shadow) + { + return new BevelBorder(type, highlight, shadow); + } + + /** + * Create a beveled border of the specified type, using the specified colors + * for the inner and outer highlight and shadow areas. + * + * @param type An int specifying either BevelBorder.LOWERED or + * BevelBorder.RAISED + * @param highlightOuter A Color object for the outer edge of the + * highlight area + * @param highlightInner A Color object for the inner edge of the + * highlight area + * @param shadowOuter A Color object for the outer edge of the shadow area + * @param shadowInner A Color object for the inner edge of the shadow area + * + * @return The Border object + */ + public static Border createBevelBorder(int type, Color highlightOuter, + Color highlightInner, + Color shadowOuter, Color shadowInner) + { + return new BevelBorder(type, highlightOuter, highlightInner, shadowOuter, + shadowInner); + } + + /** + * Create a border with an "etched" look using the component's current + * background color for highlighting and shading. + * + * @return The Border object + */ + public static Border createEtchedBorder() + { + return new EtchedBorder(); + } + + /** + * Create a border with an "etched" look using the component's current + * background color for highlighting and shading. + * + * @return The Border object + */ + public static Border createEtchedBorder(int etchType) + { + return new EtchedBorder(etchType); + } + + /** + * Create a border with an "etched" look using the specified highlighting and + * shading colors. + * + * @param highlight A Color object for the border highlights + * @param shadow A Color object for the border shadows + * + * @return The Border object + */ + public static Border createEtchedBorder(Color highlight, Color shadow) + { + return new EtchedBorder(highlight, shadow); + } + + /** + * Create a border with an "etched" look using the specified highlighting and + * shading colors. + * + * @param highlight A Color object for the border highlights + * @param shadow A Color object for the border shadows + * + * @return The Border object + */ + public static Border createEtchedBorder(int etchType, Color highlight, + Color shadow) + { + return new EtchedBorder(etchType, highlight, shadow); + } + + /** + * Create a new title border specifying the text of the title, using the + * default border (etched), using the default text position (sitting on the + * top line) and default justification (left) and using the default font and + * text color determined by the current look and feel. + * + * @param title A String containing the text of the title + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(String title) + { + return new TitledBorder(title); + } + + /** + * Create a new title border with an empty title specifying the border + * object, using the default text position (sitting on the top line) and + * default justification (left) and using the default font, text color, + * and border determined by the current look and feel. (The Motif and Windows + * look and feels use an etched border; The Java look and feel use a + * gray border.) + * + * @param border The Border object to add the title to + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(Border border) + { + return new TitledBorder(border); + } + + /** + * Add a title to an existing border, specifying the text of the title, using + * the default positioning (sitting on the top line) and default + * justification (left) and using the default font and text color determined + * by the current look and feel. + * + * @param order The Border object to add the title to + * @param title A String containing the text of the title + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(Border border, String title) + { + return new TitledBorder(border, title); + } + + /** + * Add a title to an existing border, specifying the text of the title along + * with its positioning, using the default font and text color determined by + * the current look and feel. + * + * @param border The Border object to add the title to + * @param title A String containing the text of the title + * @param titleJustification An int specifying the left/right position of + * the title -- one of TitledBorder.LEFT, TitledBorder.CENTER, or + * TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION (left). + * @param titlePosition An int specifying the vertical position of the text + * in relation to the border -- one of: TitledBorder.ABOVE_TOP, + * TitledBorder.TOP (sitting on the top line), TitledBorder.BELOW_TOP, + * TitledBorder.ABOVE_BOTTOM, TitledBorder.BOTTOM (sitting on the bottom + * line), TitledBorder.BELOW_BOTTOM, or TitledBorder.DEFAULT_POSITION + * (top). + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(Border border, String title, + int titleJustification, + int titlePosition) + { + return new TitledBorder(border, title, titleJustification, titlePosition); + } + + /** + * Add a title to an existing border, specifying the text of the title along + * with its positioning and font, using the default text color determined by + * the current look and feel. + * + * @param border - the Border object to add the title to + * @param title - a String containing the text of the title + * @param titleJustification - an int specifying the left/right position of + * the title -- one of TitledBorder.LEFT, TitledBorder.CENTER, or + * TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION (left). + * @param titlePosition - an int specifying the vertical position of the + * text in relation to the border -- one of: TitledBorder.ABOVE_TOP, + * TitledBorder.TOP (sitting on the top line), TitledBorder.BELOW_TOP, + * TitledBorder.ABOVE_BOTTOM, TitledBorder.BOTTOM (sitting on the bottom + * line), TitledBorder.BELOW_BOTTOM, or TitledBorder.DEFAULT_POSITION (top). + * @param titleFont - a Font object specifying the title font + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(Border border, String title, + int titleJustification, + int titlePosition, + Font titleFont) + { + return new TitledBorder(border, title, titleJustification, titlePosition, + titleFont); + } + + /** + * Add a title to an existing border, specifying the text of the title along + * with its positioning, font, and color. + * + * @param border - the Border object to add the title to + * @param title - a String containing the text of the title + * @param titleJustification - an int specifying the left/right position of + * the title -- one of TitledBorder.LEFT, TitledBorder.CENTER, or + * TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION (left). + * @param titlePosition - an int specifying the vertical position of the text + * in relation to the border -- one of: TitledBorder.ABOVE_TOP, + * TitledBorder.TOP (sitting on the top line), TitledBorder.BELOW_TOP, + * TitledBorder.ABOVE_BOTTOM, TitledBorder.BOTTOM (sitting on the bottom + * line), TitledBorder.BELOW_BOTTOM, or TitledBorder.DEFAULT_POSITION (top). + * @param titleFont - a Font object specifying the title font + * @param titleColor - a Color object specifying the title color + * + * @return The TitledBorder object + */ + public static TitledBorder createTitledBorder(Border border, String title, + int titleJustification, + int titlePosition, + Font titleFont, Color titleColor) + { + return new TitledBorder(border, title, titleJustification, titlePosition, + titleFont, titleColor); + } + + /** + * Creates an empty border that takes up no space. (The width of the top, + * bottom, left, and right sides are all zero.) + * + * @return The Border object + */ + public static Border createEmptyBorder() + { + return new EmptyBorder(0, 0, 0, 0); + } + + /** + * Creates an empty border that takes up no space but which does no drawing, + * specifying the width of the top, left, bottom, and right sides. + * + * @param top An int specifying the width of the top in pixels + * @param left An int specifying the width of the left side in pixels + * @param bottom An int specifying the width of the right side in pixels + * @param right An int specifying the width of the bottom in pixels + * + * @return The Border object + */ + public static Border createEmptyBorder(int top, int left, int bottom, + int right) + { + return new EmptyBorder(top, left, bottom, right); + } + + /** + * Create a compound border with a null inside edge and a null outside edge. + * + * @return The CompoundBorder object + */ + public static CompoundBorder createCompoundBorder() + { + return new CompoundBorder(); + } + + /** + * Create a compound border specifying the border objects to use for the + * outside and inside edges. + * + * @param outsideBorder A Border object for the outer edge of the + * compound border + * @param insideBorder A Border object for the inner edge of the + * compound border + * + * @return The CompoundBorder object + */ + public static CompoundBorder createCompoundBorder(Border outsideBorder, + Border insideBorder) + { + return new CompoundBorder(outsideBorder, insideBorder); + } + + /** + * Create a matte-look border using a solid color. (The difference between + * this border and a line border is that you can specify the individual border + * dimensions.) + * + * @param top + * An int specifying the width of the top in pixels + * @param left + * An int specifying the width of the left side in pixels + * @param bottom + * An int specifying the width of the right side in pixels + * @param right + * An int specifying the width of the bottom in pixels + * @param color + * A Color to use for the border + * @return The MatteBorder object + */ + public static MatteBorder createMatteBorder(int top, int left, int bottom, + int right, Color color) + { + return new MatteBorder(top, left, bottom, right, color); + } + + /** + * Create a matte-look border that consists of multiple tiles of a specified + * icon. Multiple copies of the icon are placed side-by-side to fill up the + * border area. + * + * Note: + * If the icon doesn't load, the border area is painted gray. + * + * @param top An int specifying the width of the top in pixels + * @param left An int specifying the width of the left side in pixels + * @param bottom An int specifying the width of the right side in pixels + * @param right An int specifying the width of the bottom in pixels + * @param tileIcon The Icon object used for the border tiles + * + * @return The MatteBorder object + */ + public static MatteBorder createMatteBorder(int top, int left, int bottom, + int right, Icon tileIcon) + { + return new MatteBorder(top, left, bottom, right, tileIcon); + } +} diff --git a/libjava/classpath/javax/swing/BoundedRangeModel.java b/libjava/classpath/javax/swing/BoundedRangeModel.java new file mode 100644 index 0000000..5f85000 --- /dev/null +++ b/libjava/classpath/javax/swing/BoundedRangeModel.java @@ -0,0 +1,171 @@ +/* BoundedRangeModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import javax.swing.event.ChangeListener; + +/** + * The data model that is used in components that display a range of values, + * like {@link JProgressBar} and {@link JSlider}. + * + * @author Andrew Selkirk + */ +public interface BoundedRangeModel +{ + /** + * getValue + * + * @return int + * + * @see #setValue(int) + */ + int getValue(); + + /** + * setValue + * + * @param value the value + * + * @see #getValue() + */ + void setValue(int value); + + /** + * getMinimum + * + * @return int + * + * @see #setMinimum(int) + */ + int getMinimum(); + + /** + * setMinimum + * + * @param minimum the minimum value + * + * @see #getMinimum() + */ + void setMinimum(int minimum); + + /** + * getMaximum + * + * @return int + * + * @see #setMaximum(int) + */ + int getMaximum(); + + /** + * setMaximum + * + * @param maximum the maximum value + * + * @see #getMaximum() + */ + void setMaximum(int maximum); + + /** + * Returns the value of the valueIsAdjusting property. + * + * @return true if value is adjusting, + * otherwise false + * + * @see setValueIsAdjusting(boolean) + */ + boolean getValueIsAdjusting(); + + /** + * setValueIsAdjusting + * + * @param adjusting true if adjusting, + * false otherwise + * + * @see #getValueIsAdjusting() + */ + void setValueIsAdjusting(boolean adjusting); + + /** + * Returns the current extent. + * + * @return the extent + * + * @see #setExtent(int) + */ + int getExtent(); + + /** + * setExtent + * + * @param extent the extent + * + * @see #getExtent() + */ + void setExtent(int extent); + + /** + * setRangeProperties + * @param value the value + * @param extent the extent + * @param minnimum the minimum value + * @param maximum the maximum value + * @param adjusting TODO + */ + void setRangeProperties(int value, int extent, int minimum, int maximum, + boolean adjusting); + + /** + * Adds a ChangeListener to this object. + * + * @param listener the listener to add + * + * @see #removeChangeListener(javax.swing.event.ChangeListener) + */ + void addChangeListener(ChangeListener listener); + + /** + * Removes a ChangeListener from this object. + * + * @param listener the listener to remove + * + * @see #addChangeListener(javax.swing.event.ChangeListener) + */ + void removeChangeListener(ChangeListener listener); +} diff --git a/libjava/classpath/javax/swing/Box.java b/libjava/classpath/javax/swing/Box.java new file mode 100644 index 0000000..546a282 --- /dev/null +++ b/libjava/classpath/javax/swing/Box.java @@ -0,0 +1,287 @@ +/* Box.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTError; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.LayoutManager; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * A component that uses a {@link BoxLayout} as Layout Manager. + * + * In addition to that, this class provides a set of static methods for + * creating some filler components ('struts' and 'glue') for use in + * containers that are laid out using BoxLayout. + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class Box extends JComponent implements Accessible +{ + private static final long serialVersionUID = 1525417495883046342L; + + // FIXME: disable to make libjava compile; visibility rules are broken + protected class AccessibleBox // extends Container.AccessibleAWTContainer + { + private static final long serialVersionUID = -7775079816389931944L; + + protected AccessibleBox() + { + } + + public AccessibleRole getAccessibleRole() + { + return null; + } + } + + /** + * A component that servers as a filler in BoxLayout controlled containers. + */ + public static class Filler extends JComponent implements Accessible + { + private static final long serialVersionUID = -1204263191910183998L; + + // FIXME: disable to make libjava compile; visibility rules are broken + protected class AccessibleBoxFiller // extends Component.AccessibleAWTComponent + { + private static final long serialVersionUID = 164963348357479321L; + + protected AccessibleBoxFiller() + { + } + + public AccessibleRole getAccessibleRole() + { + return null; + } + } + + protected AccessibleContext accessibleContext; + + private transient Dimension min, pref, max; + + /** + * Creates a new instance of Filler. + * + * @param min the minimum size of the filler. + * @param pref the preferred size of the filler. + * @param max the maximum size of the filler. + */ + public Filler(Dimension min, Dimension pref, Dimension max) + { + changeShape(min, pref, max); + } + + /** + * Changes the dimensions of this Filler. + * + * @param min the new minimum size of the filler. + * @param pref the new preferred size of the filler. + * @param max the new maximum size of the filler. + */ + public void changeShape(Dimension min, Dimension pref, Dimension max) + { + this.min = min; + this.pref = pref; + this.max = max; + } + + public AccessibleContext getAccessibleContext() + { + // FIXME: disable to make libjava compile; visibility rules are broken + // if (accessibleContext == null) + // accessibleContext = new AccessibleBoxFiller(); + return accessibleContext; + } + + /** + * Returns the maximum size of this Filler. + * + * @return the maximum size of this Filler. + */ + public Dimension getMaximumSize() + { + return max; + } + + /** + * Returns the minimum size of this Filler. + * + * @return the minimum size of this Filler. + */ + public Dimension getMinimumSize() + { + return min; + } + + /** + * Returns the preferred size of this Filler. + * + * @return the preferred size of this Filler. + */ + public Dimension getPreferredSize() + { + return pref; + } + } + + /** + * Creates a new Box component, that lays out its children according + * to the axis parameter. + * + * @param axis the orientation of the BoxLayout. + * + * @see BoxLayout#X_AXIS + * @see BoxLayout#Y_AXIS + * @see BoxLayout#LINE_AXIS + * @see BoxLayout#PAGE_AXIS + */ + public Box(int axis) + { + super.setLayout(new BoxLayout(this, axis)); + } + + /** + * Creates a filler component which acts as glue between components. + * It does not take space unless some extra space is available. If extra + * space is available, this component can expand in both X and Y directions. + * + * @return a glue-like filler component. + */ + public static Component createGlue() + { + Filler glue = new Filler(new Dimension(0,0), new Dimension(0,0), + new Dimension(Short.MAX_VALUE,Short.MAX_VALUE) + ); + return glue; + } + + public static Box createHorizontalBox() + { + return new Box(BoxLayout.X_AXIS); + } + + /** + * Creates a filler component which acts as glue between components. + * It does not take space unless some extra space is available. If extra + * space is available, this component can expand in the X direction. + * + * @return a glue-like filler component. + */ + public static Component createHorizontalGlue() + { + Filler glue = new Filler(new Dimension(0,0), new Dimension(0,0), + new Dimension(Short.MAX_VALUE, 0) + ); + return glue; + } + + /** + * Creates a filler component which acts as strut between components. + * It will fill exactly the specified horizontal size. + * + * @param width the width of this strut in pixels. + * + * @return a strut-like filler component. + */ + public static Component createHorizontalStrut(int width) + { + Filler strut = new Filler(new Dimension(width, 0), + new Dimension(width, 0), + new Dimension(width, Integer.MAX_VALUE)); + return strut; + } + + public static Component createRigidArea(Dimension d) + { + return new Filler(d, d, d); + } + + public static Box createVerticalBox() + { + return new Box(BoxLayout.Y_AXIS); + } + + /** + * Creates a filler component which acts as glue between components. + * It does not take space unless some extra space is available. If extra + * space is available, this component can expand in the Y direction. + * + * @return a glue-like filler component. + */ + public static Component createVerticalGlue() + { + return createGlue(); + } + + /** + * Creates a filler component which acts as strut between components. + * It will fill exactly the specified vertical size. + * + * @param height the height of this strut in pixels. + * + * @return a strut-like filler component. + */ + public static Component createVerticalStrut(int height) + { + Filler strut = new Filler(new Dimension(0, height), + new Dimension(0, height), + new Dimension(Integer.MAX_VALUE, height)); + return strut; + } + + public void setLayout(LayoutManager l) + { + throw new AWTError("Not allowed to set layout managers for boxes."); + } + + public AccessibleContext getAccessibleContext() + { + // if (accessibleContext == null) + // accessibleContext = new AccessibleBox(); + return accessibleContext; + } + + +} diff --git a/libjava/classpath/javax/swing/BoxLayout.java b/libjava/classpath/javax/swing/BoxLayout.java new file mode 100644 index 0000000..5dfe1d6 --- /dev/null +++ b/libjava/classpath/javax/swing/BoxLayout.java @@ -0,0 +1,746 @@ +/* BoxLayout.java -- A layout for swing components. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.AWTError; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Container; +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 for swing components. + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Roman Kennke (roman@kennke.org) + */ +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 d for this direction. This will + * be d.width for horizontal and d.height for + * vertical direction. + * + * @param d the size as Dimension object + * + * @return the correct part of d for this direction + */ + int size(Dimension d); + + /** + * Returns the lower bounds of the {@link Insets} object according to this + * direction. This will be insets.top for vertical direction + * and insets.left 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 c. coord1 + * specifies the coordinate of the location in this direction, + * coord2 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 c. coord1 + * specifies the size in this direction, + * coord2 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 d for this direction. This will + * be d.width for horizontal and d.height for + * vertical direction. + * + * @param d the size as Dimension object + * + * @return the correct part of d 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 insets.top for vertical direction + * and insets.left 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 + */ + 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 c. coord1 + * specifies the coordinate of the location in this direction, + * coord2 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 c. coord1 + * specifies the size in this direction, + * coord2 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 d for this direction. This will + * be d.width for horizontal and d.height for + * vertical direction. + * + * @param d the size as Dimension object + * + * @return the correct part of d 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 insets.top for vertical direction + * and insets.left 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 + */ + 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 c. coord1 + * specifies the coordinate of the location in this direction, + * coord2 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 c. coord1 + * specifies the size in this direction, + * coord2 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; + + /** + * Specifies that components are laid out top to bottom. + */ + public static final int Y_AXIS = 1; + + /** + * Specifies that components are laid out in the direction of a line of text. + */ + public static final int LINE_AXIS = 2; + + /** + * Sepcifies that components are laid out in the direction of the line flow. + */ + public static final int PAGE_AXIS = 3; + + /* + * Needed for serialization. + */ + private static final long serialVersionUID = -2474455742719112368L; + + /* + * The container given to the constructor. + */ + 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(); + + /** Constant for the vertical direction. */ + private static final Direction VERTICAL = new Vertical(); + + /** + * Constructs a BoxLayout object. + * + * @param container The container that needs to be laid out. + * @param way The orientation of the components. + * + * @exception AWTError If way has an invalid value. + */ + public BoxLayout(Container container, int way) + { + int width = 0; + int height = 0; + this.container = container; + this.way = way; + } + + /** + * Adds a component to the layout. Not used in BoxLayout. + * + * @param name The name of the component to add. + * @param component the component to add to the layout. + */ + public void addLayoutComponent(String name, Component component) + { + } + + /** + * Removes a component from the layout. Not used in BoxLayout. + * + * @param component The component to remove from the layout. + */ + public void removeLayoutComponent(Component component) + { + } + + private boolean isHorizontalIn(Container parent) + { + ComponentOrientation orientation = parent.getComponentOrientation(); + return this.way == X_AXIS + || (this.way == LINE_AXIS + && orientation.isHorizontal()) + || (this.way == PAGE_AXIS + && (!orientation.isHorizontal())); + } + + + + /** + * Returns the preferred size of the layout. + * + * @param parent The container that needs to be laid out. + * + * @return The dimension of the layout. + */ + 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); + + 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; + } + + return new Dimension(x, y); + } + + /** + * Returns the minimum size of the layout. + * + * @param parent The container that needs to be laid out. + * + * @return The dimension of the layout. + */ + 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)) + { + // 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); + } + } + + return new Dimension(x, y); + } + + /** + * Lays out the specified container using this layout. + * + * @param parent The container that needs to be laid out. + */ + public void layoutContainer(Container parent) + { + if (isHorizontalIn(parent)) + layoutAlgorithm(parent, HORIZONTAL, VERTICAL); + else + layoutAlgorithm(parent, VERTICAL, HORIZONTAL); + } + + /** + * Adds a component to the layout. Not used in BoxLayout + * + * @param child The component to add to the layout. + * @param constraints The constraints for the component in the layout. + */ + public void addLayoutComponent(Component child, Object constraints) + { + } + + /** + * Returns the alignment along the X axis for the container. + * + * @param parent The container that needs to be laid out. + * + * @return The alignment. + */ + public float getLayoutAlignmentX(Container parent) + { + if (parent != container) + throw new AWTError("invalid parent"); + + return 0; + } + + /** + * Returns the alignment along the Y axis for the container. + * + * @param parent The container that needs to be laid out. + * + * @return The alignment. + */ + public float getLayoutAlignmentY(Container parent) + { + if (parent != container) + throw new AWTError("invalid parent"); + + return 0; + } + + /** + * Invalidates the layout. + * + * @param parent The container that needs to be laid out. + */ + public void invalidateLayout(Container parent) + { + if (parent != container) + throw new AWTError("invalid parent"); + } + + /** + * Returns the maximum size of the layout gived the components + * in the given container. + * + * @param parent The container that needs to be laid out. + * + * @return The dimension of the layout. + */ + 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; + + List children = AWTUtilities.getVisibleChildren(parent); + + if (isHorizontalIn(parent)) + { + + // 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.getMaximumSize(); + x += sz.width; + // Check for overflow. + if (x < 0) + x = Integer.MAX_VALUE; + 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.getMaximumSize(); + y += sz.height; + // Check for overflow + if (y < 0) + y = Integer.MAX_VALUE; + x = Math.max(x, sz.width); + } + } + return new Dimension(x, y); + } + + /** + * Lays out the Container c in the layout direction + * layoutDir. The direction that is crossing the layout + * direction is specified in crossDir. + * + * @param parent + * @param layoutDir + * @param crossDir + */ + void layoutAlgorithm(Container parent, Direction layoutDir, Direction crossDir) + { + 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();) + { + 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; + } + } + + /** + * Distributes some space over a set of components. This implementation + * tries to set the components as close as possible to their + * preferredSizes, and respects the components + * minimumSize and maximumSize. + * + * The algorithm is implemented as follows: + * + *

+ * + * @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 + */ + void distributeSpace(Collection freeComponents, int remainder, Direction dir) + { + // 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();) + { + // Add/substract share to component. + SizeReq sizeReq = (SizeReq) i.next(); + double available = 0; + if (remainder >= 0) + available = sizeReq.max - sizeReq.size; + 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); + } + // 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 new file mode 100644 index 0000000..bea8aea --- /dev/null +++ b/libjava/classpath/javax/swing/ButtonGroup.java @@ -0,0 +1,179 @@ +/* ButtonGroup.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Vector; + + +/** + * DOCUMENT ME! + */ +public class ButtonGroup implements Serializable +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = 4259076101881721375L; + + /** The buttons added to this button group. */ + protected Vector buttons = new Vector(); + + /** The currently selected button model. */ + ButtonModel sel; + + /** + * Creates a new button group. + */ + public ButtonGroup() + { + } + + /** + * Adds a button to this group. + * + * @param b the button to add + */ + public void add(AbstractButton b) + { + b.getModel().setGroup(this); + buttons.addElement(b); + } + + /** + * Removed a given button from this group. + * + * @param b the button to remove + */ + public void remove(AbstractButton b) + { + b.getModel().setGroup(null); + buttons.removeElement(b); + } + + /** + * Returns the currently added buttons. + * + * @return Enumeration over all added buttons + */ + public Enumeration getElements() + { + return buttons.elements(); + } + + /** + * Returns the currently selected button model. + * + * @return the currently selected button model, null if none was selected + * yet + */ + public ButtonModel getSelection() + { + return sel; + } + + /** + * DOCUMENT ME! + * + * @param m DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + AbstractButton FindButton(ButtonModel m) + { + for (int i = 0; i < buttons.size(); i++) + { + AbstractButton a = (AbstractButton) buttons.get(i); + if (a.getModel() == m) + return a; + } + return null; + } + + /** + * Sets the currently selected button model. Only one button of a group can + * be selected at a time. + * + * @param m the model to select + * @param b true if this button is to be selected, false otherwise + */ + public void setSelected(ButtonModel m, boolean b) + { + if ((sel != m || b) && (! b || sel == m)) + return; + + if (b && sel != m) + { + ButtonModel old = sel; + sel = m; + + if (old != null) + old.setSelected(false); + AbstractButton button = FindButton(old); + if (button != null) + button.repaint(); + } + else if (!b && sel == m) + m.setSelected(true); + } + + /** + * Checks if the given ButtonModel is selected in this button + * group. + * + * @param m DOCUMENT ME! + * + * @return true of given ButtonModel is selected, false + * otherwise + */ + public boolean isSelected(ButtonModel m) + { + return m == sel; + } + + /** + * Return the number of buttons in this button group. + * + * @return the number of buttons + * + * @since 1.3 + */ + public int getButtonCount() + { + return buttons.size(); + } +} diff --git a/libjava/classpath/javax/swing/ButtonModel.java b/libjava/classpath/javax/swing/ButtonModel.java new file mode 100644 index 0000000..1bdc5d1 --- /dev/null +++ b/libjava/classpath/javax/swing/ButtonModel.java @@ -0,0 +1,85 @@ +/* ButtonModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.ItemSelectable; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; + +import javax.swing.event.ChangeListener; + +/** + * The data model that is used in all kinds of buttons. + */ +public interface ButtonModel extends ItemSelectable +{ + boolean isArmed(); + void setArmed(boolean b); + + + boolean isEnabled(); + void setEnabled(boolean b); + + void setPressed(boolean b); + boolean isPressed(); + + + void removeActionListener(ActionListener l); + void addActionListener(ActionListener l); + + void addItemListener(ItemListener l); + void removeItemListener(ItemListener l); + + void addChangeListener(ChangeListener l); + void removeChangeListener(ChangeListener l); + + void setRollover(boolean b); + boolean isRollover(); + + int getMnemonic(); + void setMnemonic(int key); + + void setActionCommand(String s); + String getActionCommand(); + + void setGroup(ButtonGroup group); + + void setSelected(boolean b); + boolean isSelected(); +} diff --git a/libjava/classpath/javax/swing/CellEditor.java b/libjava/classpath/javax/swing/CellEditor.java new file mode 100644 index 0000000..bdb1665 --- /dev/null +++ b/libjava/classpath/javax/swing/CellEditor.java @@ -0,0 +1,96 @@ +/* CellEditor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.util.EventObject; + +import javax.swing.event.CellEditorListener; + +/** + * Provides edit capabilities for components that display cells like + * {@link JTable}, {@link JList} and {@link JTree}. + * + * @author Andrew Selkirk + */ +public interface CellEditor +{ + /** + * getCellEditorValue + * @returns Object + */ + Object getCellEditorValue(); + + /** + * isCellEditable + * @param event TODO + * @returns boolean + */ + boolean isCellEditable(EventObject event); + + /** + * shouldSelectCell + * @param event TODO + * @returns boolean + */ + boolean shouldSelectCell(EventObject event); + + /** + * stopCellEditing + * @returns boolean + */ + boolean stopCellEditing(); + + /** + * cancelCellEditing + */ + void cancelCellEditing(); + + /** + * addCellEditorListener + * @param value0 TODO + */ + void addCellEditorListener(CellEditorListener listener); + + /** + * removeCellEditorListener + * @param listener TODO + */ + void removeCellEditorListener(CellEditorListener listener); + +} // CellEditor diff --git a/libjava/classpath/javax/swing/CellRendererPane.java b/libjava/classpath/javax/swing/CellRendererPane.java new file mode 100644 index 0000000..db7a143 --- /dev/null +++ b/libjava/classpath/javax/swing/CellRendererPane.java @@ -0,0 +1,251 @@ +/* CellRendererPane.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * The CellRendererPane's purpose is to paint the cells of JList, JTable and + * JTree. It intercepts the usual paint tree, so that we don't walk up and + * repaint everything. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class CellRendererPane + extends Container + implements Accessible +{ + private static final long serialVersionUID = -7642183829532984273L; + + /** + * AccessibleCellRendererPane + */ + protected class AccessibleCellRendererPane extends AccessibleAWTContainer + { + private static final long serialVersionUID = -8981090083147391074L; + + /** + * Constructor AccessibleCellRendererPane + * @param component TODO + */ + protected AccessibleCellRendererPane() + { + } + + /** + * getAccessibleRole + * @returns AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PANEL; + } + } + + /** + * accessibleContext + */ + protected AccessibleContext accessibleContext = null; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructs a new CellRendererPane. + */ + public CellRendererPane() + { + } // CellRendererPane() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * Should not be called. + * + * @param graphics not used here + */ + public void update(Graphics graphics) + { + } // update() + + /** + * Despite normal behaviour this does not cause the container + * to be invalidated. This prevents propagating up the paint tree. + */ + public void invalidate() + { + } // invalidate() + + /** + * Should not be called. + * + * @param graphics not used here + */ + public void paint(Graphics graphics) + { + } + + /** + * Overridden to check if a component is already a child of this Container. + * If it's already a child, nothing is done. Otherwise we pass this to + * super.addImpl(). + * + * @param c the component to add + * @param constraints not used here + * @param index not used here + */ + protected void addImpl(Component c, Object constraints, int index) + { + if (!isAncestorOf(c)) + { + super.addImpl(c, constraints, index); + } + } // addImpl() + + /** + * Paints the specified component c on the {@link Graphics} + * context graphics. The Graphics context is tranlated to + * (x,y) and the components bounds are set to (w,h). If + * shouldValidate + * is set to true, then the component is validated before painting. + * + * @param graphics the graphics context to paint on + * @param c the component to be painted + * @param p the parent of the component + * @param x the X coordinate of the upper left corner where c should + be painted + * @param y the Y coordinate of the upper left corner where c should + be painted + * @param w the width of the components drawing area + * @param h the height of the components drawing area + * @param shouldValidate if c should be validated before + * painting + */ + public void paintComponent(Graphics graphics, Component c, + Container p, int x, int y, int w, int h, + boolean shouldValidate) + { + // reparent c + addImpl(c, null, 0); + + // translate to (x,y) + graphics.translate(x, y); + + // set bounds of c + c.setBounds(0, 0, w, h); + + // validate if necessary + if (shouldValidate) + { + c.validate(); + } + + // paint component + c.paint(graphics); + + // untranslate g + graphics.translate(-x, -y); + + } // paintComponent() + + /** + * Paints the specified component c on the {@link Graphics} + * context graphics. The Graphics context is tranlated to (x,y) + * and the components bounds are set to (w,h). The component is not + * validated before painting. + * + * @param graphics the graphics context to paint on + * @param c the component to be painted + * @param p the parent of the component + * @param x the X coordinate of the upper left corner where c should + be painted + * @param y the Y coordinate of the upper left corner where c should + be painted + * @param w the width of the components drawing area + * @param h the height of the components drawing area + */ + public void paintComponent(Graphics graphics, Component c, + Container p, int x, int y, int w, int h) + { + paintComponent(graphics, c, p, x, y, w, h, false); + } // paintComponent() + + /** + * Paints the specified component c on the {@link Graphics} + * context g. The Graphics context is tranlated to (r.x,r.y) and + * the components bounds are set to (r.width,r.height). + * The component is not + * validated before painting. + * + * @param graphics the graphics context to paint on + * @param c the component to be painted + * @param p the component on which we paint + * @param r the bounding rectangle of c + */ + public void paintComponent(Graphics graphics, Component c, + Container p, Rectangle r) + { + paintComponent(graphics, c, p, r.x, r.y, r.width, r.height); + } // paintComponent() + + /** + * getAccessibleContext TODO + * @return AccessibleContext + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleCellRendererPane(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/ComboBoxEditor.java b/libjava/classpath/javax/swing/ComboBoxEditor.java new file mode 100644 index 0000000..4eb5fc5 --- /dev/null +++ b/libjava/classpath/javax/swing/ComboBoxEditor.java @@ -0,0 +1,96 @@ +/* ComboBoxEditor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.event.ActionListener; + +/** + * Provides edit capabilities for {@link JComboBox}es. + * + * @author Andrew Selkirk + * @author Olga Rodimina + */ +public interface ComboBoxEditor +{ + /** + * This method returns component that will be used by the combo box to + * display/edit currently selected item in the combo box. + * + * @return Component that will be used by the combo box to display/edit + * currently selected item + */ + Component getEditorComponent(); + + /** + * Sets item that should be editted when any editting operation is performed + * by the user. The value is always equal to the currently selected value + * in the combo box. Thus, whenever a different value is selected from the + * 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 + */ + void setItem(Object item); + + /** + * This method returns item that is currently editable. + * + * @return Item in the combo box that is currently editable + */ + Object getItem(); + + /** + * selectAll + */ + void selectAll(); + + /** + * This method adds specified ActionListener to this ComboBoxEditor. + * + * @param listener + */ + void addActionListener(ActionListener listener); + + /** + * This method removes given ActionListener from this ComboBoxEditor. + * + * @param listener TODO + */ + void removeActionListener(ActionListener listener); +} // ComboBoxEditor diff --git a/libjava/classpath/javax/swing/ComboBoxModel.java b/libjava/classpath/javax/swing/ComboBoxModel.java new file mode 100644 index 0000000..6968db4 --- /dev/null +++ b/libjava/classpath/javax/swing/ComboBoxModel.java @@ -0,0 +1,67 @@ +/* ComboBoxModel.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + + +/** + * The data model for {@link JComboBox}. 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 should fire ListDataEvents to ComboBox's ListDataListeners. + * + * @author Andrew Selkirk + */ +public interface ComboBoxModel extends ListModel +{ + /** + * This method sets the selected item in the combo box. Class + * implementing this interface should fire ListDataEvents to + * all registered ListDataListeners to indicated that the + * selection has changed. + * + * @param item item in the combo box that should be selected + */ + void setSelectedItem(Object item); + + /** + * The method returns currently selected item in the combo box + * + * @returns item that is currently selected in the combo box. + */ + Object getSelectedItem(); +} // ComboBoxModel diff --git a/libjava/classpath/javax/swing/ComponentInputMap.java b/libjava/classpath/javax/swing/ComponentInputMap.java new file mode 100644 index 0000000..4ecc058 --- /dev/null +++ b/libjava/classpath/javax/swing/ComponentInputMap.java @@ -0,0 +1,130 @@ +/* ComponentInputMap.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + + +/** + * @author Andrew Selkirk + * @author Michael Koch + */ +public class ComponentInputMap extends InputMap +{ + /** + * The component to notify. + */ + private JComponent component; + + /** + * Creates ComponentInputMap object that notifies the given + * component about changes to it. + * + * @param comp the component to notify + * + * @exception IllegalArgumentException if comp is null + */ + public ComponentInputMap(JComponent comp) + { + if (comp == null) + throw new IllegalArgumentException(); + + this.component = comp; + } + + /** + * Puts a new entry into the InputMap. + * If actionMapKey is null an existing entry will be removed. + * + * @param keystroke the keystroke for the entry + * @param actionMapKey the action. + */ + public void put(KeyStroke keystroke, Object value) + { + super.put(keystroke, value); + // FIXME: Notify component. + } + + /** + * Clears the InputMap. + */ + public void clear() + { + super.clear(); + // FIXME: Notify component. + } + + /** + * Remove an entry from the InputMap. + * + * @param key the key of the entry to remove + */ + public void remove(KeyStroke keystroke) + { + super.remove(keystroke); + // FIXME: Notify component. + } + + /** + * Sets a parent for this ComponentInputMap. + * + * @param parentMap the new parent + * + * @exception IllegalArgument if parentMap is not a + * ComponentInputMap or not associated with the same component + */ + public void setParent(InputMap parentMap) + { + if (! (parentMap instanceof ComponentInputMap)) + throw new IllegalArgumentException(); + + if (((ComponentInputMap) parentMap).getComponent() != component) + throw new IllegalArgumentException(); + + super.setParent(parentMap); + // FIXME: Notify component. + } + + /** + * Returns the component to notify about changes. + * + * @return a JComponent object + */ + public JComponent getComponent() + { + return component; + } +} diff --git a/libjava/classpath/javax/swing/DebugGraphics.java b/libjava/classpath/javax/swing/DebugGraphics.java new file mode 100644 index 0000000..e73c120 --- /dev/null +++ b/libjava/classpath/javax/swing/DebugGraphics.java @@ -0,0 +1,885 @@ +/* DebugGraphics.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.image.ImageObserver; +import java.io.PrintStream; +import java.text.AttributedCharacterIterator; + + +/** + * DebugGraphics + * @author Andrew Selkirk + * @version 1.0 + */ +public class DebugGraphics extends Graphics +{ + /** + * LOG_OPTION + */ + public static final int LOG_OPTION = 1; + + /** + * FLASH_OPTION + */ + public static final int FLASH_OPTION = 2; + + /** + * BUFFERED_OPTION + */ + public static final int BUFFERED_OPTION = 4; + + /** + * NONE_OPTION + */ + public static final int NONE_OPTION = -1; + + static Color debugFlashColor = Color.RED; + static int debugFlashCount = 10; + static int debugFlashTime = 1000; + static PrintStream debugLogStream = System.out; + + /** + * graphics + */ + Graphics graphics; + + /** + * color + */ + Color color = Color.BLACK; + + /** + * buffer + */ + Image buffer; + + /** + * debugOptions + */ + int debugOptions; + + /** + * graphicsID + */ + int graphicsID; + + /** + * xOffset + */ + int xOffset; + + /** + * yOffset + */ + int yOffset; + + /** + * Creates a DebugGraphics object. + */ + public DebugGraphics() + { + // TODO + } + + /** + * Creates a DebugGraphics object. + * + * @param graphics The Graphics object to wrap + * @param component TODO + */ + public DebugGraphics(Graphics graphics, JComponent component) + { + this.graphics = graphics; + // FIXME: What shall we do with component ? + } + + /** + * Creates a DebugGraphics object. + * + * @param graphics The Graphics object to wrap + */ + public DebugGraphics(Graphics graphics) + { + this.graphics = graphics; + } + + /** + * Sets the color to draw stuff with. + * + * @param color The color + */ + public void setColor(Color color) + { + this.color = color; + } + + /** + * Creates a overrides Graphics.create to create a + * DebugGraphics object. + * + * @return a new DebugGraphics object. + */ + public Graphics create() + { + return new DebugGraphics(graphics.create()); + } + + /** + * Creates a overrides Graphics.create to create a + * DebugGraphics object. + * + * @param x the x coordinate + * @param y the y coordinate + * @param width the width + * @param height the height + * + * @return a new DebugGraphics object. + */ + public Graphics create(int x, int y, int width, int height) + { + return new DebugGraphics(graphics.create(x, y, width, height)); + } + + /** + * flashColor + * + * @return Color + */ + public static Color flashColor() + { + return debugFlashColor; + } + + /** + * setFlashColor + * + * @param color the color to use for flashing + */ + public static void setFlashColor(Color color) + { + debugFlashColor = color; + } + + /** + * flashTime + * + * @return The time in milliseconds + */ + public static int flashTime() + { + return debugFlashTime; + } + + /** + * setFlashTime + * + * @param time The time in milliseconds + */ + public static void setFlashTime(int time) + { + debugFlashTime = time; + } + + /** + * flashCount + * + * @return The number of flashes + */ + public static int flashCount() + { + return debugFlashCount; + } + + /** + * setFlashCount + * + * @param count The number of flashes + */ + public static void setFlashCount(int count) + { + debugFlashCount = count; + } + + /** + * logStream + * + * @return The PrintStream to write logging messages to + */ + public static PrintStream logStream() + { + return debugLogStream; + } + + /** + * setLogStream + * + * @param stream The currently set PrintStream. + */ + public static void setLogStream(PrintStream stream) + { + debugLogStream = stream; + } + + /** + * getFont + * + * @return The font + */ + public Font getFont() + { + return graphics.getFont(); + } + + /** + * setFont + * + * @param font The font to use for drawing text + */ + public void setFont(Font font) + { + graphics.setFont(font); + } + + /** + * Returns the color used for drawing. + * + * @return The color. + */ + public Color getColor() + { + return color; + } + + /** + * Returns the font metrics of the current font. + * + * @return a FontMetrics object + */ + public FontMetrics getFontMetrics() + { + return graphics.getFontMetrics(); + } + + /** + * Returns the font metrics for a given font. + * + * @param font the font to get the metrics for + * + * @return a FontMetrics object + */ + public FontMetrics getFontMetrics(Font font) + { + return graphics.getFontMetrics(font); + } + + /** + * translate + * + * @param x the x coordinate + * @param y the y coordinate + */ + public void translate(int x, int y) + { + graphics.translate(x, y); + } + + /** + * setPaintMode + */ + public void setPaintMode() + { + graphics.setPaintMode(); + } + + /** + * setXORMode + * + * @param color the color + */ + public void setXORMode(Color color) + { + graphics.setXORMode(color); + } + + /** + * getClipBounds + * + * @return Rectangle + */ + public Rectangle getClipBounds() + { + return graphics.getClipBounds(); + } + + /** + * Intersects the current clip region with the given region. + * + * @param x The x-position of the region + * @param y The y-position of the region + * @param width The width of the region + * @param height The height of the region + */ + public void clipRect(int x, int y, int width, int height) + { + graphics.clipRect(x, y, width, height); + } + + /** + * Sets the clipping region. + * + * @param x The x-position of the region + * @param y The y-position of the region + * @param width The width of the region + * @param height The height of the region + */ + public void setClip(int x, int y, int width, int height) + { + graphics.setClip(x, y, width, height); + } + + /** + * Returns the current clipping region. + * + * @return Shape + */ + public Shape getClip() + { + return graphics.getClip(); + } + + /** + * Sets the current clipping region + * + * @param shape The clippin region + */ + public void setClip(Shape shape) + { + graphics.setClip(shape); + } + + private void sleep(int milliseconds) + { + try + { + Thread.sleep(milliseconds); + } + catch (InterruptedException e) + { + // Ignore this. + } + } + + /** + * Draws a rectangle. + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + */ + public void drawRect(int x, int y, int width, int height) + { + 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.drawRect(x, y, width, height); + } + + /** + * Draws a filled rectangle. + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + */ + public void fillRect(int x, int y, int width, int height) + { + 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.fillRect(x, y, width, height); + } + + /** + * clearRect + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + */ + public void clearRect(int x, int y, int width, int height) + { + graphics.clearRect(x, y, width, height); + } + + /** + * drawRoundRect + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param arcWidth TODO + * @param arcHeight TODO + */ + public void drawRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + /** + * fillRoundRect + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param arcWidth TODO + * @param arcHeight TODO + */ + public void fillRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + /** + * drawLine + * + * @param x1 The x-position of the start + * @param y1 The y-position of the start + * @param x2 The x-position of the end + * @param y2 The y-position of the end + */ + public void drawLine(int x1, int y1, int x2, int y2) + { + graphics.drawLine(x1, y1, x2, y2); + } + + /** + * draw3DRect + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param raised TODO + */ + public void draw3DRect(int x, int y, int width, int height, boolean raised) + { + graphics.draw3DRect(x, y, width, height, raised); + } + + /** + * fill3DRect + * + * @param x The x-position of the rectangle + * @param y The y-position of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param raised TODO + */ + public void fill3DRect(int x, int y, int width, int height, boolean raised) + { + graphics.fill3DRect(x, y, width, height, raised); + } + + /** + * drawOval + * + * @param x the x coordinate + * @param y the y coordiante + * @param width the width + * @param height the height + */ + public void drawOval(int x, int y, int width, int height) + { + graphics.drawOval(x, y, width, height); + } + + /** + * fillOval + * + * @param x the x coordinate + * @param y the y coordinate + * @param width the width + * @param height the height + */ + public void fillOval(int x, int y, int width, int height) + { + graphics.fillOval(x, y, width, height); + } + + /** + * drawArc + * + * @param x the x coordinate + * @param y the y coordinate + * @param width the width + * @param height the height + * @param startAngle TODO + * @param arcAngle TODO + */ + public void drawArc(int x, int y, int width, int height, + int startAngle, int arcAngle) + { + graphics.drawArc(x, y, width, height, startAngle, arcAngle); + } + + /** + * fillArc + * + * @param x the coordinate + * @param y the y coordinate + * @param width the width + * @param height the height + * @param startAngle TODO + * @param arcAngle TODO + */ + public void fillArc(int x, int y, int width, int height, + int startAngle, int arcAngle) + { + graphics.fillArc(x, y, width, height, startAngle, arcAngle); + } + + /** + * drawPolyline + * + * @param xpoints TODO + * @param ypoints TODO + * @param npoints TODO + */ + public void drawPolyline(int[] xpoints, int[] ypoints, int npoints) + { + graphics.drawPolyline(xpoints, ypoints, npoints); + } + + /** + * drawPolygon + * + * @param xpoints TODO + * @param ypoints TODO + * @param npoints TODO + */ + public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) + { + graphics.drawPolygon(xpoints, ypoints, npoints); + } + + /** + * fillPolygon + * + * @param xpoints TODO + * @param ypoints TODO + * @param npoints TODO + */ + public void fillPolygon(int[] xpoints, int[] ypoints, int npoints) + { + graphics.fillPolygon(xpoints, ypoints, npoints); + } + + /** + * drawString + * + * @param string the string + * @param x the x coordinate + * @param y the y coordinate + */ + public void drawString(String string, int x, int y) + { + graphics.drawString(string, x, y); + } + + /** + * drawString + * + * @param iterator TODO + * @param x the x coordinate + * @param y the y coordinate + */ + public void drawString(AttributedCharacterIterator iterator, + int x, int y) + { + graphics.drawString(iterator, x, y); + } + + /** + * drawBytes + * + * @param data TODO + * @param offset TODO + * @param length TODO + * @param x the x coordinate + * @param y the y coordinate + */ + public void drawBytes(byte[] data, int offset, int length, + int x, int y) + { + graphics.drawBytes(data, offset, length, x, y); + } + + /** + * drawChars + * + * @param data array of characters to draw + * @param offset offset in array + * @param length number of characters in array to draw + * @param x x-position + * @param y y-position + */ + public void drawChars(char[] data, int offset, int length, + int x, int y) + { + 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); + } + + /** + * drawImage + * + * @param image The image to draw + * @param x The x position + * @param y The y position + * @param observer The image observer + * @return boolean + */ + public boolean drawImage(Image image, int x, int y, + ImageObserver observer) + { + return graphics.drawImage(image, x, y, observer); + } + + /** + * drawImage + * + * @param image The image to draw + * @param x The x position + * @param y The y position + * @param width The width of the area to draw the image + * @param height The height of the area to draw the image + * @param observer The image observer + * + * @return boolean + */ + public boolean drawImage(Image image, int x, int y, int width, + int height, ImageObserver observer) + { + return graphics.drawImage(image, x, y, width, height, observer); + } + + /** + * drawImage + * + * @param image The image to draw + * @param x The x position + * @param y The y position + * @param background The color for the background in the opaque regions + * of the image + * @param observer The image observer + * + * @return boolean + */ + public boolean drawImage(Image image, int x, int y, + Color background, ImageObserver observer) + { + return graphics.drawImage(image, x, y, background, observer); + } + + /** + * drawImage + * + * @param image The image to draw + * @param x The x position + * @param y The y position + * @param width The width of the area to draw the image + * @param height The height of the area to draw the image + * @param background The color for the background in the opaque regions + * of the image + * @param observer The image observer + * + * @return boolean + */ + public boolean drawImage(Image image, int x, int y, int width, int height, + Color background, ImageObserver observer) + { + return graphics.drawImage(image, x, y, width, height, background, observer); + } + + /** + * drawImage + * + * @param image The image to draw + * @param dx1 TODO + * @param dy1 TODO + * @param dx2 TODO + * @param dy2 TODO + * @param sx1 TODO + * @param sy1 TODO + * @param sx2 TODO + * @param sy2 TODO + * @param observer The image observer + * + * @return boolean + */ + public boolean drawImage(Image image, int dx1, int dy1, + int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) + { + return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + + /** + * drawImage + * + * @param image The image to draw + * @param dx1 TODO + * @param dy1 TODO + * @param dx2 TODO + * @param dy2 TODO + * @param sx1 TODO + * @param sy1 TODO + * @param sx2 TODO + * @param sy2 TODO + * @param background The color for the background in the opaque regions + * of the image + * @param observer The image observer + * + * @return boolean + */ + public boolean drawImage(Image image, int dx1, int dy1, + int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + Color background, ImageObserver observer) + { + return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, background, observer); + } + + /** + * copyArea + * + * @param x The x position of the source area + * @param y The y position of the source area + * @param width The width of the area + * @param height The height of the area + * @param destx The x position of the destination area + * @param desty The y posiiton of the destination area + */ + public void copyArea(int x, int y, int width, int height, + int destx, int desty) + { + graphics.copyArea(x, y, width, height, destx, desty); + } + + /** + * Releases all system resources that this Graphics is using. + */ + public void dispose() + { + graphics.dispose(); + graphics = null; + } + + /** + * isDrawingBuffer + * + * @return boolean + */ + public boolean isDrawingBuffer() + { + return false; // TODO + } + + /** + * setDebugOptions + * + * @param options the debug options + */ + public void setDebugOptions(int options) + { + debugOptions = options; + } + + /** + * getDebugOptions + * + * @return the debug options + */ + public int getDebugOptions() + { + return debugOptions; + } +} diff --git a/libjava/classpath/javax/swing/DefaultBoundedRangeModel.java b/libjava/classpath/javax/swing/DefaultBoundedRangeModel.java new file mode 100644 index 0000000..53c0fb3 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultBoundedRangeModel.java @@ -0,0 +1,443 @@ +/* DefaultBoundedRangeModel.java -- Default implementation + of BoundedRangeModel. + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * A default implementation of BoundedRangeModel. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class DefaultBoundedRangeModel + implements BoundedRangeModel, Serializable +{ + /** + * The identifier of this class in object serialization. Verified + * using the serialver tool of Sun J2SE 1.4.1_01. + */ + private static final long serialVersionUID = 5034068491295259790L; + + /** + * An event that is sent to all registered {@link ChangeListener}s + * when the state of this range model has changed. + * + *

The event object is created on demand, the first time it + * is actually needed.

+ * + * @see #fireStateChanged() + */ + protected transient ChangeEvent changeEvent; + + /** + * The list of the currently registered EventListeners. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * The current value of the range model, which is always between + * {@link #minimum} and ({@link #maximum} - {@link #extent}). In a + * scroll bar visualization of a {@link BoundedRangeModel}, the + * value is displayed as the position of the thumb. + */ + private int value; + + /** + * The current extent of the range model, which is a number greater + * than or equal to zero. In a scroll bar visualization of a {@link + * BoundedRangeModel}, the extent is displayed as the + * size of the thumb. + */ + private int extent; + + /** + * The current minimum value of the range model, which is always + * less than or equal to {@link #maximum}. + */ + private int minimum; + + /** + * The current maximum value of the range model, which is always + * greater than or equal to {@link #minimum}. + */ + private int maximum; + + /** + * A property that indicates whether the value of this {@link + * BoundedRangeModel} is going to change in the immediate future. + */ + private boolean isAdjusting; + + /** + * Constructs a DefaultBoundedRangeModel with default + * values for the properties. The properties value, + * extent and minimum will be initialized + * to zero; maximum will be set to 100; the property + * valueIsAdjusting will be false. + */ + public DefaultBoundedRangeModel() + { + // The fields value, extent, minimum have the default value 0, and + // isAdjusting is already false. These fields no not need to be + // set explicitly. + maximum = 100; + } + + /** + * Constructs a DefaultBoundedRangeModel with the + * specified values for some properties. + * + * @param value the initial value of the range model, which must be + * a number between minimum and (maximum - + * extent). In a scroll bar visualization of a {@link + * BoundedRangeModel}, the value is displayed as the + * position of the thumb. + * @param extent the initial extent of the range model, which is a + * number greater than or equal to zero. In a scroll bar + * visualization of a {@link BoundedRangeModel}, the + * extent is displayed as the size of the thumb. + * @param minimum the initial minimal value of the range model. + * @param maximum the initial maximal value of the range model. + * + * @throws IllegalArgumentException if the following condition is + * not satisfied: minimum <= value <= value + extent <= + * maximum. + */ + public DefaultBoundedRangeModel(int value, int extent, int minimum, + int maximum) + { + if (!(minimum <= value && extent >= 0 && (value + extent) <= maximum)) + throw new IllegalArgumentException(); + + this.value = value; + this.extent = extent; + this.minimum = minimum; + this.maximum = maximum; + + // The isAdjusting field already has a false value by default. + } + + /** + * Returns a string with all relevant properties of this range + * model. + * + * @return a string representing the object + */ + public String toString() + { + return getClass().getName() + + "[value=" + value + + ", extent=" + extent + + ", min=" + minimum + + ", max=" + maximum + + ", adj=" + isAdjusting + + ']'; + } + + /** + * Returns the current value of this bounded range model. In a + * scroll bar visualization of a {@link BoundedRangeModel}, the + * value is displayed as the position of the thumb. + * + * @return the value + */ + public int getValue() + { + return value; + } + + /** + * Changes the current value of this bounded range model. In a + * scroll bar visualization of a {@link BoundedRangeModel}, the + * value is displayed as the position of the thumb; + * changing the value of a scroll bar's model + * thus moves the thumb to a different position. + * + * @param value the value + */ + public void setValue(int value) + { + value = Math.max(minimum, value); + if (value + extent > maximum) + value = maximum - extent; + + if (value != this.value) + { + this.value = value; + fireStateChanged(); + } + } + + /** + * Returns the current extent of this bounded range model, which is + * a number greater than or equal to zero. In a scroll bar + * visualization of a {@link BoundedRangeModel}, the + * extent is displayed as the size of the thumb. + * + * @return the extent + */ + public int getExtent() + { + return extent; + } + + /** + * Changes the current extent of this bounded range model. In a + * scroll bar visualization of a {@link BoundedRangeModel}, the + * extent is displayed as the size of the thumb. + * + * @param extent the new extent of the range model, which is a + * number greater than or equal to zero. + */ + public void setExtent(int extent) + { + extent = Math.max(extent, 0); + if (value + extent > maximum) + extent = maximum - value; + + if (extent != this.extent) + { + this.extent = extent; + fireStateChanged(); + } + } + + /** + * Returns the current minimal value of this bounded range model. + */ + public int getMinimum() + { + return minimum; + } + + /** + * Changes the current minimal value of this bounded range model. + * + * @param minimum the new minimal value. + */ + public void setMinimum(int minimum) + { + int value, maximum; + + maximum = Math.max(minimum, this.maximum); + value = Math.max(minimum, this.value); + + setRangeProperties(value, extent, minimum, maximum, isAdjusting); + } + + /** + * Returns the current maximal value of this bounded range model. + * + * @return the maximum + */ + public int getMaximum() + { + return maximum; + } + + /** + * Changes the current maximal value of this bounded range model. + * + * @param maximum the new maximal value. + */ + public void setMaximum(int maximum) + { + int value, extent, minimum; + + minimum = Math.min(this.minimum, maximum); + extent = Math.min(this.extent, maximum - minimum); + value = Math.min(this.value, maximum - extent); + + setRangeProperties(value, extent, minimum, maximum, isAdjusting); + } + + /** + * Returns whether or not the value of this bounded range model is + * going to change in the immediate future. Scroll bars set this + * property to true while the thumb is being dragged + * around; when the mouse is relased, they set the property to + * false and post a final {@link ChangeEvent}. + * + * @return true if the value will change soon again; + * false if the value will probably not change soon. + */ + public boolean getValueIsAdjusting() + { + return isAdjusting; + } + + /** + * Specifies whether or not the value of this bounded range model is + * going to change in the immediate future. Scroll bars set this + * property to true while the thumb is being dragged + * around; when the mouse is relased, they set the property to + * false. + * + * @param isAdjusting true if the value will change + * soon again; false if the value will probably not + * change soon. + */ + public void setValueIsAdjusting(boolean isAdjusting) + { + if (isAdjusting == this.isAdjusting) + return; + + this.isAdjusting = isAdjusting; + fireStateChanged(); + } + + /** + * Sets all properties. + * + * @param value the new value of the range model. In a scroll bar + * visualization of a {@link BoundedRangeModel}, the + * value is displayed as the position of the thumb. + * @param extent the new extent of the range model, which is a + * number greater than or equal to zero. In a scroll bar + * visualization of a {@link BoundedRangeModel}, the + * extent is displayed as the size of the thumb. + * @param minimum the new minimal value of the range model. + * @param maximum the new maximal value of the range model. + * @param isAdjusting whether or not the value of this bounded range + * model is going to change in the immediate future. Scroll bars set + * this property to true while the thumb is being + * dragged around; when the mouse is relased, they set the property + * to false. + */ + public void setRangeProperties(int value, int extent, int minimum, + int maximum, boolean isAdjusting) + { + minimum = Math.min(Math.min(minimum, maximum), value); + maximum = Math.max(value, maximum); + if (extent + value > maximum) + extent = maximum - value; + extent = Math.max(0, extent); + + if ((value == this.value) + && (extent == this.extent) + && (minimum == this.minimum) + && (maximum == this.maximum) + && (isAdjusting == this.isAdjusting)) + return; + + this.value = value; + this.extent = extent; + this.minimum = minimum; + this.maximum = maximum; + this.isAdjusting = isAdjusting; + + fireStateChanged(); + } + + /** + * Subscribes a ChangeListener to state changes. + * + * @param listener the listener to be subscribed. + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * Cancels the subscription of a ChangeListener. + * + * @param listener the listener to be unsubscribed. + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * Sends a {@link ChangeEvent} to any registered {@link + * ChangeListener}s. + * + * @see #addChangeListener(ChangeListener) + * @see #removeChangeListener(ChangeListener) + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + if (changeEvent == null) + changeEvent = new ChangeEvent(this); + + for (int i = listeners.length - 1; i >= 0; --i) + listeners[i].stateChanged(changeEvent); + } + + /** + * Retrieves the current listeners of the specified class. + * + * @param c the class of listeners; usually {@link + * ChangeListener}.class. + * + * @return an array with the currently subscribed listeners, or + * an empty array if there are currently no listeners. + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Returns all ChangeListeners that are currently + * subscribed for changes to this + * DefaultBoundedRangeModel. + * + * @return an array with the currently subscribed listeners, or + * an empty array if there are currently no listeners. + * + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) getListeners(ChangeListener.class); + } +} diff --git a/libjava/classpath/javax/swing/DefaultButtonModel.java b/libjava/classpath/javax/swing/DefaultButtonModel.java new file mode 100644 index 0000000..2cfb9e9 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultButtonModel.java @@ -0,0 +1,575 @@ +/* DefaultButtonModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * The pUrpose of this class is to model the dynamic state of an abstract + * button. The concrete button type holding this state may be a a "toggle" + * button (checkbox, radio button) or a "push" button (menu button, button). + * If the model is disabled, only the "selected" property can be changed. An + * attempt to change the "armed", "rollover" or "pressed" properties while + * the model is disabled will be blocked. Any successful (non-blocked) change + * to the model's properties will trigger the firing of a ChangeEvent. Any + * change to the "selected" property will trigger the firing of an ItemEvent + * in addition to ChangeEvent. This is true whether the model is enabled or + * not. One other state change is special: the transition from "enabled, + * armed and pressd" to "enabled, armed and not-pressed". This is considered + * the "trailing edge" of a successful mouse click, and therefore fires an + * ActionEvent in addition to a ChangeEvent. In all other respects this class + * is just a container of boolean flags. + * + * @author Graydon Hoare (graydon_at_redhat.com) + */ +public class DefaultButtonModel implements ButtonModel, Serializable +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -5342609566534980231L; + + /** + * Indicates that the button is partially committed to being + * pressed, but not entirely. This usually happens when a user has pressed + * but not yet released the mouse button. + */ + public static final int ARMED = 1; + + /** + * State constant indicating that the button is enabled. Buttons cannot be + * pressed or selected unless they are enabled. + */ + public static final int ENABLED = 8; + + /** + * State constant indicating that the user is holding down the button. When + * this transitions from true to false, an ActionEvent may be fired, + * depending on the value of the "armed" property. + */ + public static final int PRESSED = 4; + + /** + * State constant indicating that the mouse is currently positioned over the + * button. + */ + public static final int ROLLOVER = 16; + + /** + * State constant indicating that the button is selected. This constant is + * only meaningful for toggle-type buttons (radio buttons, checkboxes). + */ + public static final int SELECTED = 2; + + /** + * Represents the "state properties" (armed, enabled, pressed, rollover and + * selected) by a bitwise combination of integer constants. + */ + protected int stateMask = ENABLED; + + /** + * List of ItemListeners, ChangeListeners, and ActionListeners registered on + * this model. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** The single ChangeEvent this model (re)uses to call its ChangeListeners. */ + protected ChangeEvent changeEvent = new ChangeEvent(this); + + /** + * The group this model belongs to. Only one button in a group may be + * selected at any given time. + */ + protected ButtonGroup group; + + /** + * The key code (one of {@link java.awt.event.KeyEvent} VK_) used to press + * this button via a keyboard interface. + */ + protected int mnemonic = KeyEvent.VK_UNDEFINED; + + /** + * The string used as the "command" property of any ActionEvent this model + * sends. + */ + protected String actionCommand; + + /** + * Creates a new DefaultButtonModel object. + */ + public DefaultButtonModel() + { + } + + /** + * Return null. Use {@link AbstractButton} if you wish to + * interface with a button via an {@link ItemSelectable} interface. + * + * @return null + */ + public Object[] getSelectedObjects() + { + return null; + } + + /** + * Returns a specified class of listeners. + * + * @param listenerType the type of listener to return + * + * @return array of listeners + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Add an ActionListener to the model. Usually only called to subscribe an + * AbstractButton's listener to the model. + * + * @param l The listener to add + */ + public void addActionListener(ActionListener l) + { + listenerList.add(ActionListener.class, l); + } + + /** + * Remove an ActionListener to the model. Usually only called to unsubscribe + * an AbstractButton's listener to the model. + * + * @param l The listener to remove + */ + public void removeActionListener(ActionListener l) + { + listenerList.remove(ActionListener.class, l); + } + + /** + * Returns all registered ActionListener objects. + * + * @return array of ActionListener objects + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) listenerList.getListeners(ActionListener.class); + } + + /** + * Add an ItemListener to the model. Usually only called to subscribe an + * AbstractButton's listener to the model. + * + * @param l The listener to add + */ + public void addItemListener(ItemListener l) + { + listenerList.add(ItemListener.class, l); + } + + /** + * Remove an ItemListener to the model. Usually only called to unsubscribe + * an AbstractButton's listener to the model. + * + * @param l The listener to remove + */ + public void removeItemListener(ItemListener l) + { + listenerList.remove(ItemListener.class, l); + } + + /** + * Returns all registered ItemListener objects. + * + * @return array of ItemListener objects + */ + public ItemListener[] getItemListeners() + { + return (ItemListener[]) listenerList.getListeners(ItemListener.class); + } + + /** + * Add a ChangeListener to the model. Usually only called to subscribe an + * AbstractButton's listener to the model. + * + * @param l The listener to add + */ + public void addChangeListener(ChangeListener l) + { + listenerList.add(ChangeListener.class, l); + } + + /** + * Remove a ChangeListener to the model. Usually only called to unsubscribe + * an AbstractButton's listener to the model. + * + * @param l The listener to remove + */ + public void removeChangeListener(ChangeListener l) + { + listenerList.remove(ChangeListener.class, l); + } + + /** + * Returns all registered ChangeListener objects. + * + * @return array of ChangeListener objects + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Inform each ItemListener in the {@link listenerList} that an ItemEvent + * has occurred. This happens in response to any change to the {@link + * stateMask} field. + * + * @param e The ItemEvent to fire + */ + protected void fireItemStateChanged(ItemEvent e) + { + ItemListener[] ll = getItemListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].itemStateChanged(e); + } + + /** + * Inform each ActionListener in the {@link listenerList} that an + * ActionEvent has occurred. This happens in response to the any change to + * the {@link stateMask} field which makes the enabled, armed and pressed + * properties all simultaneously true. + * + * @param e The ActionEvent to fire + */ + protected void fireActionPerformed(ActionEvent e) + { + ActionListener[] ll = getActionListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].actionPerformed(e); + } + + /** + * Inform each ChangeListener in the {@link listenerList} that a ChangeEvent + * has occurred. This happens in response to the any change to a property + * of the model. + */ + protected void fireStateChanged() + { + ChangeListener[] ll = getChangeListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].stateChanged(changeEvent); + } + + /** + * Get the value of the model's "armed" property. + * + * @return The current "armed" property + */ + public boolean isArmed() + { + return (stateMask & ARMED) == ARMED; + } + + /** + * Set the value of the model's "armed" property. + * + * @param a The new "armed" property + */ + public void setArmed(boolean a) + { + // if this call does not represent a CHANGE in state, then return + if ((a && isArmed()) || (!a && !isArmed())) + return; + + // cannot change ARMED state unless button is enabled + if (!isEnabled()) + return; + + // make the change + if (a) + stateMask = stateMask | ARMED; + else + stateMask = stateMask & (~ARMED); + + // notify interested ChangeListeners + fireStateChanged(); + } + + /** + * Get the value of the model's "enabled" property. + * + * @return The current "enabled" property. + */ + public boolean isEnabled() + { + return (stateMask & ENABLED) == ENABLED; + } + + /** + * Set the value of the model's "enabled" property. + * + * @param e The new "enabled" property + */ + public void setEnabled(boolean e) + { + // if this call does not represent a CHANGE in state, then return + if ((e && isEnabled()) || (!e && !isEnabled())) + return; + + // make the change + if (e) + stateMask = stateMask | ENABLED; + else + stateMask = stateMask & (~ENABLED); + + // notify interested ChangeListeners + fireStateChanged(); + } + + /** + * Set the value of the model's "pressed" property. + * + * @param p The new "pressed" property + */ + public void setPressed(boolean p) + { + // if this call does not represent a CHANGE in state, then return + if ((p && isPressed()) || (!p && !isPressed())) + return; + + // cannot changed PRESSED state unless button is enabled + if (!isEnabled()) + return; + + // make the change + if (p) + stateMask = stateMask | PRESSED; + else + stateMask = stateMask & (~PRESSED); + + // notify interested ChangeListeners + fireStateChanged(); + + // if button is armed and was released, fire action event + if (!p && isArmed()) + fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, + actionCommand)); + } + + /** + * Get the value of the model's "pressed" property. + * + * @return The current "pressed" property + */ + public boolean isPressed() + { + return (stateMask & PRESSED) == PRESSED; + } + + /** + * Set the value of the model's "rollover" property. + * + * @param r The new "rollover" property + */ + public void setRollover(boolean r) + { + // if this call does not represent a CHANGE in state, then return + if ((r && isRollover()) || (!r && !isRollover())) + return; + + // cannot set ROLLOVER property unless button is enabled + if (!isEnabled()) + return; + + // make the change + if (r) + stateMask = stateMask | ROLLOVER; + else + stateMask = stateMask & (~ROLLOVER); + + // notify interested ChangeListeners + fireStateChanged(); + } + + /** + * Set the value of the model's "selected" property. + * + * @param s The new "selected" property + */ + public void setSelected(boolean s) + { + // if this call does not represent a CHANGE in state, then return + if ((s && isSelected()) || (!s && !isSelected())) + return; + + // make the change + if (s) + stateMask = stateMask | SELECTED; + else + stateMask = stateMask & (~SELECTED); + + // notify interested ChangeListeners + fireStateChanged(); + + // fire ItemStateChanged events + if (s) + { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + null, ItemEvent.SELECTED)); + if (group != null) + group.setSelected(this, true); + } + else + { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + null, ItemEvent.DESELECTED)); + if (group != null) + group.setSelected(this, false); + } + } + + /** + * Get the value of the model's "selected" property. + * + * @return The current "selected" property + */ + public boolean isSelected() + { + return (stateMask & SELECTED) == SELECTED; + } + + /** + * Get the value of the model's "rollover" property. + * + * @return The current "rollover" property + */ + public boolean isRollover() + { + return (stateMask & ROLLOVER) == ROLLOVER; + } + + /** + * Get the value of the model's "mnemonic" property. + * + * @return The current "mnemonic" property + */ + public int getMnemonic() + { + return mnemonic; + } + + /** + * Set the value of the model's "mnemonic" property. + * + * @param key The new "mnemonic" property + */ + public void setMnemonic(int key) + { + if (mnemonic != key) + { + mnemonic = key; + fireStateChanged(); + } + } + + /** + * Set the value of the model's "actionCommand" property. This property is + * used as the "command" property of the {@link ActionEvent} fired from the + * model. + * + * @param s The new "actionCommand" property. + */ + public void setActionCommand(String s) + { + if (actionCommand != s) + { + actionCommand = s; + fireStateChanged(); + } + } + + /** + * Returns the current value of the model's "actionCommand" property. + * + * @return The current "actionCommand" property + */ + public String getActionCommand() + { + return actionCommand; + } + + /** + * Set the value of the model's "group" property. The model is said to be a + * member of the {@link ButtonGroup} held in its "group" property, and only + * one model in a given group can have their "selected" property be + * true at a time. + * + * @param g The new "group" property + */ + public void setGroup(ButtonGroup g) + { + if (group != g) + { + group = g; + fireStateChanged(); + } + } + + /** + * Returns the current value of the model's "group" property. + * + * @return The value of the "group" property + */ + public ButtonGroup getGroup() + { + return group; + } +} diff --git a/libjava/classpath/javax/swing/DefaultCellEditor.java b/libjava/classpath/javax/swing/DefaultCellEditor.java new file mode 100644 index 0000000..e67e2f5 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultCellEditor.java @@ -0,0 +1,344 @@ +/* DefaultCellEditor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.Serializable; +import java.util.EventObject; + +import javax.swing.table.TableCellEditor; +import javax.swing.tree.TreeCellEditor; + +/** + * DefaultCellEditor + * @author Andrew Selkirk + * @version 1.0 + */ +public class DefaultCellEditor + extends AbstractCellEditor + implements TableCellEditor, TreeCellEditor +{ + private static final long serialVersionUID = 3564035141373880027L; + + /** + * EditorDelegate + */ + protected class EditorDelegate + implements ActionListener, ItemListener, Serializable + { + private static final long serialVersionUID = -1420007406015481933L; + + /** + * value + */ + protected Object value; + + /** + * Constructor EditorDelegate + * + * @param value0 TODO + */ + protected EditorDelegate() + { + } + + /** + * setValue + * + * @param event TODO + */ + public void setValue(Object event) + { + } + + /** + * getCellEditorValue + * + * @returns Object + */ + public Object getCellEditorValue() + { + return null; // TODO + } // getCellEditorValue() + + /** + * isCellEditable + * + * @param event TODO + * + * @returns boolean + */ + public boolean isCellEditable(EventObject event) + { + return false; // TODO + } // isCellEditable() + + /** + * shouldSelectCell + * + * @param event TODO + * + * @returns boolean + */ + public boolean shouldSelectCell(EventObject event) + { + return false; // TODO + } // shouldSelectCell() + + /** + * stopCellEditing + * + * @returns boolean + */ + public boolean stopCellEditing() + { + return false; // TODO + } // stopCellEditing() + + /** + * cancelCellEditing + */ + public void cancelCellEditing() + { + // TODO + } // cancelCellEditing() + + /** + * startCellEditing + * + * @param event TODO + * + * @returns boolean + */ + public boolean startCellEditing(EventObject event) + { + return false; // TODO + } // startCellEditing() + + /** + * actionPerformed + * + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } // actionPerformed() + + /** + * itemStateChanged + * + * @param event TODO + */ + public void itemStateChanged(ItemEvent event) + { + // TODO + } // itemStateChanged() + + } // EditorDelegate + + /** + * editorComponent + */ + protected JComponent editorComponent; + + /** + * delegate + */ + protected EditorDelegate delegate; + + /** + * clickCountToStart + */ + protected int clickCountToStart; + + /** + * Constructor DefaultCellEditor + * + * @param textfield TODO + */ + public DefaultCellEditor(JTextField textfield) + { + // TODO + } // DefaultCellEditor() + + /** + * Constructor DefaultCellEditor + * + * @param checkbox TODO + */ + public DefaultCellEditor(JCheckBox checkbox) + { + // TODO + } // DefaultCellEditor() + + /** + * Constructor DefaultCellEditor + * + * @param combobox TODO + */ + public DefaultCellEditor(JComboBox combobox) + { + // TODO + } // DefaultCellEditor() + + /** + * getComponent + * + * @returns Component + */ + public Component getComponent() + { + return null; // TODO + } // getComponent() + + /** + * getClickCountToStart + * + * @returns int + */ + public int getClickCountToStart() + { + return 0; // TODO + } // getClickCountToStart() + + /** + * setClickCountToStart + * + * @param count TODO + */ + public void setClickCountToStart(int count) + { + // TODO + } // setClickCountToStart() + + /** + * getCellEditorValue + * + * @returns Object + */ + public Object getCellEditorValue() + { + return null; // TODO + } // getCellEditorValue() + + /** + * isCellEditable + * + * @param event TODO + * + * @returns boolean + */ + public boolean isCellEditable(EventObject event) + { + return false; // TODO + } // isCellEditable() + + /** + * shouldSelectCell + * + * @param event TODO + * + * @returns boolean + */ + public boolean shouldSelectCell(EventObject event) + { + return false; // TODO + } // shouldSelectCell() + + /** + * stopCellEditing + * + * @returns boolean + */ + public boolean stopCellEditing() + { + return false; // TODO + } // stopCellEditing() + + /** + * cancelCellEditing + */ + public void cancelCellEditing() + { + // TODO + } // cancelCellEditing() + + /** + * getTreeCellEditorComponent + * + * @param tree TODO + * @param value TODO + * @param isSelected TODO + * @param expanded TODO + * @param leaf TODO + * @param row TODO + * + * @returns Component + */ + public Component getTreeCellEditorComponent(JTree tree, Object value, + boolean isSelected, + boolean expanded, boolean leaf, + int row) + { + return null; // TODO + } // getTreeCellEditorComponent() + + /** + * getTableCellEditorComponent + * + * @param tree TODO + * @param value TODO + * @param isSelected TODO + * @param row TODO + * @param column TODO + * + * @returns Component + */ + public Component getTableCellEditorComponent(JTable tree, Object value, + boolean isSelected, int row, + int column) + { + return null; // TODO + } // getTableCellEditorComponent() +} diff --git a/libjava/classpath/javax/swing/DefaultComboBoxModel.java b/libjava/classpath/javax/swing/DefaultComboBoxModel.java new file mode 100644 index 0000000..1cea886 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultComboBoxModel.java @@ -0,0 +1,238 @@ +/* DefaultComboBoxModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Vector; + + +/** + * DefaultComboBoxModel is a data model for JComboBox. 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. + * + * @author Andrew Selkirk + * @author Olga Rodimina + * @author Robert Schuster + * @version 1.0 + */ +public class DefaultComboBoxModel extends AbstractListModel + implements MutableComboBoxModel, Serializable +{ + private static final long serialVersionUID = 6698657703676921904L; + + /** + * List containing items in the combo box + */ + private Vector list; + + /** + * Currently selected item in the combo box list + */ + private Object selectedItem = null; + + /** + * Constructor DefaultComboBoxModel. Create empty JComboBox. + */ + public DefaultComboBoxModel() + { + list = new Vector(); + } + + /** + * Constructs new DefaultComboBoxModel object and initializes its item list + * to values in the given array. + * + * @param items array containing items of the combo box. + */ + public DefaultComboBoxModel(Object[] items) + { + list = new Vector(Arrays.asList(items)); + } + + /** + * Consturcts new DefaultComboBoxModel object and initializes its item list + * to values in the given vector. + * + * @param vector Vector containing items for this combo box. + */ + public DefaultComboBoxModel(Vector vector) + { + this.list = vector; + } + + /** + * 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. + * + * @param object item to add to the combo box list + */ + public void addElement(Object object) + { + list.add(object); + fireIntervalAdded(this, list.size() - 1, list.size()); + } + + /** + * 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. + * + * @param index index specifying location of the element to remove in the + * combo box list. + */ + public void removeElementAt(int index) + { + list.remove(index); + 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. + * + * @param object element to insert + * @param index index specifing position in the list where given element + * should be inserted. + */ + public void insertElementAt(Object object, int index) + { + list.insertElementAt(object, index); + fireIntervalAdded(this, index, index); + } + + /** + * 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. + * + * @param object Element that will be removed from the combo box list + */ + public void removeElement(Object object) + { + int index = getIndexOf(object); + if (index != -1) + removeElementAt(index); + } + + /** + * 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. + */ + public void removeAllElements() + { + list.clear(); + int listSize = getSize(); + fireIntervalAdded(this, 0, listSize); + } + + /** + * Returns number of items in the combo box list + * + * @return number of items in the combo box list + */ + public int getSize() + { + return list.size(); + } + + /** + * 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. + * + *

If the given object is not contained in the combo box list then nothing + * happens.

+ * + * @param object item to select in the JComboBox + */ + 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); + } + + } + + /** + * Returns currently selected item in the combo box list + * + * @return currently selected item in the combo box list + */ + public Object getSelectedItem() + { + return selectedItem; + } + + /** + * Returns element in the combo box list located at the given index + * + * @param index specifying location of the element in the list + * + * @return return element in the combo box list located at the given index + */ + public Object getElementAt(int index) + { + return list.elementAt(index); + } + + /** + * Returns index of the specified object in the combo box list. + * + * @param object element to look for in the combo box list . + * + * @return Index specifying position of the specified element in combo box + * list. + */ + public int getIndexOf(Object object) + { + return list.indexOf(object); + } +} diff --git a/libjava/classpath/javax/swing/DefaultDesktopManager.java b/libjava/classpath/javax/swing/DefaultDesktopManager.java new file mode 100644 index 0000000..15ed262 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultDesktopManager.java @@ -0,0 +1,629 @@ +/* DefaultDesktopManager.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.Rectangle; +import java.beans.PropertyVetoException; +import java.io.Serializable; + +import javax.swing.JInternalFrame.JDesktopIcon; + +/** + * DefaultDesktopManager is the default implementation of DesktopManager for + * swing. It implements the basic beaviours for JInternalFrames in arbitrary + * parents. The methods provided by the class are not meant to be called by + * the user, instead, the JInternalFrame methods will call these methods. + */ +public class DefaultDesktopManager implements DesktopManager, Serializable +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = 4657624909838017887L; + + /** The property change event fired when the wasIcon property changes. */ + static final String WAS_ICON_ONCE_PROPERTY = "wasIconOnce"; + + /** + * The method of dragging used by the JDesktopPane that parents the + * JInternalFrame that is being dragged. + */ + private int currentDragMode = 0; + + /** + * The cache of the bounds used to draw the outline rectangle when + * OUTLINE_DRAG_MODE is used. + */ + private transient Rectangle dragCache = new Rectangle(); + + /** + * A cached JDesktopPane that is stored when the JInternalFrame is initially + * dragged. + */ + private transient Container pane; + + /** + * An array of Rectangles that holds the bounds of the JDesktopIcons in the + * JDesktopPane when looking for where to place a new icon. + */ + private transient Rectangle[] iconRects; + + /** + * This creates a new DefaultDesktopManager object. + */ + public DefaultDesktopManager() + { + } + + /** + * This method is not normally called since the user will typically add the + * JInternalFrame to a Container. If this is called, it will try to + * determine the parent of the JInternalFrame and remove any icon that + * represents this JInternalFrame and add this JInternalFrame. + * + * @param frame The JInternalFrame to open. + */ + public void openFrame(JInternalFrame frame) + { + Container c = frame.getParent(); + if (c == null) + c = frame.getDesktopIcon().getParent(); + if (c == null) + return; + + c.remove(frame.getDesktopIcon()); + c.add(frame); + frame.setVisible(true); + } + + /** + * This method removes the JInternalFrame and JDesktopIcon (if one is + * present) from their parents. + * + * @param frame The JInternalFrame to close. + */ + public void closeFrame(JInternalFrame frame) + { + Container c = frame.getParent(); + frame.doDefaultCloseAction(); + + if (c != null) + { + if (frame.isIcon()) + c.remove(frame.getDesktopIcon()); + else + c.remove(frame); + c.repaint(); + } + } + + /** + * This method resizes the JInternalFrame to match its parent's bounds. + * + * @param frame The JInternalFrame to maximize. + */ + public void maximizeFrame(JInternalFrame frame) + { + // Can't maximize from iconified state. + // It can only return to maximized state, but that would fall under + // deiconify. + if (frame.isIcon()) + return; + frame.setNormalBounds(frame.getBounds()); + + Container p = frame.getParent(); + if (p != null) + { + Rectangle pBounds = p.getBounds(); + Insets insets = p.getInsets(); + pBounds.width -= insets.left + insets.right; + pBounds.height -= insets.top + insets.bottom; + + setBoundsForFrame(frame, 0, 0, pBounds.width, pBounds.height); + } + if (p instanceof JDesktopPane) + ((JDesktopPane) p).setSelectedFrame(frame); + else + { + try + { + frame.setSelected(true); + } + catch (PropertyVetoException e) + { + // Do nothing. + } + } + } + + /** + * This method restores the JInternalFrame's bounds to what they were + * previous to the setMaximize call. + * + * @param frame The JInternalFrame to minimize. + */ + public void minimizeFrame(JInternalFrame frame) + { + Rectangle normalBounds = frame.getNormalBounds(); + + JDesktopPane p = frame.getDesktopPane(); + if (p != null) + p.setSelectedFrame(frame); + else + { + try + { + frame.setSelected(true); + } + catch (PropertyVetoException e) + { + // Do nothing. + } + } + + setBoundsForFrame(frame, normalBounds.x, normalBounds.y, + normalBounds.width, normalBounds.height); + } + + /** + * This method removes the JInternalFrame from its parent and adds its + * JDesktopIcon representation. + * + * @param frame The JInternalFrame to iconify. + */ + public void iconifyFrame(JInternalFrame frame) + { + JDesktopPane p = frame.getDesktopPane(); + JDesktopIcon icon = frame.getDesktopIcon(); + if (p != null && p.getSelectedFrame() == frame) + p.setSelectedFrame(null); + else + { + try + { + frame.setSelected(false); + } + catch (PropertyVetoException e) + { + } + } + + Container c = frame.getParent(); + + if (!wasIcon(frame)) + { + Rectangle r = getBoundsForIconOf(frame); + icon.setBounds(r); + setWasIcon(frame, Boolean.TRUE); + } + + if (c != null) + { + if (icon != null) + { + c.add(icon); + icon.setVisible(true); + } + c.remove(frame); + } + } + + /** + * This method removes the JInternalFrame's JDesktopIcon representation and + * adds the JInternalFrame back to its parent. + * + * @param frame The JInternalFrame to deiconify. + */ + public void deiconifyFrame(JInternalFrame frame) + { + JDesktopIcon icon = frame.getDesktopIcon(); + Container c = icon.getParent(); + + removeIconFor(frame); + c.add(frame); + frame.setVisible(true); + + if (!frame.isSelected()) + { + JDesktopPane p = frame.getDesktopPane(); + if (p != null) + p.setSelectedFrame(frame); + else + { + try + { + frame.setSelected(true); + } + catch (PropertyVetoException e) + { + // Do nothing. + } + } + } + + c.invalidate(); + } + + /** + * This method activates the JInternalFrame by moving it to the front and + * selecting it. + * + * @param frame The JInternalFrame to activate. + */ + public void activateFrame(JInternalFrame frame) + { + JDesktopPane p = frame.getDesktopPane(); + + if (p != null) + p.setSelectedFrame(frame); + else + { + try + { + frame.setSelected(true); + } + catch (PropertyVetoException e) + { + } + } + + frame.toFront(); + } + + /** + * This method is called when the JInternalFrame loses focus. + * + * @param frame The JInternalFram to deactivate. + */ + public void deactivateFrame(JInternalFrame frame) + { + JDesktopPane p = frame.getDesktopPane(); + if (p != null) + { + if (p.getSelectedFrame() == frame) + p.setSelectedFrame(null); + } + else + { + try + { + frame.setSelected(false); + } + catch (PropertyVetoException e) + { + } + } + } + + /** + * This method is called to indicate that the DesktopManager should prepare + * to drag the JInternalFrame. Any state information needed to drag the + * frame will be prepared now. + * + * @param component The JComponent to drag, usually a JInternalFrame. + */ + public void beginDraggingFrame(JComponent component) + { + if (component instanceof JDesktopIcon) + pane = ((JDesktopIcon) component).getInternalFrame().getDesktopPane(); + else + pane = ((JInternalFrame) component).getDesktopPane(); + if (pane == null) + return; + + dragCache = component.getBounds(); + + if (! (pane instanceof JDesktopPane)) + currentDragMode = JDesktopPane.LIVE_DRAG_MODE; + else + currentDragMode = ((JDesktopPane) pane).getDragMode(); + } + + /** + * This method is called to drag the JInternalFrame to a new location. + * + * @param component The JComponent to drag, usually a JInternalFrame. + * + * @param newX The new x coordinate. + * @param newY The new y coordinate. + */ + public void dragFrame(JComponent component, int newX, int newY) + { + if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE) + { + // FIXME: Do outline drag mode painting. + } + else + { + Rectangle b = component.getBounds(); + if (component instanceof JDesktopIcon) + component.setBounds(newX, newY, b.width, b.height); + else + setBoundsForFrame((JInternalFrame) component, newX, newY, b.width, + b.height); + } + } + + /** + * This method indicates that the dragging is done. Any state information + * stored by the DesktopManager can be cleared. + * + * @param component The JComponent that has finished dragging. + */ + public void endDraggingFrame(JComponent component) + { + if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE) + { + setBoundsForFrame((JInternalFrame) component, dragCache.x, dragCache.y, + dragCache.width, dragCache.height); + pane = null; + dragCache = null; + } + component.repaint(); + } + + /** + * This method is called to indicate that the given JComponent will be + * resized. Any state information necessary to resize the JComponent will + * be prepared now. + * + * @param component The JComponent to resize, usually a JInternalFrame. + * @param direction The direction to drag in (a SwingConstant). + */ + public void beginResizingFrame(JComponent component, int direction) + { + pane = ((JInternalFrame) component).getDesktopPane(); + if (pane == null) + return; + + dragCache = component.getBounds(); + if (! (pane instanceof JDesktopPane)) + currentDragMode = JDesktopPane.LIVE_DRAG_MODE; + else + currentDragMode = ((JDesktopPane) pane).getDragMode(); + } + + /** + * This method resizes the give JComponent. + * + * @param component The JComponent to resize. + * @param newX The new x coordinate. + * @param newY The new y coordinate. + * @param newWidth The new width. + * @param newHeight The new height. + */ + public void resizeFrame(JComponent component, int newX, int newY, + int newWidth, int newHeight) + { + dragCache.setBounds(newX, newY, newWidth, newHeight); + + if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE) + { + // FIXME: Do outline drag painting. + } + else + setBoundsForFrame(component, dragCache.x, dragCache.y, dragCache.width, + dragCache.height); + } + + /** + * This method is called to indicate that the given JComponent has finished + * dragging. Any state information stored by the DesktopManager can be + * cleared. + * + * @param component The JComponent that finished resizing. + */ + public void endResizingFrame(JComponent component) + { + if (currentDragMode == JDesktopPane.OUTLINE_DRAG_MODE) + { + setBoundsForFrame((JInternalFrame) component, dragCache.x, dragCache.y, + dragCache.width, dragCache.height); + pane = null; + dragCache = null; + } + component.repaint(); + } + + /** + * This method calls setBounds with the given parameters and repaints the + * JComponent. + * + * @param component The JComponent to set bounds for. + * @param newX The new x coordinate. + * @param newY The new y coordinate. + * @param newWidth The new width. + * @param newHeight The new height. + */ + public void setBoundsForFrame(JComponent component, int newX, int newY, + int newWidth, int newHeight) + { + component.setBounds(newX, newY, newWidth, newHeight); + component.revalidate(); + + // If not null, I'd rather repaint the parent + if (component.getParent() != null) + component.getParent().repaint(); + else + component.repaint(); + } + + /** + * This is a helper method that removes the JDesktopIcon of the given + * JInternalFrame from the parent. + * + * @param frame The JInternalFrame to remove an icon for. + */ + protected void removeIconFor(JInternalFrame frame) + { + JDesktopIcon icon = frame.getDesktopIcon(); + Container c = icon.getParent(); + if (c != null && icon != null) + c.remove(icon); + } + + /** + * This method is called by iconifyFrame to determine the bounds of the + * JDesktopIcon for the given JInternalFrame. + * + * @param frame The JInternalFrame to find the bounds of its JDesktopIcon + * for. + * + * @return The bounds of the JDesktopIcon. + */ + protected Rectangle getBoundsForIconOf(JInternalFrame frame) + { + // IconRects has no order to it. + // The icon _must_ be placed in the first free slot (working from + // the bottom left corner) + // The icon also must not be placed where another icon is placed + // (regardless whether that frame is an icon currently or not) + JDesktopPane desktopPane = frame.getDesktopPane(); + + if (desktopPane == null) + return frame.getDesktopIcon().getBounds(); + + Rectangle paneBounds = desktopPane.getBounds(); + Insets insets = desktopPane.getInsets(); + Dimension pref = frame.getDesktopIcon().getPreferredSize(); + + Component[] frames = desktopPane.getComponents(); + + int count = 0; + for (int i = 0, j = 0; i < frames.length; i++) + if (frames[i] instanceof JDesktopIcon + || frames[i] instanceof JInternalFrame + && ((JInternalFrame) frames[i]).getWasIcon() && frames[i] != frame) + count++; + iconRects = new Rectangle[count]; + for (int i = 0, j = 0; i < frames.length; i++) + if (frames[i] instanceof JDesktopIcon) + iconRects[--count] = frames[i].getBounds(); + else if (frames[i] instanceof JInternalFrame + && ((JInternalFrame) frames[i]).getWasIcon() + && frames[i] != frame) + iconRects[--count] = ((JInternalFrame) frames[i]) + .getDesktopIcon().getBounds(); + + int startingX = insets.left; + int startingY = paneBounds.height - insets.bottom - pref.height; + Rectangle ideal = new Rectangle(startingX, startingY, pref.width, + pref.height); + boolean clear = true; + + while (iconRects.length > 0) + { + clear = true; + for (int i = 0; i < iconRects.length; i++) + { + if (iconRects[i] != null && iconRects[i].intersects(ideal)) + { + clear = false; + break; + } + } + if (clear) + return ideal; + + startingX += pref.width; + if (startingX + pref.width > paneBounds.width - insets.right) + { + startingX = insets.left; + startingY -= pref.height; + } + ideal.setBounds(startingX, startingY, pref.width, pref.height); + } + + return ideal; + } + + /** + * This method sets the bounds of the JInternalFrame right before the + * maximizeFrame call. + * + * @param frame The JInternalFrame being maximized. + * @param rect The normal bounds. + */ + protected void setPreviousBounds(JInternalFrame frame, Rectangle rect) + { + frame.setNormalBounds(rect); + } + + /** + * This method returns the normal bounds of the JInternalFrame from before + * the maximize call. + * + * @param frame The JInternalFrame that is being restored. + * + * @return The previous bounds of the JInternalFrame. + */ + protected Rectangle getPreviousBounds(JInternalFrame frame) + { + return frame.getNormalBounds(); + } + + /** + * This method sets the value to true if the given JInternalFrame has been + * iconized and the bounds of its DesktopIcon are valid. + * + * @param frame The JInternalFrame for the JDesktopIcon. + * @param value True if the JInternalFrame has been iconized and the bounds + * of the JDesktopIcon are valid. + */ + protected void setWasIcon(JInternalFrame frame, Boolean value) + { + frame.setWasIcon(value.booleanValue(), WAS_ICON_ONCE_PROPERTY); + } + + /** + * This method returns true if the given JInternalFrame has been iconized + * and the bounds of its DesktopIcon are valid. + * + * @param frame The JInternalFrame for the JDesktopIcon. + * + * @return True if the given JInternalFrame has been iconized and the bounds + * of its DesktopIcon are valid. + */ + protected boolean wasIcon(JInternalFrame frame) + { + return frame.getWasIcon(); + } +} diff --git a/libjava/classpath/javax/swing/DefaultFocusManager.java b/libjava/classpath/javax/swing/DefaultFocusManager.java new file mode 100644 index 0000000..dd8e604 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultFocusManager.java @@ -0,0 +1,166 @@ +/* DefaultFocusManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.event.KeyEvent; +import java.util.Stack; + +/** + * DefaultFocusManager + * @author Andrew Selkirk + * @version 1.0 + */ +public class DefaultFocusManager extends FocusManager { + + /** + * historyStack + */ + private Stack historyStack; + + /** + * Constructor DefaultFocusManager + */ + public DefaultFocusManager() + { + // TODO + } // DefaultFocusManager() + + /** + * processKeyEvent + * + * @param component + * TODO + * @param event + * TODO + */ + public void processKeyEvent(Component component, KeyEvent event) + { + // TODO + } // processKeyEvent() + + /** + * focusNextComponent + * + * @param component + * TODO + */ + public void focusNextComponent(Component component) + { + // TODO + } // focusNextComponent() + + /** + * focusPreviousComponent + * + * @param component + * TODO + */ + public void focusPreviousComponent(Component component) + { + // TODO + } // focusPreviousComponent() + + /** + * getFirstComponent + * + * @param container + * TODO + * @returns Component + */ + public Component getFirstComponent(Container container) + { + return null; // TODO + } // getFirstComponent() + + /** + * getLastComponent + * + * @param container + * TODO + * @returns Component + */ + public Component getLastComponent(Container container) + { + return null; // TODO + } // getLastComponent() + + /** + * getComponentBefore + * + * @param container + * TODO + * @param component + * TODO + * @returns Component + */ + public Component getComponentBefore(Container container, Component component) + { + return null; // TODO + } // getComponentBefore() + + /** + * getComponentAfter + * + * @param container + * TODO + * @param component + * TODO + * @returns Component + */ + public Component getComponentAfter(Container container, Component component) + { + return null; // TODO + } // getComponentAfter() + + /** + * compareTabOrder + * + * @param component1 + * TODO + * @param component2 + * TODO + * @returns boolean + */ + public boolean compareTabOrder(Component component1, Component component2) + { + return false; // TODO + } // compareTabOrder() + +} // DefaultFocusManager diff --git a/libjava/classpath/javax/swing/DefaultListCellRenderer.java b/libjava/classpath/javax/swing/DefaultListCellRenderer.java new file mode 100644 index 0000000..0f2417d --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultListCellRenderer.java @@ -0,0 +1,179 @@ +/* DefaultListCellRenderer.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * DefaultListCellRenderer. This class is responsible for rendering list + * cells. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class DefaultListCellRenderer extends JLabel + implements ListCellRenderer, Serializable +{ + private static final long serialVersionUID = 7708947179685189462L; + + public static class UIResource extends DefaultListCellRenderer + implements javax.swing.plaf.UIResource + { + public UIResource() + { + } + } + + /** + * This border is used whenever renderer doesn't have a focus. + */ + protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); + + /** + * getListCellRendererComponent + * + * @param list JList list for the 'value' + * @param value object that should be rendered in the cell + * @param index index of the cell + * @param isSelected draw cell highlighted if isSelected is true + * @param cellHasFocus draw focus rectangle around cell if the cell has + * focus + * + * @return Component that will be painted to the desired cell. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, + boolean cellHasFocus) + { + String s = value.toString(); + setText(s); + setOpaque(true); + setHorizontalAlignment(LEFT); + + if (isSelected) + { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else + { + 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; + } + + public void validate() + { + } + + public void revalidate() + { + } + + public void repaint(long tm, int x, int y, int w, int h) + { + } + + public void repaint(Rectangle rect) + { + } + + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + } + + public void firePropertyChange(String propertyName, byte oldValue, + byte newValue) + { + } + + public void firePropertyChange(String propertyName, char oldValue, + char newValue) + { + } + + public void firePropertyChange(String propertyName, short oldValue, + short newValue) + { + } + + public void firePropertyChange(String propertyName, int oldValue, + int newValue) + { + } + + public void firePropertyChange(String propertyName, long oldValue, + long newValue) + { + } + + public void firePropertyChange(String propertyName, float oldValue, + float newValue) + { + } + + public void firePropertyChange(String propertyName, double oldValue, + double newValue) + { + } + + public void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) + { + } +} diff --git a/libjava/classpath/javax/swing/DefaultListModel.java b/libjava/classpath/javax/swing/DefaultListModel.java new file mode 100644 index 0000000..d7ff259 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultListModel.java @@ -0,0 +1,521 @@ +/* DefaultListModel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * This is a default subclass of the {@link AbstractListModel}, used by + * {@link javax.swing.JList} and similar objects as the model of a list of + * values. The implementation is based on an underlying {@link + * java.util.Vector}. + * + * @author Andrew Selkirk + * @author Graydon Hoare (graydon@redhat.com) + */ + +public class DefaultListModel extends AbstractListModel +{ + private static final long serialVersionUID = 2315945659722172272L; + + /** + * The vector of elements in this list model. + */ + private Vector elements = new Vector(); + + /** + * Gets an element of the list at the provided index. + * + * @param index The index of the element to get + * + * @return The object at the given index + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public Object elementAt(int index) + { + return elements.elementAt(index); + } + + /** + * Convert the list to a string representation. + * + * @return A string representation of the list + */ + public String toString() + { + return elements.toString(); + } + + /** + * Gets the first index of a particular element in the list. + * + * @param element The element to search for + * + * @return The first index in the list at which an object + * obj exists such that obj.equals(element) is + * true; if no such object exists, the method returns + * -1 + */ + public int indexOf(Object element) + { + return elements.indexOf(element); + } + + /** + * Gets the first index of a particular element in a list which occurs + * at or after a particular index. + * + * @param element The element to search for + * @param startIndex The index to begin searching at + * + * @return The first index in the list, greater than or equal to + * startIndex, at which an object obj exists + * such that obj.equals(element) is true; if no + * such object exists, the method returns -1 + */ + public int indexOf(Object element, int startIndex) + { + return elements.indexOf(element, startIndex); + } + + /** + * Gets the last index of a particular element in the list. + * + * @param element The element to search for + * + * @return The last index in the list at which an object + * obj exists such that obj.equals(element) is + * true; if no such object exists, the method returns + * -1 + */ + public int lastIndexOf(Object element) + { + return elements.lastIndexOf(element); + } + + /** + * Gets the last index of a particular element in a list which occurs + * at or before a particular index. + * + * @param element The element to search for + * @param endIndex The index to finish searching at + * + * @return The last index in the list, less than to or equal to + * endIndexIndex, at which an object obj exists + * such that obj.equals(element) is true; if no + * such object exists, the method returns -1 + */ + public int lastIndexOf(Object element, int endIndex) + { + return elements.lastIndexOf(element, endIndex); + } + + /** + * Gets the list element at a particular index. + * + * @param index The index to get the list value at + * + * @return The list value at the provided index + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public Object get(int index) + { + return elements.get(index); + } + + /** + * Sets the list element at a particular index. + * + * @param index The list index at which to set a value + * @param element The value to set at the specified index + * + * @return The value previously held at the specified index + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public Object set(int index, Object element) + { + Object result; + result = elements.set(index, element); + fireContentsChanged(this, index, index); + return result; + } + + /** + * Inserts an element at a particular index in the list. Each element at + * index i >= index is shifted to position i+1. + * If index is equal to size(), this is + * equivalent to appending an element to the array. Any + * index greater than size() is illegal. + * + * @param index The index to insert the element at + * @param element The element to insert at the index + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds [0, size()] + */ + public void add(int index, Object element) + { + elements.add(index, element); + fireIntervalAdded(this, index, index); + } + + /** + * Inserts an element at the end of the list. This is equivalent to + * calling list.add(list.size(), element). + * + * @param element The element to add to the list + */ + public void addElement(Object element) + { + int s = elements.size(); + elements.add(element); + fireIntervalAdded(this, s, s); + } + + /** + * Gets the number of elements in the list. + * + * @return The number of elements in the list + */ + public int size() + { + return elements.size(); + } + + /** + * Gets an array containing the elements of the list. + * + * @return An array of the objects in the list, in the order they occur + * in the list + */ + public Object[] toArray() + { + return elements.toArray(); + } + + /** + * Determines whether a particular element is a member of the list. + * + * @param element The element to search for + * + * @return true if element is a member of the + * list, otherwise false + */ + public boolean contains(Object element) + { + return elements.contains(element); + } + + /** + * Copies the list into a provided array. The provided array must be at + * least as large as the list. + * + * @param array The array to copy the list into + * + * @throws IndexOutOfBoundsException if the array is too small to hold the + * elements of the list + */ + public void copyInto(Object[] array) + { + elements.copyInto(array); + } + + /** + * Erases all the elements of the list, setting the list's size to 0. + */ + public void clear() + { + int s = elements.size(); + if (s > 0) + { + elements.clear(); + fireIntervalRemoved(this, 0, s - 1); + } + } + + /** + * Removes the element at a particular index from the list. + * + * @param index The index of the element to remove + * + * @return The value at the index, which has been removed from the list + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public Object remove(int index) + { + Object result; + result = elements.remove(index); + fireIntervalRemoved(this, index, index); + return result; + } + + /** + * Determines whether the list is empty. + * + * @return true if the list is empty, otherwise + * false + */ + public boolean isEmpty() + { + return elements.isEmpty(); + } + + /** + * Returns an {@link java.util.Enumeration} over the elements of the list. + * + * @return A new enumeration which iterates over the list + */ + public Enumeration elements() + { + return elements.elements(); + } + + /** + * Sets the capacity of the list to be equal to its size. The list's capacity + * is the number of elements it can hold before it needs to be reallocated. + * The list's size is the number of elements it currently holds. + */ + public void trimToSize() + { + elements.trimToSize(); + } + + /** + * Ensures that the list's capacity is at least equal to + * size. The list's capacity is the number of elements it + * can hold before it needs to be reallocated. + * + * @param size The capacity to ensure the list can hold + */ + public void ensureCapacity(int size) + { + elements.ensureCapacity(size); + } + + /** + * Sets the size of the list to a particular value. If the specified size + * is greater than the current size, the values at the excess list + * indices are set to null. If the specified size is less + * than the current size, the excess elements are removed from the list. + * + * @param size The new size to set the list to + */ + public void setSize(int size) + { + int oldSize = elements.size(); + elements.setSize(size); + if (oldSize < size) + { + fireIntervalAdded(this, oldSize, size - 1); + } + else if (oldSize > size) + { + this.fireIntervalRemoved(this, size, oldSize - 1); + } + } + + /** + * Gets the capacity of the list. The list's capacity is the number of + * elements it can hold before it needs to be reallocated. + * + * @return The capacity of the list + */ + public int capacity() + { + return elements.capacity(); + } + + /** + * Gets the first element in the list. + * + * @return The first element in the list + */ + public Object firstElement() + { + return elements.firstElement(); + } + + /** + * Gets the last element in the list. + * + * @return The last element in the list + */ + public Object lastElement() + { + return elements.lastElement(); + } + + /** + * Sets the list element at a particular index. + * + * @param element The value to set at the specified index + * @param index The list index at which to set a value + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public void setElementAt(Object element, int index) + { + elements.setElementAt(element, index); + fireContentsChanged(this, index, index); + } + + /** + * Removes the element at a particular index from the list. + * + * @param index The index of the element to remove + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public void removeElementAt(int index) + { + elements.remove(index); + fireIntervalRemoved(this, index, index); + } + + /** + * Inserts an element at a particular index in the list. Each element at + * index i >= index is shifted to position i+1. + * If index is equal to size(), this is + * equivalent to appending an element to the array. Any + * index greater than size() is illegal. + * + * @param element The element to insert at the index + * @param index The index to insert the element at + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds [0, size()] + */ + public void insertElementAt(Object element, int index) + { + elements.insertElementAt(element, index); + fireIntervalAdded(this, index, index); + } + + /** + * Removes the first occurrence of a particular element in the list. If the + * element does not exist in the list, nothing happens. + * + * @param element The element to remove + * + * @return true if the element existed in the list (and was + * removed), false otherwise + */ + public boolean removeElement(Object element) + { + int index; + index = elements.indexOf(element); + if (index != -1) + { + elements.remove(index); + fireIntervalRemoved(this, index, index); + return true; + } + return false; + } + + /** + * Remove all elements in the list. + */ + public void removeAllElements() + { + int size; + size = size(); + if (size > 0) + { + elements.clear(); + fireIntervalRemoved(this, 0, size - 1); + } + } + + /** + * Remove all elements between startIndex and + * endIndex inclusive. + * + * @param startIndex The first index in the range to remove + * @param endIndex The last index in the range to remove + * + * @throws ArrayIndexOutOfBoundsException if either index is outside the + * valid range of indices for this list [0, size()) + * @throws IllegalArgumentException if startIndex > endIndex + */ + public void removeRange(int startIndex, int endIndex) + { + int index; + if (startIndex > endIndex) + throw new IllegalArgumentException(); + for (index = endIndex; index >= startIndex; index--) + elements.remove(index); + fireIntervalRemoved(this, startIndex, endIndex); + } + + /** + * Gets the size of the list. + * + * @return The number of elements currently in the list + */ + public int getSize() + { + return elements.size(); + } + + /** + * Gets the list element at a particular index. + * + * @param index The index to get the list value at + * + * @return The list value at the provided index + * + * @throws ArrayIndexOutOfBoundsException If the provided index is + * outside the bounds of the list [0, size()) + */ + public Object getElementAt(int index) + { + return elements.get(index); + } +} diff --git a/libjava/classpath/javax/swing/DefaultListSelectionModel.java b/libjava/classpath/javax/swing/DefaultListSelectionModel.java new file mode 100644 index 0000000..d08ca6f --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultListSelectionModel.java @@ -0,0 +1,706 @@ +/* DefaultListSelectionModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.BitSet; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + *

This class provides a default implementation of {@link + * ListSelectioModel}, which is used by {@link javax.swing.JList} and + * similar classes to manage the selection status of a number of data + * elements.

+ * + *

The class is organized abstractly as a set of intervals of + * integers. Each interval indicates an inclusive range of indices in a + * list -- held by some other object and unknown to this class -- which is + * considered "selected". There are various accessors for querying and + * modifying the set of intervals, with simplified forms accepting a single + * index, representing an interval with only one element.

+ */ +public class DefaultListSelectionModel implements Cloneable, + ListSelectionModel, + Serializable +{ + private static final long serialVersionUID = -5718799865110415860L; + + /** The list of ListSelectionListeners subscribed to this selection model. */ + protected EventListenerList listenerList = new EventListenerList(); + + + /** + * The current list selection mode. Must be one of the numeric constants + * SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION + * or MULTIPLE_INTERVAL_SELECTION from {@link + * ListSelectionModel}. The default value is + * MULTIPLE_INTERVAL_SELECTION. + */ + int selectionMode = MULTIPLE_INTERVAL_SELECTION; + + /** + * The index of the "lead" of the most recent selection. The lead is the + * second argument in any call to {@link #setSelectionInterval}, {@link + * #addSelectionInterval} or {@link #removeSelectionInterval}. Generally + * the lead refers to the most recent position a user dragged their mouse + * over. + */ + int leadSelectionIndex = -1; + + /** + * The index of the "anchor" of the most recent selection. The anchor is + * the first argument in any call to {@link #setSelectionInterval}, + * {@link #addSelectionInterval} or {@link + * #removeSelectionInterval}. Generally the anchor refers to the first + * recent position a user clicks when they begin to drag their mouse over + * a list. + * + * @see #getAnchorSelectionIndex + * @see #setAnchorSelectionIndex + */ + int anchorSelectionIndex = -1; + + /** + * controls the range of indices provided in any {@link + * ListSelectionEvent} fired by the selectionModel. Let + * [A,L] be the range of indices between {@link + * anchorSelectionIndex} and {@link leadSelectionIndex} inclusive, and + * let [i0,i1] be the range of indices changed in a given + * call which generates a {@link ListSelectionEvent}. Then when this + * property is true, the {@link ListSelectionEvent} contains + * the range [A,L] union [i0,i1]; when false it + * will contain only [i0,i1]. The default is + * true. + * + * @see #isLeadAnchorNotificationEnabled + * @see #setLeadAnchorNotificationEnabled + */ + protected boolean leadAnchorNotificationEnabled = true; + + /** + * Whether the selection is currently "adjusting". Any {@link + * ListSelectionEvent} events constructed in response to changes in this + * list selection model will have their {@link + * ListSelectionEvent#isAdjusting} field set to this value. + * + * @see #getValueIsAdjusting + * @see #setValueIsAdjusting + */ + boolean valueIsAdjusting = false; + + + /** + * The current set of "intervals", represented simply by a {@link + * java.util.BitSet}. A set bit indicates a selected index, whereas a + * cleared bit indicates a non-selected index. + */ + BitSet sel = new BitSet(); + + /** + * A variable to store the previous value of sel. + * Used to make sure we only fireValueChanged when the BitSet + * actually does change. + */ + Object oldSel; + + /** + * Whether this call of setLeadSelectionInterval was called locally + * from addSelectionInterval + */ + boolean setLeadCalledFromAdd = false; + + /** + * Gets the value of the {@link #selectionMode} property. + * + * @return The current value of the property + */ + public int getSelectionMode() + { + return selectionMode; + } + + /** + * Sets the value of the {@link #selectionMode} property. + * + * @param a The new value of the property + */ + public void setSelectionMode(int a) + { + selectionMode = a; + } + + /** + * Gets the value of the {@link #anchorSelectionIndex} property. + * + * @return The current property value + * + * @see #setAnchorSelectionIndex + */ + public int getAnchorSelectionIndex() + { + return anchorSelectionIndex; + } + + /** + * Sets the value of the {@link #anchorSelectionIndex} property. + * + * @param anchorIndex The new property value + * + * @see #getAnchorSelectionIndex + */ + public void setAnchorSelectionIndex(int anchorIndex) + { + anchorSelectionIndex = anchorIndex; + } + + /** + * Gets the value of the {@link #leadSelectionIndex} property. + * + * @return The current property value + * + * @see #setLeadSelectionIndex + */ + public int getLeadSelectionIndex() + { + return leadSelectionIndex; + } + + /** + *

Sets the value of the {@link #anchorSelectionIndex} property. As a + * side effect, alters the selection status of two ranges of indices. Let + * OL be the old lead selection index, NL be + * the new lead selection index, and A be the anchor + * selection index. Then if A is a valid selection index, + * one of two things happens depending on the seleciton status of + * A:

+ * + * + * + *

This method generates at most a single {@link ListSelectionEvent} + * despite changing multiple ranges. The range of values provided to the + * {@link ListSelectionEvent} includes only the minimum range of values + * which changed selection status between the beginning and end of the + * method.

+ * + * @param anchorIndex The new property value + * + * @see #getAnchorSelectionIndex + */ + public void setLeadSelectionIndex(int leadIndex) + { + int oldLeadIndex = leadSelectionIndex; + if (setLeadCalledFromAdd == false) + oldSel = sel.clone(); + leadSelectionIndex = leadIndex; + + if (anchorSelectionIndex == -1) + return; + + int R1 = Math.min(anchorSelectionIndex, oldLeadIndex); + int R2 = Math.max(anchorSelectionIndex, oldLeadIndex); + int S1 = Math.min(anchorSelectionIndex, leadIndex); + int S2 = Math.max(anchorSelectionIndex, leadIndex); + + 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); + sel.set(S1, S2+1); + } + else + { + 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)) + end = i; + if (sel.equals(oldSel) == false) + fireValueChanged(beg, end, valueIsAdjusting); + } + + /** + * Gets the value of the {@link #leadAnchorNotificationEnabled} property. + * + * @return The current property value + * + * @see #setLeadAnchorNotificationEnabled + */ + public boolean isLeadAnchorNotificationEnabled() + { + return leadAnchorNotificationEnabled; + } + + /** + * Sets the value of the {@link #leadAnchorNotificationEnabled} property. + * + * @param flag The new property value + * + * @see #getLeadAnchorNotificationEnabled + */ + public void setLeadAnchorNotificationEnabled(boolean l) + { + leadAnchorNotificationEnabled = l; + } + + /** + * Gets the value of the {@link #valueIsAdjusting} property. + * + * @return The current property value + * + * @see #setValueIsAdjusting + */ + public boolean getValueIsAdjusting() + { + return valueIsAdjusting; + } + + /** + * Sets the value of the {@link #valueIsAdjusting} property. + * + * @param v The new property value + * + * @see #getValueIsAdjusting + */ + public void setValueIsAdjusting(boolean v) + { + valueIsAdjusting = v; + } + + /** + * Determines whether the selection is empty. + * + * @return true if the selection is empty, otherwise + * false + */ + public boolean isSelectionEmpty() + { + return sel.isEmpty(); + } + + /** + * Gets the smallest index which is currently a member of a selection + * interval. + * + * @return The least integer i such that i >= + * 0 and i is a member of a selected interval, or + * -1 if there are no selected intervals + * + * @see #getMaxSelectionIndex + */ + public int getMinSelectionIndex() + { + if (isSelectionEmpty()) + return -1; + + return sel.nextSetBit(0); + } + + /** + * Gets the largest index which is currently a member of a selection + * interval. + * + * @return The greatest integer i such that i >= + * 0 and i is a member of a selected interval, or + * -1 if there are no selected intervals + * + * @see #getMinSelectionIndex + */ + public int getMaxSelectionIndex() + { + if (isSelectionEmpty()) + return -1; + + int mx = -1; + for(int i=sel.nextSetBit(0); i >= 0; i=sel.nextSetBit(i+1)) + { + mx = i; + } + return mx; + } + + /** + * Determines whether a particular index is a member of a selection + * interval. + * + * @param a The index to search for + * + * @return true if the index is a member of a selection interval, + * otherwise false + */ + public boolean isSelectedIndex(int a) + { + return sel.get(a); + } + + /** + * If the {@link #selectionMode} property is equal to + * SINGLE_SELECTION equivalent to calling + * setSelectionInterval(index1, index2); + * If the {@link #selectionMode} property is equal to + * SINGLE_INTERVAL_SELECTION and the interval being + * added is not adjacent to an already selected interval, + * equivalent to setSelectionInterval(index1, index2). + * Otherwise adds the range [index0, index1] + * to the selection interval set. + * + * @param index0 The beginning of the range of indices to select + * @param index1 The end of the range of indices to select + * + * @see #setSelectionInterval + * @see #removeSelectionInterval + */ + public void addSelectionInterval(int index0, int index1) + { + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + oldSel = sel.clone(); + + if (selectionMode == SINGLE_SELECTION) + sel.clear(); + + // COMPAT: Like Sun (but not like IBM), we allow calls to + // addSelectionInterval when selectionMode is + // SINGLE_SELECTION_INTERVAL iff the interval being added + // is adjacent to an already selected interval + if (selectionMode == SINGLE_INTERVAL_SELECTION) + if (!(isSelectedIndex(index0) || + isSelectedIndex(index1) || + isSelectedIndex(Math.max(lo-1,0)) || + isSelectedIndex(Math.min(hi+1,sel.size())))) + sel.clear(); + + if (selectionMode == SINGLE_SELECTION) + index0 = index1; + + // We have to update the anchorSelectionIndex and leadSelectionIndex + // variables + + // The next if statements breaks down to "if this selection is adjacent + // to the previous selection and going in the same direction" + if ((isSelectedIndex(leadSelectionIndex)) + && ((index0 - 1 == leadSelectionIndex + && (index1 >= index0) + && (leadSelectionIndex >= anchorSelectionIndex)) + || (index0 + 1 == leadSelectionIndex && (index1 <= index0) + && (leadSelectionIndex <= anchorSelectionIndex))) + && (anchorSelectionIndex != -1 || leadSelectionIndex != -1)) + { + // setting setLeadCalledFromAdd to true tells setLeadSelectionIndex + // not to update oldSel + setLeadCalledFromAdd = true; + setLeadSelectionIndex(index1); + setLeadCalledFromAdd = false; + } + else + { + leadSelectionIndex = index1; + anchorSelectionIndex = index0; + sel.set(lo, hi+1); + if (sel.equals(oldSel) == false) + fireValueChanged(lo, hi, valueIsAdjusting); + } + } + + + /** + * Deselects all indices in the inclusive range + * [index0,index1]. + * + * @param index0 The beginning of the range of indices to deselect + * @param index1 The end of the range of indices to deselect + * + * @see #addSelectionInterval + * @see #setSelectionInterval + */ + public void removeSelectionInterval(int index0, + int index1) + { + oldSel = sel.clone(); + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + + // if selectionMode is SINGLE_INTERVAL_SELECTION and removing the interval + // (index0,index1) would leave two disjoint selection intervals, remove all + // selected indices from lo to the last selected index + if (getMinSelectionIndex() > 0 && getMinSelectionIndex() < lo && + selectionMode == SINGLE_INTERVAL_SELECTION) + hi = sel.size() - 1; + + sel.clear(lo, hi+1); + //update anchorSelectionIndex and leadSelectionIndex variables + //TODO: will probably need MouseDragged to test properly and know if this works + setAnchorSelectionIndex(index0); + leadSelectionIndex = index1; + if (sel.equals(oldSel) == false) + fireValueChanged(lo, hi, valueIsAdjusting); + } + + /** + * Removes all intervals in the selection set. + */ + public void clearSelection() + { + oldSel = sel.clone(); + int sz = sel.size(); + sel.clear(); + if (sel.equals(oldSel) == false) + fireValueChanged(0, sz, valueIsAdjusting); + } + + /** + * Clears the current selection and marks a given interval as + * "selected". If the current selection mode is + * SINGLE_SELECTION only the index index2 is + * selected. + * + * @param index0 The low end of the new selection + * @param index1 The high end of the new selection + */ + public void setSelectionInterval(int index0, int index1) + { + oldSel = sel.clone(); + sel.clear(); + if (selectionMode == SINGLE_SELECTION) + index0 = index1; + + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + sel.set(lo, hi+1); + // update the anchorSelectionIndex and leadSelectionIndex variables + setAnchorSelectionIndex(index0); + leadSelectionIndex=index1; + if (sel.equals(oldSel) == false) + fireValueChanged(lo, hi, valueIsAdjusting); + } + + /** + * Inserts a number of indices either before or after a particular + * position in the set of indices. Renumbers all indices after the + * inserted range. The new indices in the inserted range are not + * selected. This method is typically called to synchronize the selection + * model with an inserted range of elements in a {@link ListModel}. + * + * @param index The position to insert indices at + * @param length The number of indices to insert + * @param before Indicates whether to insert the indices before the index + * or after it + */ + public void insertIndexInterval(int index, + int length, + boolean before) + { + if (!before) + { + index++; + length--; + } + BitSet tmp = sel.get(index, sel.size()); + sel.clear(index, sel.size()); + int n = tmp.size(); + for (int i = 0; i < n; ++i) + sel.set(index + length + i, tmp.get(i)); + } + + /** + * Removes a range from the set of indices. Renumbers all indices after + * the removed range. This method is typically called to synchronize the + * selection model with a deleted range of elements in a {@link + * ListModel}. + * + * @param index0 The first index to remove (inclusive) + * @param index1 The last index to remove (inclusive) + */ + public void removeIndexInterval(int index0, + int index1) + { + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + + BitSet tmp = sel.get(hi, sel.size()); + sel.clear(lo, sel.size()); + int n = tmp.size(); + for (int i = 0; i < n; ++i) + sel.set(lo + i, tmp.get(i)); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model to + * indicate that a series of adjustment has just ended. + * + * The values of {@link #getMinSelectionIndex} and + * {@link getMaxSelectionIndex} are used in the {@link ListSelectionEvent} + * that gets fired. + * + * @param isAdjusting true if this is the final change + * in a series of adjustments, false/code> otherwise + */ + protected void fireValueChanged(boolean isAdjusting) + { + fireValueChanged(getMinSelectionIndex(), getMaxSelectionIndex(), + isAdjusting); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model. + * + * @param firstIndex The low index of the changed range + * @param lastIndex The high index of the changed range + */ + protected void fireValueChanged(int firstIndex, int lastIndex) + { + fireValueChanged(firstIndex, lastIndex, getValueIsAdjusting()); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model. + * + * @param firstIndex The low index of the changed range + * @param lastIndex The high index of the changed range + * @param isAdjusting Whether this change is part of a seqence of adjustments + * made to the selection, such as during interactive scrolling + */ + protected void fireValueChanged(int firstIndex, int lastIndex, + boolean isAdjusting) + { + ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, + lastIndex, isAdjusting); + ListSelectionListener[] listeners = getListSelectionListeners(); + for (int i = 0; i < listeners.length; ++i) + listeners[i].valueChanged(evt); + } + + /** + * Adds a listener. + * + * @param listener The listener to add + * + * @see removeListSelectionListener + * @see getListSelectionListeners + */ + public void addListSelectionListener(ListSelectionListener listener) + { + listenerList.add(ListSelectionListener.class, listener); + } + + /** + * Removes a registered listener. + * + * @param listener The listener to remove + * + * @see addListSelectionListener + * @see getListSelectionListeners + */ + public void removeListSelectionListener(ListSelectionListener listener) + { + listenerList.remove(ListSelectionListener.class, listener); + } + + /** + * Returns an array of all registerers listeners. + * + * @param listenerType The type of listener to retrieve + * + * @return The array + * + * @see getListSelectionListener + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Returns an array of all registerd list selection listeners. + * + * @return the array + * + * @see addListSelectionListener + * @see removeListSelectionListener + * @see getListeners + * @since 1.4 + */ + public ListSelectionListener[] getListSelectionListeners() + { + return (ListSelectionListener[]) getListeners(ListSelectionListener.class); + } + + /** + * Returns a clone of this object. + * listenerList don't gets duplicated. + * + * @return the cloned object + * + * @throws CloneNotSupportedException if an error occurs + */ + public Object clone() + throws CloneNotSupportedException + { + DefaultListSelectionModel model = + (DefaultListSelectionModel) super.clone(); + model.sel = (BitSet) sel.clone(); + return model; + } +} diff --git a/libjava/classpath/javax/swing/DefaultSingleSelectionModel.java b/libjava/classpath/javax/swing/DefaultSingleSelectionModel.java new file mode 100644 index 0000000..039883e --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultSingleSelectionModel.java @@ -0,0 +1,172 @@ +/* DefaultSingleSelectionModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * DefaultSingleSelectionModel + * + * @author Andrew Selkirk + */ +public class DefaultSingleSelectionModel + implements SingleSelectionModel, Serializable +{ + private static final long serialVersionUID = 3676229404753786004L; + + /** + * changeEvent + */ + protected transient ChangeEvent changeEvent = new ChangeEvent(this); + + /** + * listenerList + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * index + */ + private int index = -1; + + /** + * Constructor DefaultSingleSelectionModel + */ + public DefaultSingleSelectionModel() + { + // Do nothing. + } + + /** + * getSelectedIndex + * @return int + */ + public int getSelectedIndex() + { + return index; + } + + /** + * setSelectedIndex + * @param index TODO + */ + public void setSelectedIndex(int index) + { + this.index = index; + fireStateChanged(); + } + + /** + * clearSelection + */ + public void clearSelection() + { + index = -1; + fireStateChanged(); + } + + /** + * isSelected + * @return boolean + */ + public boolean isSelected() + { + return index != -1; + } + + /** + * addChangeListener + * + * @param listener the listener to add + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * removeChangeListener + * + * @param listener the listener to remove + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * fireStateChanged + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].stateChanged(changeEvent); + } + + /** + * getListeners + * + * @param listenerClass the type fo listener + * + * @return an array of listeners + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerClass) + { + return listenerList.getListeners(listenerClass); + } + + /** + * getChangeListeners + * + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) getListeners(ChangeListener.class); + } +} diff --git a/libjava/classpath/javax/swing/DesktopManager.java b/libjava/classpath/javax/swing/DesktopManager.java new file mode 100644 index 0000000..300d665 --- /dev/null +++ b/libjava/classpath/javax/swing/DesktopManager.java @@ -0,0 +1,177 @@ +/* DesktopManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * DesktopManagers are responsible for implementing the behaviours for the + * JInternalFrames that belong to JDesktopPanes. Actions such as maximizing, + * minimizing, iconifying, etc will be delegated to the DesktopManager. + */ +public interface DesktopManager +{ + /** + * This method will cause the JInternalFrame to be displayed in the set + * location. This usually is not needed since the user will add the + * JInternalFrame to a Container separately. + * + * @param frame The JInternalFrame to open. + */ + void openFrame(JInternalFrame frame); + + /** + * This method should remove the JInternalFrame from its parent. + * + * @param frame The JInternalFrame to close. + */ + void closeFrame(JInternalFrame frame); + + /** + * This method should maximize the JInternalFrame to match its parent's + * bounds. + * + * @param frame The JInternalFrame to maximize. + */ + void maximizeFrame(JInternalFrame frame); + + /** + * This method should restore the JInternalFrame to its normal bounds. + * + * @param frame The JInternalFrame to minimize. + */ + void minimizeFrame(JInternalFrame frame); + + /** + * This method should remove the JInternalFrame from its parent and replace + * it with a JDesktopIcon. + * + * @param frame The JInternalFrame to iconify. + */ + void iconifyFrame(JInternalFrame frame); + + /** + * This method should remove the JDesktopIcon from its parent and replace it + * with the JInternalFrame that the JDesktopIcon represents. + * + * @param frame The JInternalFrame to deiconify. + */ + void deiconifyFrame(JInternalFrame frame); + + /** + * This method should give focus to the JInternalFrame and its default focus + * owner. + * + * @param frame The JInternalFrame to activate. + */ + void activateFrame(JInternalFrame vframe); + + /** + * This method should be called when the JInternalFrame gets deselected and + * subsequently loses focus. + * + * @param frame The JInternalFrame to deactivate. + */ + void deactivateFrame(JInternalFrame frame); + + /** + * This method should be called in preparation for dragging. This needs to + * be called prior to dragFrame calls so that the DesktopManager can + * prepare any state information. + * + * @param frame The JInternalFrame to prepare for dragging. + */ + void beginDraggingFrame(JComponent frame); + + /** + * This method drags the given JInternalFrame to the given x and y + * coordinates. + * + * @param frame The JInternalFrame to drag. + * @param x The new x coordinate. + * @param y The new y coordinate. + */ + void dragFrame(JComponent frame, int x, int y); + + /** + * This method should be called after dragFrame calls. Any information used + * by the DesktopManager for dragging the JInternalFrame can be cleared. + * + * @param frame The JInternalFrame that finished dragging. + */ + void endDraggingFrame(JComponent frame); + + /** + * This method should be called prior to any resizeFrame calls. Any state + * information needed by the DesktopManager to resize the JInternalFrame + * will be prepared here. + * + * @param frame The JInternalFrame to resize. + * @param direction One of eight directions specified by SwingConstants. + */ + void beginResizingFrame(JComponent frame, int direction); + + /** + * This method is called to resize the given JInternalFrame to the given + * bounds. + * + * @param frame The JInternalFrame to resize. + * @param x The new x coordinate. + * @param y The new y coordinate. + * @param width The new width. + * @param height The new height. + */ + void resizeFrame(JComponent frame, int x, int y, int width, int height); + + /** + * This method is called to signify that the resize is finished. Any + * information used to resize the JInternalFrame can now be cleared. + * + * @param frame The JInternalFrame that just finished dragging. + */ + void endResizingFrame(JComponent frame); + + /** + * This method does the actual work for reshaping the JInternalFrame. + * + * @param frame The JInternalFrame to resize. + * @param x The new x coordinate. + * @param y The new y coordinate. + * @param width The new width. + * @param height The new height. + */ + void setBoundsForFrame(JComponent frame, int x, int y, int width, int height); +} // DesktopManager diff --git a/libjava/classpath/javax/swing/FocusManager.java b/libjava/classpath/javax/swing/FocusManager.java new file mode 100644 index 0000000..9f898e6 --- /dev/null +++ b/libjava/classpath/javax/swing/FocusManager.java @@ -0,0 +1,161 @@ +/* FocusManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.DefaultKeyboardFocusManager; +import java.awt.KeyboardFocusManager; +import java.awt.event.KeyEvent; + +/** + * FocusManager + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class FocusManager + extends DefaultKeyboardFocusManager +{ + /** + * DisabledFocusManager + */ + static class DisabledFocusManager + extends FocusManager + { + + /** + * Constructor DisabledFocusManager + */ + DisabledFocusManager() + { + // TODO + } + + /** + * processKeyEvent + * @param component TODO + * @param event TODO + */ + public void processKeyEvent(Component component, KeyEvent event) + { + // TODO + } + + /** + * focusNextComponent + * @param component TODO + */ + public void focusNextComponent(Component component) + { + // TODO + } + + /** + * focusPreviousComponent + * @param value0 TODO + */ + public void focusPreviousComponent(Component value0) + { + // TODO + } + } + + /** + * FOCUS_MANAGER_CLASS_PROPERTY + */ + public static final String FOCUS_MANAGER_CLASS_PROPERTY = + "FocusManagerClassName"; + + /** + * Constructor FocusManager + */ + public FocusManager() + { + super(); + } + + /** + * getCurrentManager + * @returns 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; + } + + /** + * setCurrentManager + * @param manager TODO + */ + public static void setCurrentManager(FocusManager manager) + { + KeyboardFocusManager.setCurrentKeyboardFocusManager(manager); + } + + /** + * disableSwingFocusManager + * @deprecated 1.4 + */ + public static void disableSwingFocusManager() + { + // TODO + } + + /** + * isFocusManagerEnabled + * @return boolean + * @deprecated 1.4 + */ + public static boolean isFocusManagerEnabled() + { + return false; // TODO + } +} diff --git a/libjava/classpath/javax/swing/GrayFilter.java b/libjava/classpath/javax/swing/GrayFilter.java new file mode 100644 index 0000000..1a88f6f --- /dev/null +++ b/libjava/classpath/javax/swing/GrayFilter.java @@ -0,0 +1,92 @@ +/* GrayFilter.java -- Java class for filtering Pixels to produce Gray Pictures + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.image.FilteredImageSource; +import java.awt.image.RGBImageFilter; + +public class GrayFilter extends RGBImageFilter +{ + private boolean b; + private double p; + + /** + * Create a GrayFilter. If b is true then brighten. Also, indicate how much + * gray. + * + * @param b if brighten + * @param p percent of gray, 0 - 100 + */ + public GrayFilter(boolean b, int p) + { + this.b = b; //FIXME - HANDLE THIS + this.p = (1. - (p / 100.)) / 3.; + } + + /** + * Create grayed image + * + * @param src image to gray + * + * @return a grayed image + */ + public static Image createDisabledImage(Image src) + { + return (Toolkit.getDefaultToolkit(). + createImage(new FilteredImageSource(src.getSource(), + new GrayFilter(true, 0)))); + } + + /** + * Filter RGB to gray + */ + public int filterRGB(int x, int y, int rgb) + { + int alpha = 0xff000000 & rgb; + int red = (0xff0000 & rgb) >> 16; + int green = (0xff00 & rgb) >> 8; + int blue = (0xff & rgb); + int gray = (int) ((0.299 * red + 0.587 * green + 0.114 * blue) * p); + if (b) + gray = Math.min(gray + 128, 255); + return gray | gray << 8 | gray << 16 | alpha ; + } +} diff --git a/libjava/classpath/javax/swing/Icon.java b/libjava/classpath/javax/swing/Icon.java new file mode 100644 index 0000000..c00eee4 --- /dev/null +++ b/libjava/classpath/javax/swing/Icon.java @@ -0,0 +1,52 @@ +/* Icon.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Graphics; + +/** + * Defines the methods that an object must implement if it should be used + * as an icon in Swing. + */ +public interface Icon +{ + int getIconHeight(); + int getIconWidth(); + void paintIcon(Component c, Graphics g, int x, int y); +} diff --git a/libjava/classpath/javax/swing/ImageIcon.java b/libjava/classpath/javax/swing/ImageIcon.java new file mode 100644 index 0000000..36f23d2 --- /dev/null +++ b/libjava/classpath/javax/swing/ImageIcon.java @@ -0,0 +1,361 @@ +/* ImageIcon.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.Toolkit; +import java.awt.image.ImageObserver; +import java.io.Serializable; +import java.net.URL; +import java.util.Locale; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleIcon; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; + +public class ImageIcon + implements Icon, Serializable, Accessible +{ + /** + * Accessibility support for ImageIcon. + */ + protected class AccessibleImageIcon + extends AccessibleContext + implements AccessibleIcon, Serializable + { + private static final long serialVersionUID = 2113430526551336564L; + + /** + * Creates a new instance of AccessibleImageIcon. + */ + protected AccessibleImageIcon() + { + } + + /** + * Returns the AccessibleRole of ImageIcon, which is + * {@link AccessibleRole#ICON}. + * + * @return {@link AccessibleRole#ICON} + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.ICON; + } + + /** + * Returns the accessible state of this ImageIcon. + * + * @return the accessible state of this ImageIcon + */ + public AccessibleStateSet getAccessibleStateSet() + { + // TODO: which state information from ImageIcon is returned here?? + return new AccessibleStateSet(); + } + + /** + * Returns the accessible parent of this object, which is null + * in this case, because ImageIcons have no parent. + * + * @return null, because ImageIcons have no parent + */ + public Accessible getAccessibleParent() + { + // TODO: ImageIcons have no parent, have they ?? + return null; + } + + /** + * Returns the index of this object in its accessible parent, which is + * -1 here, because ImageIcons have no accessible parent. + * + * @return -1 because ImageIcons have no parent + */ + public int getAccessibleIndexInParent() + { + // TODO: do ImageIcons have parents?? + return -1; + } + + /** + * Returns the number of accessible children of this component, + * which is 0, because ImageIcons have no children. + * + * @return 0 because ImageIcons have no children + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * Returns the accessible child at index i, which is + * null in this case because ImageIcons have no children. + * + * @param i the index of the child to be fetched + * + * @return null because ImageIcons have no children + */ + public Accessible getAccessibleChild(int i) + { + return null; + } + + /** + * Returns the locale of this object. This returns the default locale + * that is set for the current VM. + * + * @return the locale of this object + */ + public Locale getLocale() + { + return Locale.getDefault(); + } + + /** + * Returns the accessible Icon description. This returns the + * actual 'description' property of the ImageIcon. + * + * @return the accessible Icon description + */ + public String getAccessibleIconDescription() + { + return getDescription(); + } + + /** + * Sets the accessible Icon description. This sets the + * actual 'description' property of the ImageIcon. + * + * @param newDescr the description to be set + */ + public void setAccessibleIconDescription(String newDescr) + { + setDescription(newDescr); + } + + /** + * Returns the icon height. This returns the iconHeight property of + * the underlying Icon. + * + * @return the icon height + */ + public int getAccessibleIconHeight() + { + return getIconHeight(); + } + + /** + * Returns the icon width. This returns the iconWidth property of + * the underlying Icon. + * + * @return the icon width + */ + public int getAccessibleIconWidth() + { + return getIconWidth(); + } + } // AccessibleIcon + + private static final long serialVersionUID = 532615968316031794L; + + /** A dummy Component that is used in the MediaTracker. */ + protected static Component component = new Component(){}; + + /** The MediaTracker used to monitor the loading of images. */ + protected static MediaTracker tracker = new MediaTracker(component); + + /** The ID that is used in the tracker. */ + private static int id; + + Image image; + String description; + ImageObserver observer; + + /** The image loading status. */ + private int loadStatus; + + /** The AccessibleContext of this ImageIcon. */ + private AccessibleContext accessibleContext; + + public ImageIcon() + { + } + + public ImageIcon(String file) + { + this(file, file); + } + + public ImageIcon(String file, String description) + { + this(Toolkit.getDefaultToolkit().getImage(file), description); + } + + public ImageIcon(byte[] imageData) + { + this(imageData, null); + } + + public ImageIcon(byte[] imageData, String description) + { + this(Toolkit.getDefaultToolkit().createImage(imageData), description); + } + + public ImageIcon(URL url) + { + this(url, null); + } + + public ImageIcon(URL url, String description) + { + this(Toolkit.getDefaultToolkit().getImage(url), description); + } + + public ImageIcon(Image image) + { + this(image, null); + } + + public ImageIcon(Image image, String description) + { + setImage(image); + setDescription(description); + } + + public ImageObserver getImageObserver() + { + return observer; + } + + public void setImageObserver(ImageObserver newObserver) + { + observer = newObserver; + } + + public Image getImage() + { + return image; + } + + public void setImage(Image image) + { + loadImage(image); + this.image = image; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public int getIconHeight() + { + return image.getHeight(observer); + } + + public int getIconWidth() + { + return image.getWidth(observer); + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.drawImage(image, x, y, observer != null ? observer : c); + } + + /** + * Loads the image and blocks until the loading operation is finished. + * + * @param image the image to be loaded + */ + protected void loadImage(Image image) + { + try + { + tracker.addImage(image, id); + id++; + tracker.waitForID(id - 1); + } + catch (InterruptedException ex) + { + ; // ignore this for now + } + finally + { + loadStatus = tracker.statusID(id - 1, false); + } + } + + /** + * Returns the load status of the icon image. + * + * @return the load status of the icon image + * + * @see {@link MediaTracker.COMPLETE} + * @see {@link MediaTracker.ABORTED} + * @see {@link MediaTracker.ERRORED} + */ + public int getImageLoadStatus() + { + return loadStatus; + } + + /** + * Returns the AccessibleContext for this ImageIcon. + * + * @return the AccessibleContext for this ImageIcon + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleImageIcon(); + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/InputMap.java b/libjava/classpath/javax/swing/InputMap.java new file mode 100644 index 0000000..afc431d --- /dev/null +++ b/libjava/classpath/javax/swing/InputMap.java @@ -0,0 +1,213 @@ +/* InputMap.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +/** + * @author Andrew Selkirk + * @author Michael Koch + * + * @since 1.3 + */ +public class InputMap + implements Serializable +{ + private static final long serialVersionUID = -5429059542008604257L; + + /** + * inputMap + */ + private Map inputMap = new HashMap(); + + /** + * parent + */ + private InputMap parent; + + /** + * Creates a new InputMap instance. + */ + public InputMap() + { + // TODO + } + + /** + * Returns the binding for keystroke. + * + * @param key the key of the enty + * + * @return the binding associated with keystroke may be null + */ + public Object get(KeyStroke keystroke) + { + Object result = inputMap.get(keystroke); + + if (result == null && parent != null) + result = parent.get(keystroke); + return result; + } + + /** + * Puts a new entry into the InputMap. + * If actionMapKey is null an existing entry will be removed. + * + * @param keystroke the keystroke for the entry + * @param actionMapKey the action. + */ + public void put(KeyStroke keystroke, Object actionMapKey) + { + if (actionMapKey == null) + inputMap.remove(keystroke); + else + inputMap.put(keystroke, actionMapKey); + } + + /** + * Remove an entry from the InputMap. + * + * @param key the key of the entry to remove + */ + public void remove(KeyStroke keystroke) + { + inputMap.remove(keystroke); + } + + /** + * Returns the parent of this InputMap. + * + * @return the parent, may be null. + */ + public InputMap getParent() + { + return parent; + } + + /** + * Sets a parent for this InputMap. + * + * @param parentMap the new parent + */ + public void setParent(InputMap parentMap) + { + parent = parentMap; + } + + /** + * Returns the number of entries in this InputMap. + * + * @return the number of entries + */ + public int size() + { + return inputMap.size(); + } + + /** + * Clears the InputMap. + */ + public void clear() + { + inputMap.clear(); + } + + /** + * Returns all keys of entries in this InputMap. + * + * @return an array of keys + */ + public KeyStroke[] keys() + { + KeyStroke[] array = new KeyStroke[size()]; + return (KeyStroke[]) inputMap.keySet().toArray(array); + } + + /** + * Returns all keys of entries in this InputMap + * and all its parents. + * + * @return an array of keys + */ + public KeyStroke[] allKeys() + { + Set set = new HashSet(); + + if (parent != null) + set.addAll(Arrays.asList(parent.allKeys())); + + set.addAll(inputMap.keySet()); + KeyStroke[] array = new KeyStroke[size()]; + return (KeyStroke[]) set.toArray(array); + } + + /** + * writeObject + * + * @param stream the stream to write to + * + * @exception IOException If an error occurs + */ + private void writeObject(ObjectOutputStream stream) throws IOException + { + // TODO + } + + /** + * readObject + * + * @param stream the stream to read from + * + * @exception ClassNotFoundException If the serialized class cannot be found + * @exception IOException If an error occurs + */ + private void readObject(ObjectInputStream stream) + throws ClassNotFoundException, IOException + { + // TODO + } +} diff --git a/libjava/classpath/javax/swing/InputVerifier.java b/libjava/classpath/javax/swing/InputVerifier.java new file mode 100644 index 0000000..836c1a5 --- /dev/null +++ b/libjava/classpath/javax/swing/InputVerifier.java @@ -0,0 +1,75 @@ +/* InputVerifier.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + + +/** + * InputVerifier + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class InputVerifier +{ + /** + * Creates a InputVerifier + */ + public InputVerifier() + { + } + + /** + * verify + * + * @param component the component to verify + * + * @return true if valid, false otherwise. + */ + public abstract boolean verify(JComponent component); + + /** + * shouldYieldFocus + * + * @param component the component to verify + * + * @return true if valid, false otherwise. + */ + public boolean shouldYieldFocus(JComponent component) + { + return verify(component); + } +} diff --git a/libjava/classpath/javax/swing/InternalFrameFocusTraversalPolicy.java b/libjava/classpath/javax/swing/InternalFrameFocusTraversalPolicy.java new file mode 100644 index 0000000..0609f09 --- /dev/null +++ b/libjava/classpath/javax/swing/InternalFrameFocusTraversalPolicy.java @@ -0,0 +1,55 @@ +/* InternalFrameFocusTraversalPolicy.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.FocusTraversalPolicy; + +/** + * @author Michael Koch + * + * @since 1.4 + */ +public abstract class InternalFrameFocusTraversalPolicy extends FocusTraversalPolicy +{ + public Component getInitialComponent(JInternalFrame frame) + { + return getDefaultComponent(frame); + } +} diff --git a/libjava/classpath/javax/swing/JApplet.java b/libjava/classpath/javax/swing/JApplet.java new file mode 100644 index 0000000..95a05c0 --- /dev/null +++ b/libjava/classpath/javax/swing/JApplet.java @@ -0,0 +1,213 @@ +/* JApplet.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.LayoutManager; +import java.awt.event.KeyEvent; + +import javax.accessibility.AccessibleContext; + +public class JApplet extends Applet + implements RootPaneContainer +{ + private static final long serialVersionUID = 7269359214497372587L; + + protected JRootPane rootPane; + + /** + * @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; + + public JApplet() + { + super.setLayout(new BorderLayout(1, 1)); + getRootPane(); // Will do set/create. + initStageDone = true; // Init stage is now over. + } + + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + public void setLayout(LayoutManager manager) + { + // 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); + } + else + super.setLayout(manager); + } + + public void setLayeredPane(JLayeredPane layeredPane) + { + getRootPane().setLayeredPane(layeredPane); + } + + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } + + public JRootPane getRootPane() + { + if (rootPane == null) + setRootPane(createRootPane()); + return rootPane; + } + + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); + + rootPane = root; + add(rootPane, BorderLayout.CENTER); + } + + protected JRootPane createRootPane() + { + return new JRootPane(); + } + + public Container getContentPane() + { + return getRootPane().getContentPane(); + } + + public void setContentPane(Container contentPane) + { + getRootPane().setContentPane(contentPane); + } + + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + public void setGlassPane(Component glassPane) + { + getRootPane().setGlassPane(glassPane); + } + + protected void addImpl(Component comp, Object constraints, int index) + { + // 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); + else + { + if (isRootPaneCheckingEnabled()) + throw new Error("Do not use add() on JApplet directly. Use " + + "getContentPane().add() instead"); + getContentPane().add(comp, constraints, index); + } + } + + public AccessibleContext getAccessibleContext() + { + return null; + } + + public JMenuBar getJMenuBar() + { + return getRootPane().getJMenuBar(); + } + + public void setJMenuBar(JMenuBar menubar) + { + getRootPane().setJMenuBar(menubar); + } + + protected String paramString() + { + return "JFrame"; + } + + protected void processKeyEvent(KeyEvent e) + { + super.processKeyEvent(e); + } + + public void remove(Component comp) + { + // If we're removing the root pane, use super.remove. Otherwise + // pass it on to the content pane instead + if (comp == rootPane) + super.remove(rootPane); + else + getContentPane().remove(comp); + } + + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + public void update(Graphics g) + { + paint(g); + } +} diff --git a/libjava/classpath/javax/swing/JButton.java b/libjava/classpath/javax/swing/JButton.java new file mode 100644 index 0000000..0234e47 --- /dev/null +++ b/libjava/classpath/javax/swing/JButton.java @@ -0,0 +1,155 @@ +/* JButton.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.plaf.ButtonUI; + + +/** + * An instance of JButton can be added to a panel, frame etc + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JButton extends AbstractButton + implements Accessible +{ + private static final long serialVersionUID = -1907255238954382202L; + boolean def; + boolean is_def; + + public JButton() + { + this(null, null); + } + + public JButton(Action a) + { + this(); + setAction(a); + } + + public JButton(Icon icon) + { + this(null, icon); + } + + public JButton(String text) + { + this(text, null); + } + + public JButton(String text, Icon icon) + { + super(); + init(text, icon); + setModel(new DefaultButtonModel()); + } + + public Object[] getSelectedObjects() + { + return null; + } + + protected void configurePropertiesFromAction(Action a) + { + // Factory method which sets the AbstractButton's properties according to + // values from the Action instance. + super.configurePropertiesFromAction(a); + } + + public AccessibleContext getAccessibleContext() + { + // Gets the AccessibleContext associated with this JButton. + return null; + } + + public String getUIClassID() + { + // Returns a string that specifies the name of the L&F class that renders + // this component. + return "ButtonUI"; + } + + public boolean isDefaultButton() + { + // Returns whether or not this button is the default button on the + // RootPane. + return is_def; + } + + public boolean isDefaultCapable() + { + // Returns whether or not this button is capable of being the default + // button on the RootPane. + return def; + } + + protected String paramString() + { + String superParam = super.paramString(); + + // 41 is the maximum number of chars which may be needed. + StringBuffer sb = new StringBuffer(41); + sb.append(",defaultButton=").append(is_def); + sb.append(",defaultCapable=").append(def); + + return superParam + sb.toString(); + } + + /** + * Overrides JComponent.removeNotify to check if this button is currently + * set as the default button on the RootPane, and if so, sets the RootPane's + * default button to null to ensure the RootPane doesn't hold onto an invalid + * button reference. + */ + public void removeNotify() + { + } + + public void setDefaultCapable(boolean defaultCapable) + { + def = defaultCapable; + } + + public void updateUI() + { + setUI((ButtonUI) UIManager.getUI(this)); + } +} diff --git a/libjava/classpath/javax/swing/JCheckBox.java b/libjava/classpath/javax/swing/JCheckBox.java new file mode 100644 index 0000000..5e7e80c --- /dev/null +++ b/libjava/classpath/javax/swing/JCheckBox.java @@ -0,0 +1,143 @@ +/* JCheckBox.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import javax.accessibility.AccessibleContext; + +/** + * An instance of JCheckbox can be added to a panel, frame etc + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JCheckBox extends JToggleButton +{ + private static final long serialVersionUID = -5246739313864538930L; + + public static final String BORDER_PAINTED_FLAT_CHANGED_PROPERTY = + "borderPaintedFlat"; + + private boolean borderPaintedFlat; + + private void init() + { + borderPainted = false; + contentAreaFilled = false; + } + + public JCheckBox() + { + super(); + init(); + } + + public JCheckBox(Action action) + { + super(action); + init(); + } + + public JCheckBox(Icon icon) + { + super(icon); + init(); + } + + public JCheckBox(Icon icon, boolean selected) + { + super(icon, selected); + init(); + } + + public JCheckBox(String text) + { + super(text); + init(); + } + + public JCheckBox(String text, boolean selected) + { + super(text, selected); + init(); + } + + public JCheckBox(String text, Icon icon) + { + super(text, icon); + init(); + } + + public JCheckBox(String text, Icon icon, boolean selected) + { + super(text, icon, selected); + init(); + } + + /** + * 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. + */ + public String getUIClassID() + { + return "CheckBoxUI"; + } + + protected String paramString() + { + return super.paramString() + ",borderPaintedFlat=" + borderPaintedFlat; + } + + public boolean isBorderPaintedFlat() + { + return borderPaintedFlat; + } + + public void setBorderPaintedFlat(boolean newValue) + { + firePropertyChange("borderPaintedFlat", borderPaintedFlat, newValue); + borderPaintedFlat = newValue; + } +} diff --git a/libjava/classpath/javax/swing/JCheckBoxMenuItem.java b/libjava/classpath/javax/swing/JCheckBoxMenuItem.java new file mode 100644 index 0000000..46a42ad --- /dev/null +++ b/libjava/classpath/javax/swing/JCheckBoxMenuItem.java @@ -0,0 +1,251 @@ +/* JCheckBoxMenuItem.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class represents JCheckBoxMenuItem. Its behaviour is very similar + * to JCheckBoxButton. Just like the JCheckBoxButton, user can check and + * uncheck this menu item by clicking on it. Also setSelected()/setState() + * can be use used for the same purpose. JCheckBoxMenuItem uses + * ToggleButtonModel to keep track of its selection. + */ +public class JCheckBoxMenuItem extends JMenuItem implements SwingConstants, + Accessible +{ + private static final long serialVersionUID = -6676402307973384715L; + + /** name for the UI delegate for this menuItem. */ + private static final String uiClassID = "CheckBoxMenuItemUI"; + + /** Indicates whether this menu item is checked. */ + private boolean state; + + /** + * This array contains text of this menu item if this menu item is in + * checked state and null it is not. + */ + private Object[] selectedObjects = new Object[1]; + + /** + * Creates a new JCheckBoxMenuItem object. + */ + public JCheckBoxMenuItem() + { + this(null, null); + } + + /** + * Creates a new JCheckBoxMenuItem with given icon + * + * @param icon Icon for this menu item + */ + public JCheckBoxMenuItem(Icon icon) + { + this(null, icon); + } + + /** + * Creates a new JCheckBoxMenuItem with given label + * + * @param text Label for this menu item + */ + public JCheckBoxMenuItem(String text) + { + this(text, null); + } + + /** + * Creates a new JCheckBoxMenuItem using given action + * + * @param action Action for this menu item. + */ + public JCheckBoxMenuItem(Action action) + { + this(); + setAction(action); + } + + /** + * Creates a new JCheckBoxMenuItem object with given label and icon + * + * @param text Label for this menu item + * @param icon Icon for this menu item + */ + public JCheckBoxMenuItem(String text, Icon icon) + { + this(text, icon, false); + } + + /** + * Creates a new JCheckBoxMenuItem object using specified label and + * marked as checked if given 'state' is true. + * + * @param text Label for this menu item + * @param state true if this item should be in checked state and + * false otherwise + */ + public JCheckBoxMenuItem(String text, boolean state) + { + this(text, null, state); + } + + /** + * Creates a new JCheckBoxMenuItem object with given label, icon, + * and marked as checked if given 'state' is true. + * + * @param text Label for this menu item + * @param icon icon for this menu item + * @param state true if this item should be in checked state and + * false otherwise + */ + public JCheckBoxMenuItem(String text, Icon icon, boolean state) + { + super(text, icon); + setModel(new JToggleButton.ToggleButtonModel()); + this.state = state; + } + + 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. + * + * @return The Look and Feel classID. "JCheckBoxMenuItemUI" + */ + public String getUIClassID() + { + return uiClassID; + } + + /** + * Returns checked state for this check box menu item. + * + * @return Returns true if this menu item is in checked state + * and false otherwise. + */ + public boolean getState() + { + return state; + } + + /** + * Sets state for this check box menu item. If + * given 'state' is true, then mark menu item as checked, + * and uncheck this menu item otherwise. + * + * @param state new state for this menu item + */ + public synchronized void setState(boolean state) + { + this.state = state; + } + + /** + * This method returns array containing label of this + * menu item if it is selected and null otherwise. + * + * @return Array containing label of this + * menu item if this menu item is selected or null otherwise. + */ + public Object[] getSelectedObjects() + { + if (state == true) + selectedObjects[0] = this.getText(); + else + selectedObjects[0] = null; + + return selectedObjects; + } + + /** + * This method overrides JComponent.requestFocus with an empty + * implementation, since JCheckBoxMenuItems should not + * receve focus in general. + */ + public void requestFocus() + { + // Should do nothing here + } + + /** + * A string that describes this JCheckBoxMenuItem. Normally only used + * for debugging. + * + * @return A string describing this JCheckBoxMenuItem + */ + protected String paramString() + { + return "JCheckBoxMenuItem"; + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJCheckBoxMenuItem(); + + return accessibleContext; + } + + protected class AccessibleJCheckBoxMenuItem extends AccessibleJMenuItem + { + private static final long serialVersionUID = 1079958073579370777L; + + /** + * Creates a new AccessibleJCheckBoxMenuItem object. + */ + protected AccessibleJCheckBoxMenuItem() + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.CHECK_BOX; + } + } +} diff --git a/libjava/classpath/javax/swing/JColorChooser.java b/libjava/classpath/javax/swing/JColorChooser.java new file mode 100644 index 0000000..e16b981 --- /dev/null +++ b/libjava/classpath/javax/swing/JColorChooser.java @@ -0,0 +1,702 @@ +/* JColorChooser.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTError; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.colorchooser.AbstractColorChooserPanel; +import javax.swing.colorchooser.ColorSelectionModel; +import javax.swing.colorchooser.DefaultColorSelectionModel; +import javax.swing.plaf.ColorChooserUI; + + +/** + * The JColorChooser is a Swing widget that offers users different ways to + * select a color. By default, three different panels are presented to the + * user that are capable of changing the selected color. There are three ways + * to utilize JColorChooser. The first is to build a JColorChooser and add it + * to the content pane. The second is to use the createDialog method to + * create a JDialog that holds a JColorChooser. The third is to show a + * JColorChooser in a JDialog directly using the showDialog method. + */ +public class JColorChooser extends JComponent implements Accessible +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = 9168066781620640889L; + + /** + * AccessibleJColorChooser + */ + protected class AccessibleJColorChooser + extends JComponent.AccessibleJComponent + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = -2038297864782299082L; + + /** + * Constructor AccessibleJColorChooser + */ + protected AccessibleJColorChooser() + { + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.COLOR_CHOOSER; + } // getAccessibleRole() + } // AccessibleJColorChooser + + /** The model used with the JColorChooser. */ + private ColorSelectionModel selectionModel; + + /** The preview panel associated with the JColorChooser. */ + private JComponent previewPanel; + + /** + * The set of AbstractColorChooserPanels associated with the JColorChooser. + */ + private AbstractColorChooserPanel[] chooserPanels; + + /** A Drag and Drop property. */ + private boolean dragEnabled; + + /** + * The property fired by the JColorChooser when the selectionModel property + * changes. + */ + public static final String SELECTION_MODEL_PROPERTY = "selectionModel"; + + /** + * The property fired by the JColorChooser when the previewPanel property + * changes. + */ + public static final String PREVIEW_PANEL_PROPERTY = "previewPanel"; + + /** + * The property fired by the JColorChooser when the chooserPanels property + * changes. + */ + public static final String CHOOSER_PANELS_PROPERTY = "chooserPanels"; + + /** accessibleContext */ + protected AccessibleContext accessibleContext; + + /** + * This method creates a new JColorChooser with the default initial color. + */ + public JColorChooser() + { + this(new DefaultColorSelectionModel()); + } // JColorChooser() + + /** + * This method creates a new JColorChooser with the given initial color. + * + * @param initial The initial color. + */ + public JColorChooser(Color initial) + { + this(new DefaultColorSelectionModel(initial)); + } // JColorChooser() + + /** + * This method creates a new JColorChooser with the given model. The model + * will dictate what the initial color for the JColorChooser is. + * + * @param model The Model to use with the JColorChooser. + */ + public JColorChooser(ColorSelectionModel model) + { + if (model == null) + model = new DefaultColorSelectionModel(); + selectionModel = model; + updateUI(); + } // JColorChooser() + + /** + * This method sets the current color for the JColorChooser. + * + * @param color The new color for the JColorChooser. + */ + public void setColor(Color color) + { + if (color != null) + selectionModel.setSelectedColor(color); + } // setColor() + + /** + * This method sets the current color for the JColorChooser using RGB + * values. + * + * @param r The red value. + * @param g The green value. + * @param b The blue value. + */ + public void setColor(int r, int g, int b) + { + selectionModel.setSelectedColor(new Color(r, g, b)); + } // setColor() + + /** + * This method sets the current color for the JColorChooser using the + * integer value. Bits 0-7 represent the blue value. Bits 8-15 represent + * the green value. Bits 16-23 represent the red value. + * + * @param color The new current color of the JColorChooser. + */ + public void setColor(int color) + { + setColor(new Color(color, false)); + } // setColor() + + /** + * This method shows a JColorChooser inside a JDialog. The JDialog will + * block until it is hidden. The JDialog comes with three buttons: OK, + * Cancel, and Reset. Pressing OK or Cancel hide the JDialog. Pressing + * Reset will reset the JColorChooser to its initial value. + * + * @param component The Component that parents the JDialog. + * @param title The title displayed in the JDialog. + * @param initial The initial color. + * + * @return The selected color. + */ + public static Color showDialog(Component component, String title, + Color initial) + { + JColorChooser choose = new JColorChooser(initial); + + JDialog dialog = createDialog(component, title, true, choose, null, null); + + dialog.getContentPane().add(choose); + dialog.pack(); + dialog.show(); + + return choose.getColor(); + } // showDialog() + + /** + * This is a helper method to make the given JDialog block until it is + * hidden. This is package-private to avoid an accessor method. + * + * @param dialog The JDialog to block. + */ + static void makeModal(JDialog dialog) + { + try + { + synchronized (dialog) + { + while (dialog.isVisible()) + dialog.wait(); + } + } + catch (InterruptedException e) + { + } + } + + /** + * This is a helper method to find the first Frame or Dialog ancestor of the + * given Component. + * + * @param c The Component to find ancestors for. + * + * @return A Frame or Dialog ancestor. Null if none are found. + */ + private static Component findParent(Component c) + { + Component parent = SwingUtilities.getAncestorOfClass(Frame.class, c); + if (parent != null) + return parent; + parent = SwingUtilities.getAncestorOfClass(Dialog.class, c); + return parent; + } + + /** + * This method will take the given JColorChooser and place it in a JDialog + * with the given modal property. Three buttons are displayed in the + * JDialog: OK, Cancel and Reset. If OK or Cancel are pressed, the JDialog + * is hidden. If Reset is pressed, then the JColorChooser will take on its + * default color value. The given okListener will be registered to the OK + * button and the cancelListener will be registered to the Cancel button. + * If the modal property is set, then the JDialog will block until it is + * hidden. + * + * @param component The Component that will parent the JDialog. + * @param title The title displayed in the JDialog. + * @param modal The modal property. + * @param chooserPane The JColorChooser to place in the JDialog. + * @param okListener The ActionListener to register to the OK button. + * @param cancelListener The ActionListener to register to the Cancel + * button. + * + * @return A JDialog with the JColorChooser inside of it. + * + * @throws AWTError If the component is not a suitable parent. + */ + public static JDialog createDialog(Component component, String title, + boolean modal, JColorChooser chooserPane, + ActionListener okListener, + ActionListener cancelListener) + { + Component parent = findParent(component); + if (parent == null) + throw new AWTError("No suitable parent found for Component."); + JDialog dialog; + if (parent instanceof Frame) + dialog = new ModalDialog((Frame) parent, title); + else + dialog = new ModalDialog((Dialog) parent, title); + dialog.setModal(modal); + + dialog.getContentPane().setLayout(new BorderLayout()); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + + ActionListener al = new DefaultOKCancelListener(dialog); + + JButton ok = new JButton("OK"); + ok.addActionListener(okListener); + ok.addActionListener(al); + + JButton cancel = new JButton("Cancel"); + cancel.addActionListener(cancelListener); + cancel.addActionListener(al); + + JButton reset = new JButton("Reset"); + reset.addActionListener(new DefaultResetListener(chooserPane)); + + dialog.getContentPane().add(chooserPane, BorderLayout.NORTH); + + panel.add(ok); + panel.add(cancel); + panel.add(reset); + + dialog.getContentPane().add(panel, BorderLayout.SOUTH); + + return dialog; + } // createDialog() + + /** + * This method returns the UI Component used for this JColorChooser. + * + * @return The UI Component for this JColorChooser. + */ + public ColorChooserUI getUI() + { + return (ColorChooserUI) ui; + } // getUI() + + /** + * This method sets the UI Component used for this JColorChooser. + * + * @param ui The UI Component to use with this JColorChooser. + */ + public void setUI(ColorChooserUI ui) + { + super.setUI(ui); + } // setUI() + + /** + * This method resets the UI Component property to the Look and Feel + * default. + */ + public void updateUI() + { + setUI((ColorChooserUI) UIManager.getUI(this)); + revalidate(); + } // updateUI() + + /** + * This method returns a String identifier for the UI Class to be used with + * the JColorChooser. + * + * @return The String identifier for the UI Class. + */ + public String getUIClassID() + { + return "ColorChooserUI"; + } // getUIClassID() + + /** + * This method returns the current color for the JColorChooser. + * + * @return The current color for the JColorChooser. + */ + public Color getColor() + { + return selectionModel.getSelectedColor(); // TODO + } // getColor() + + /** + * This method changes the previewPanel property for the JTabbedPane. The + * previewPanel is responsible for indicating the current color of the + * JColorChooser. + * + * @param component The Component that will act as the previewPanel. + */ + public void setPreviewPanel(JComponent component) + { + if (component != previewPanel) + { + JComponent old = previewPanel; + previewPanel = component; + firePropertyChange(PREVIEW_PANEL_PROPERTY, old, previewPanel); + } + } // setPreviewPanel() + + /** + * This method returns the current previewPanel used with this + * JColorChooser. + * + * @return The current previewPanel. + */ + public JComponent getPreviewPanel() + { + return previewPanel; // TODO + } // getPreviewPanel() + + /** + * This method adds the given AbstractColorChooserPanel to the list of the + * JColorChooser's chooserPanels. + * + * @param panel The AbstractColorChooserPanel to add. + */ + public void addChooserPanel(AbstractColorChooserPanel panel) + { + if (panel == null) + return; + AbstractColorChooserPanel[] old = chooserPanels; + AbstractColorChooserPanel[] newPanels = + new AbstractColorChooserPanel[(old == null) ? 1 : old.length + 1]; + if (old != null) + System.arraycopy(old, 0, newPanels, 0, old.length); + newPanels[newPanels.length - 1] = panel; + chooserPanels = newPanels; + panel.installChooserPanel(this); + firePropertyChange(CHOOSER_PANELS_PROPERTY, old, newPanels); + } // addChooserPanel() + + /** + * This method removes the given AbstractColorChooserPanel from the + * JColorChooser's list of chooserPanels. + * + * @param panel The AbstractColorChooserPanel to remove. + * + * @return The AbstractColorChooserPanel that was removed. + */ + public AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel panel) + { + int index = -1; + for (int i = 0; i < chooserPanels.length; i++) + if (panel == chooserPanels[i]) + { + index = i; + break; + } + + if (index == -1) + return null; + + AbstractColorChooserPanel[] old = chooserPanels; + if (chooserPanels.length == 1) + chooserPanels = null; + else + { + AbstractColorChooserPanel[] newPanels = + new AbstractColorChooserPanel[chooserPanels.length - 1]; + System.arraycopy(chooserPanels, 0, newPanels, 0, index); + System.arraycopy(chooserPanels, index, newPanels, index - 1, + chooserPanels.length - index); + chooserPanels = newPanels; + } + panel.uninstallChooserPanel(this); + firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels); + return panel; + } + + /** + * This method sets the chooserPanels property for this JColorChooser. + * + * @param panels The new set of AbstractColorChooserPanels to use. + */ + public void setChooserPanels(AbstractColorChooserPanel[] panels) + { + if (panels != chooserPanels) + { + if (chooserPanels != null) + for (int i = 0; i < chooserPanels.length; i++) + if (chooserPanels[i] != null) + chooserPanels[i].uninstallChooserPanel(this); + + AbstractColorChooserPanel[] old = chooserPanels; + chooserPanels = panels; + + if (panels != null) + for (int i = 0; i < panels.length; i++) + if (panels[i] != null) + panels[i].installChooserPanel(this); + + firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels); + } + } // setChooserPanels() + + /** + * This method returns the AbstractColorChooserPanels used with this + * JColorChooser. + * + * @return The AbstractColorChooserPanels used with this JColorChooser. + */ + public AbstractColorChooserPanel[] getChooserPanels() + { + return chooserPanels; + } // getChooserPanels() + + /** + * This method returns the ColorSelectionModel used with this JColorChooser. + * + * @return The ColorSelectionModel. + */ + public ColorSelectionModel getSelectionModel() + { + return selectionModel; + } // getSelectionModel() + + /** + * This method sets the ColorSelectionModel to be used with this + * JColorChooser. + * + * @param model The ColorSelectionModel to be used with this JColorChooser. + * + * @throws AWTError If the given model is null. + */ + public void setSelectionModel(ColorSelectionModel model) + { + if (model == null) + throw new AWTError("ColorSelectionModel is not allowed to be null."); + selectionModel = model; + } // setSelectionModel() + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean getDragEnabled() + { + return dragEnabled; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setDragEnabled(boolean b) + { + dragEnabled = b; + } + + /** + * This method returns a String describing the JColorChooser. + * + * @return A String describing the JColorChooser. + */ + protected String paramString() + { + return "JColorChooser"; + } // paramString() + + /** + * getAccessibleContext + * + * @return AccessibleContext + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJColorChooser(); + + return accessibleContext; + } + + /** + * A helper class that hides a JDialog when the action is performed. + */ + static class DefaultOKCancelListener implements ActionListener + { + /** The JDialog to hide. */ + private JDialog dialog; + + /** + * Creates a new DefaultOKCancelListener with the given JDialog to hide. + * + * @param dialog The JDialog to hide. + */ + public DefaultOKCancelListener(JDialog dialog) + { + super(); + this.dialog = dialog; + } + + /** + * This method hides the JDialog when called. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + dialog.hide(); + } + } + + /** + * This method resets the JColorChooser color to the initial color when the + * action is performed. + */ + static class DefaultResetListener implements ActionListener + { + /** The JColorChooser to reset. */ + private JColorChooser chooser; + + /** The initial color. */ + private Color init; + + /** + * Creates a new DefaultResetListener with the given JColorChooser. + * + * @param chooser The JColorChooser to reset. + */ + public DefaultResetListener(JColorChooser chooser) + { + super(); + this.chooser = chooser; + init = chooser.getColor(); + } + + /** + * This method resets the JColorChooser to its initial color. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + chooser.setColor(init); + } + } + + /** + * This is a custom JDialog that will notify when it is hidden and the modal + * property is set. + */ + static class ModalDialog extends JDialog + { + /** The modal property. */ + private boolean modal; + + /** + * Creates a new ModalDialog object with the given parent and title. + * + * @param parent The parent of the JDialog. + * @param title The title of the JDialog. + */ + public ModalDialog(Frame parent, String title) + { + super(parent, title); + } + + /** + * Creates a new ModalDialog object with the given parent and title. + * + * @param parent The parent of the JDialog. + * @param title The title of the JDialog. + */ + public ModalDialog(Dialog parent, String title) + { + super(parent, title); + } + + /** + * This method sets the modal property. + * + * @param modal The modal property. + */ + public void setModal(boolean modal) + { + this.modal = modal; + } + + /** + * This method shows the ModalDialog. + */ + public void show() + { + super.show(); + if (modal) + makeModal(this); + } + + /** + * This method hides the ModalDialog. + */ + public synchronized void hide() + { + super.hide(); + notifyAll(); + } + } +} diff --git a/libjava/classpath/javax/swing/JComboBox.java b/libjava/classpath/javax/swing/JComboBox.java new file mode 100644 index 0000000..4284ec8 --- /dev/null +++ b/libjava/classpath/javax/swing/JComboBox.java @@ -0,0 +1,1223 @@ +/* JComboBox.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.ItemSelectable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +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; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.ComboBoxUI; + +/** + * JComboBox. JComboBox is a container, that keeps track of elements added to + * it by the user. JComboBox allows user to select any item in its list and + * displays the selected item to the user. JComboBox also can show/hide popup + * menu containing its list of item whenever the mouse is pressed over it. + * + * @author Andrew Selkirk + * @author Olga Rodimina + * @author Robert Schuster + */ +public class JComboBox extends JComponent implements ItemSelectable, + ListDataListener, + ActionListener, + Accessible +{ + + private static final long serialVersionUID = 5654585963292734470L; + + /** + * Classes implementing this interface are + * responsible for matching key characters typed by the user with combo + * box's items. + */ + public static interface KeySelectionManager + { + int selectionForKey(char aKey, ComboBoxModel aModel); + } + + /** + * Maximum number of rows that should be visible by default in the + * JComboBox's popup + */ + private static final int DEFAULT_MAXIMUM_ROW_COUNT = 8; + + /** + * Data model used by JComboBox to keep track of its list data and currently + * selected element in the list. + */ + protected ComboBoxModel dataModel; + + /** + * Renderer renders(paints) every object in the combo box list in its + * associated list cell. This ListCellRenderer is used only when this + * JComboBox is uneditable. + */ + protected ListCellRenderer renderer; + + /** + * Editor that is responsible for editing an object in a combo box list. + */ + protected ComboBoxEditor editor; + + /** + * Number of rows that will be visible in the JComboBox's popup. + */ + protected int maximumRowCount; + + /** + * This field indicates if textfield of this JComboBox is editable or not. + */ + protected boolean isEditable; + + /** + * This field is reference to the current selection of the combo box. + */ + protected Object selectedItemReminder; + + /** + * keySelectionManager + */ + protected KeySelectionManager keySelectionManager; + + /** + * This actionCommand is used in ActionEvent that is fired to JComboBox's + * ActionListeneres. + */ + protected String actionCommand; + + /** + * This property indicates if heavyweight popup or lightweight popup will be + * used to diplay JComboBox's elements. + */ + protected boolean lightWeightPopupEnabled; + + /** + * The action taken when new item is selected in the JComboBox + */ + private Action action; + + /** + * since 1.4 If this field is set then comboBox's display area for the + * selected item will be set by default to this value. + */ + private Object prototypeDisplayValue; + + /** + * Constructs JComboBox object with specified data model for it. + *

Note that the JComboBox will not change the value that + * is preselected by your ComboBoxModel implementation.

+ * + * @param model Data model that will be used by this JComboBox to keep track + * of its list of items. + */ + public JComboBox(ComboBoxModel model) + { + setEditable(false); + setEnabled(true); + setMaximumRowCount(DEFAULT_MAXIMUM_ROW_COUNT); + setModel(model); + setActionCommand("comboBoxChanged"); + + lightWeightPopupEnabled = true; + isEditable = false; + + updateUI(); + } + + /** + * Constructs JComboBox with specified list of items. + * + * @param itemArray array containing list of items for this JComboBox + */ + public JComboBox(Object[] itemArray) + { + this(new DefaultComboBoxModel(itemArray)); + + if (itemArray.length > 0) + setSelectedIndex(0); + } + + /** + * Constructs JComboBox object with specified list of items. + * + * @param itemVector vector containing list of items for this JComboBox. + */ + public JComboBox(Vector itemVector) + { + this(new DefaultComboBoxModel(itemVector)); + + if (itemVector.size() > 0) + setSelectedIndex(0); + } + + /** + * Constructor. Creates new empty JComboBox. ComboBox's data model is set to + * DefaultComboBoxModel. + */ + public JComboBox() + { + this(new DefaultComboBoxModel()); + } + + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * This method returns true JComboBox is editable and false otherwise + * + * @return boolean true if JComboBox is editable and false otherwise + */ + public boolean isEditable() + { + return isEditable; + } + + /* + * This method adds ancestor listener to this JComboBox. + */ + protected void installAncestorListener() + { + /* FIXME: Need to implement. + * + * Need to add ancestor listener to this JComboBox. This listener + * should close combo box's popup list of items whenever it + * receives an AncestorEvent. + */ + } + + /** + * Set the "UI" property of the combo box, which is a look and feel class + * responsible for handling comboBox's input events and painting it. + * + * @param ui The new "UI" property + */ + public void setUI(ComboBoxUI ui) + { + super.setUI(ui); + } + + /** + * This method sets this comboBox's UI to the UIManager's default for the + * current look and feel. + */ + public void updateUI() + { + setUI((ComboBoxUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns the String identifier for the UI class to the used + * with the JComboBox. + * + * @return The String identifier for the UI class. + */ + public String getUIClassID() + { + return "ComboBoxUI"; + } + + /** + * This method returns the UI used to display the JComboBox. + * + * @return The UI used to display the JComboBox. + */ + public ComboBoxUI getUI() + { + return (ComboBoxUI) ui; + } + + /** + * Set the data model for this JComboBox. This un-registers all listeners + * associated with the current model, and re-registers them with the new + * model. + * + * @param newDataModel The new data model for this JComboBox + */ + public void setModel(ComboBoxModel newDataModel) + { + // dataModel is null if it this method is called from inside the constructors. + if (dataModel != null) + { + // Prevents unneccessary updates. + if (dataModel == newDataModel) + return; + + // Removes itself (as DataListener) from the to-be-replaced model. + dataModel.removeListDataListener(this); + } + + /* Adds itself as a DataListener to the new model. + * It is intentioned that this operation will fail with a NullPointerException if the + * caller delivered a null argument. + */ + newDataModel.addListDataListener(this); + + // Stores old data model for event notification. + ComboBoxModel oldDataModel = dataModel; + dataModel = newDataModel; + + // Notifies the listeners of the model change. + firePropertyChange("model", oldDataModel, dataModel); + } + + /** + * This method returns data model for this comboBox. + * + * @return ComboBoxModel containing items for this combo box. + */ + public ComboBoxModel getModel() + { + return dataModel; + } + + /** + * This method sets JComboBox's popup to be either lightweight or + * heavyweight. If 'enabled' is true then lightweight popup is used and + * heavyweight otherwise. By default lightweight popup is used to display + * this JComboBox's elements. + * + * @param enabled indicates if lightweight popup or heavyweight popup should + * be used to display JComboBox's elements. + */ + public void setLightWeightPopupEnabled(boolean enabled) + { + lightWeightPopupEnabled = enabled; + } + + /** + * This method returns whether popup menu that is used to display list of + * combo box's item is lightWeight or not. + * + * @return boolean true if popup menu is lightweight and false otherwise. + */ + public boolean isLightWeightPopupEnabled() + { + return lightWeightPopupEnabled; + } + + /** + * This method sets editability of the combo box. If combo box is editable + * the user can choose component from the combo box list by typing + * component's name in the editor(JTextfield by default). Otherwise if not + * editable, the user should use the list to choose the component. This + * method fires PropertyChangeEvents to JComboBox's registered + * PropertyChangeListeners to indicate that 'editable' property of the + * JComboBox has changed. + * + * @param editable indicates if the JComboBox's textfield should be editable + * or not. + */ + public void setEditable(boolean editable) + { + if (isEditable != editable) + { + isEditable = editable; + firePropertyChange("editable", !isEditable, isEditable); + } + } + + /** + * Sets number of rows that should be visible in this JComboBox's popup. If + * this JComboBox's popup has more elements that maximum number or rows + * then popup will have a scroll pane to allow users to view other + * elements. + * + * @param rowCount number of rows that will be visible in JComboBox's popup. + */ + public void setMaximumRowCount(int rowCount) + { + if (maximumRowCount != rowCount) + { + int oldMaximumRowCount = maximumRowCount; + maximumRowCount = rowCount; + firePropertyChange("maximumRowCount", oldMaximumRowCount, + maximumRowCount); + } + } + + /** + * This method returns number of rows visible in the JComboBox's list of + * items. + * + * @return int maximun number of visible rows in the JComboBox's list. + */ + public int getMaximumRowCount() + { + return maximumRowCount; + } + + /** + * This method sets cell renderer for this JComboBox that will be used to + * paint combo box's items. The Renderer should only be used only when + * JComboBox is not editable. In the case when JComboBox is editable the + * editor must be used. This method also fires PropertyChangeEvent when + * cellRendered for this JComboBox has changed. + * + * @param aRenderer cell renderer that will be used by this JComboBox to + * paint its elements. + */ + public void setRenderer(ListCellRenderer aRenderer) + { + if (renderer != aRenderer) + { + ListCellRenderer oldRenderer = renderer; + renderer = aRenderer; + firePropertyChange("renderer", oldRenderer, renderer); + } + } + + /** + * This method returns renderer responsible for rendering selected item in + * the combo box + * + * @return ListCellRenderer + */ + public ListCellRenderer getRenderer() + { + return renderer; + } + + /** + * Sets editor for this JComboBox + * + * @param newEditor ComboBoxEditor for this JComboBox. This method fires + * PropertyChangeEvent when 'editor' property is changed. + */ + public void setEditor(ComboBoxEditor newEditor) + { + if (editor == newEditor) + return; + + if (editor != null) + editor.removeActionListener(this); + + ComboBoxEditor oldEditor = editor; + editor = newEditor; + + if (editor != null) + editor.addActionListener(this); + + firePropertyChange("editor", oldEditor, editor); + } + + /** + * Returns editor component that is responsible for displaying/editing + * selected item in the combo box. + * + * @return ComboBoxEditor + */ + public ComboBoxEditor getEditor() + { + return editor; + } + + /** + * Forces combo box to select given item + * + * @param item element in the combo box to select. + */ + public void setSelectedItem(Object item) + { + dataModel.setSelectedItem(item); + } + + /** + * Returns currently selected item in the combo box. + * The result may be null to indicate that nothing is + * currently selected. + * + * @return element that is currently selected in this combo box. + */ + public Object getSelectedItem() + { + return dataModel.getSelectedItem(); + } + + /** + * Forces JComboBox to select component located in the given index in the + * combo box. + *

If the index is below -1 or exceeds the upper bound an + * IllegalArgumentException is thrown.

+ *

If the index is -1 then no item gets selected.

+ * + * @param index index specifying location of the component that should be + * selected. + */ + public void setSelectedIndex(int index) + { + if (index < -1 || index >= dataModel.getSize()) + // Fails because index is out of bounds. + throw new IllegalArgumentException("illegal index: " + index); + else + // Selects the item at the given index or clears the selection if the + // index value is -1. + setSelectedItem((index == -1) ? null : dataModel.getElementAt(index)); + } + + /** + * Returns index of the item that is currently selected in the combo box. If + * no item is currently selected, then -1 is returned. + *

+ * Note: For performance reasons you should minimize invocation of this + * method. If the data model is not an instance of + * DefaultComboBoxModel the complexity is O(n) where n is the + * number of elements in the combo box. + *

+ * + * @return int Index specifying location of the currently selected item in the + * combo box or -1 if nothing is selected in the combo box. + */ + public int getSelectedIndex() + { + Object selectedItem = getSelectedItem(); + + if (selectedItem != null) + { + if (dataModel instanceof DefaultComboBoxModel) + // Uses special method of DefaultComboBoxModel to retrieve the index. + return ((DefaultComboBoxModel) dataModel).getIndexOf(selectedItem); + else + { + // Iterates over all items to retrieve the index. + int size = dataModel.getSize(); + + for (int i = 0; i < size; i++) + { + Object o = dataModel.getElementAt(i); + + // XXX: Is special handling of ComparableS neccessary? + if ((selectedItem != null) ? selectedItem.equals(o) : o == null) + return i; + } + } + } + + // returns that no item is currently selected + return -1; + } + + public Object getPrototypeDisplayValue() + { + return prototypeDisplayValue; + } + + public void setPrototypeDisplayValue(Object newPrototypeDisplayValue) + { + prototypeDisplayValue = newPrototypeDisplayValue; + } + + /** + * This method adds given element to this JComboBox. + *

A RuntimeException is thrown if the data model is not + * an instance of {@link MutableComboBoxModel}.

+ * + * @param element element to add + */ + public void addItem(Object element) + { + if (dataModel instanceof MutableComboBoxModel) + ((MutableComboBoxModel) dataModel).addElement(element); + else + throw new RuntimeException("Unable to add the item because the data " + + "model it is not an instance of " + + "MutableComboBoxModel."); + } + + /** + * Inserts given element at the specified index to this JComboBox. + *

A RuntimeException is thrown if the data model is not + * an instance of {@link MutableComboBoxModel}.

+ * + * @param element element to insert + * @param index position where to insert the element + */ + public void insertItemAt(Object element, int index) + { + if (dataModel instanceof MutableComboBoxModel) + ((MutableComboBoxModel) dataModel).insertElementAt(element, index); + else + throw new RuntimeException("Unable to insert the item because the data " + + "model it is not an instance of " + + "MutableComboBoxModel."); + } + + /** + * This method removes given element from this JComboBox. + *

A RuntimeException is thrown if the data model is not + * an instance of {@link MutableComboBoxModel}.

+ * + * @param element element to remove + */ + public void removeItem(Object element) + { + if (dataModel instanceof MutableComboBoxModel) + ((MutableComboBoxModel) dataModel).removeElement(element); + else + throw new RuntimeException("Unable to remove the item because the data " + + "model it is not an instance of " + + "MutableComboBoxModel."); + } + + /** + * This method remove element location in the specified index in the + * JComboBox. + *

A RuntimeException is thrown if the data model is not + * an instance of {@link MutableComboBoxModel}.

+ * + * @param index index specifying position of the element to remove + */ + public void removeItemAt(int index) + { + if (dataModel instanceof MutableComboBoxModel) + ((MutableComboBoxModel) dataModel).removeElementAt(index); + else + throw new RuntimeException("Unable to remove the item because the data " + + "model it is not an instance of " + + "MutableComboBoxModel."); + } + + /** + * This method removes all elements from this JComboBox. + *

+ * A RuntimeException is thrown if the data model is not an + * instance of {@link MutableComboBoxModel}. + *

+ */ + public void removeAllItems() + { + if (dataModel instanceof DefaultComboBoxModel) + // Uses special method if we have a DefaultComboBoxModel. + ((DefaultComboBoxModel) dataModel).removeAllElements(); + else if (dataModel instanceof MutableComboBoxModel) + { + // Iterates over all items and removes each. + MutableComboBoxModel mcbm = (MutableComboBoxModel) dataModel; + + // We intentionally remove the items backwards to support models which + // shift their content to the beginning (e.g. linked lists) + for (int i = mcbm.getSize() - 1; i >= 0; i--) + mcbm.removeElementAt(i); + } + else + throw new RuntimeException("Unable to remove the items because the data " + +"model it is not an instance of " + + "MutableComboBoxModel."); + } + + /** + * This method displays popup with list of combo box's items on the screen + */ + public void showPopup() + { + setPopupVisible(true); + } + + /** + * This method hides popup containing list of combo box's items + */ + public void hidePopup() + { + setPopupVisible(false); + } + + /** + * This method either displayes or hides the popup containing list of combo + * box's items. + * + * @param visible show popup if 'visible' is true and hide it otherwise + */ + public void setPopupVisible(boolean visible) + { + getUI().setPopupVisible(this, visible); + } + + /** + * Checks if popup is currently visible on the screen. + * + * @return boolean true if popup is visible and false otherwise + */ + public boolean isPopupVisible() + { + return getUI().isPopupVisible(this); + } + + /** + * This method sets actionCommand to the specified string. ActionEvent fired + * to this JComboBox registered ActionListeners will contain this + * actionCommand. + * + * @param aCommand new action command for the JComboBox's ActionEvent + */ + public void setActionCommand(String aCommand) + { + actionCommand = aCommand; + } + + /** + * Returns actionCommand associated with the ActionEvent fired by the + * JComboBox to its registered ActionListeners. + * + * @return String actionCommand for the ActionEvent + */ + public String getActionCommand() + { + return actionCommand; + } + + /** + * setAction + * + * @param a action to set + */ + public void setAction(Action a) + { + Action old = action; + action = a; + configurePropertiesFromAction(action); + if (action != null) + // FIXME: remove from old action and add to new action + // PropertyChangeListener to listen to changes in the action + addActionListener(action); + } + + /** + * This method returns Action that is invoked when selected item is changed + * in the JComboBox. + * + * @return Action + */ + public Action getAction() + { + return action; + } + + /** + * Configure properties of the JComboBox by reading properties of specified + * action. This method always sets the comboBox's "enabled" property to the + * value of the Action's "enabled" property. + * + * @param a An Action to configure the combo box from + */ + protected void configurePropertiesFromAction(Action a) + { + if (a == null) + { + setEnabled(true); + setToolTipText(null); + } + else + { + setEnabled(a.isEnabled()); + setToolTipText((String) (a.getValue(Action.SHORT_DESCRIPTION))); + } + } + + /** + * Creates PropertyChangeListener to listen for the changes in comboBox's + * action properties. + * + * @param action action to listen to for property changes + * + * @return a PropertyChangeListener that listens to changes in + * action properties. + */ + protected PropertyChangeListener createActionPropertyChangeListener(Action action) + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + Action act = (Action) (e.getSource()); + configurePropertiesFromAction(act); + } + }; + } + + /** + * This method fires ItemEvent to this JComboBox's registered ItemListeners. + * This method is invoked when currently selected item in this combo box + * has changed. + * + * @param e the ItemEvent describing the change in the combo box's + * selection. + */ + protected void fireItemStateChanged(ItemEvent e) + { + ItemListener[] ll = getItemListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].itemStateChanged(e); + } + + /** + * This method fires ActionEvent to this JComboBox's registered + * ActionListeners. This method is invoked when user explicitly changes + * currently selected item. + */ + protected void fireActionEvent() + { + ActionListener[] ll = getActionListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].actionPerformed(new ActionEvent(this, + ActionEvent.ACTION_PERFORMED, + actionCommand)); + } + + /** + * 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 + * the change. + */ + protected void selectedItemChanged() + { + // Fire ItemEvent to indicated that previously selected item is now + // deselected + if (selectedItemReminder != null) + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + selectedItemReminder, + ItemEvent.DESELECTED)); + + // Fire ItemEvent to indicate that new item is selected + Object newSelection = getSelectedItem(); + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + newSelection, ItemEvent.SELECTED)); + + // Fire Action Event to JComboBox's registered listeners + fireActionEvent(); + + selectedItemReminder = newSelection; + } + + /** + * Returns Object array of size 1 containing currently selected element in + * the JComboBox. + * + * @return Object[] Object array of size 1 containing currently selected + * element in the JComboBox. + */ + public Object[] getSelectedObjects() + { + return new Object[] { getSelectedItem() }; + } + + /** + * This method handles actionEvents fired by the ComboBoxEditor. It changes + * this JComboBox's selection to the new value currently in the editor and + * hides list of combo box items. + * + * @param e the ActionEvent + */ + public void actionPerformed(ActionEvent e) + { + setSelectedItem(((ComboBoxEditor) e.getSource()).getItem()); + setPopupVisible(false); + } + + /** + * This method selects item in this combo box that matches specified + * specified keyChar and returns true if such item is found. Otherwise + * false is returned. + * + * @param keyChar character indicating which item in the combo box should be + * selected. + * + * @return boolean true if item corresponding to the specified keyChar + * exists in the combo box. Otherwise false is returned. + */ + public boolean selectWithKeyChar(char keyChar) + { + // FIXME: Need to implement + return false; + } + + /** + * The part of implementation of ListDataListener interface. This method is + * invoked when some items where added to the JComboBox's data model. + * + * @param event ListDataEvent describing the change + */ + public void intervalAdded(ListDataEvent event) + { + // FIXME: Need to implement + repaint(); + } + + /** + * The part of implementation of ListDataListener interface. This method is + * invoked when some items where removed from the JComboBox's data model. + * + * @param event ListDataEvent describing the change. + */ + public void intervalRemoved(ListDataEvent event) + { + // FIXME: Need to implement + repaint(); + } + + /** + * The part of implementation of ListDataListener interface. This method is + * invoked when contents of the JComboBox's data model changed. + * + * @param event ListDataEvent describing the change + */ + public void contentsChanged(ListDataEvent event) + { + // if first and last index of the given ListDataEvent are both -1, + // then it indicates that selected item in the combo box data model + // have changed. + if (event.getIndex0() == -1 && event.getIndex1() == -1) + selectedItemChanged(); + } + + /** + * This method disables or enables JComboBox. If the JComboBox is enabled, + * then user is able to make item choice, otherwise if JComboBox is + * disabled then user is not able to make a selection. + * + * @param enabled if 'enabled' is true then enable JComboBox and disable it + */ + public void setEnabled(boolean enabled) + { + boolean oldEnabled = super.isEnabled(); + if (enabled != oldEnabled) + { + super.setEnabled(enabled); + firePropertyChange("enabled", oldEnabled, enabled); + } + } + + /** + * This method initializes specified ComboBoxEditor to display given item. + * + * @param anEditor ComboBoxEditor to initialize + * @param anItem Item that should displayed in the specified editor + */ + public void configureEditor(ComboBoxEditor anEditor, Object anItem) + { + anEditor.setItem(anItem); + } + + /** + * This method hides combo box's popup whenever TAB key is pressed. + * + * @param e The KeyEvent indicating which key was pressed. + */ + 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; + } + + /** + * setKeySelectionManager + * + * @param aManager + */ + public void setKeySelectionManager(KeySelectionManager aManager) + { + } + + /** + * getKeySelectionManager + * + * @return JComboBox.KeySelectionManager + */ + public KeySelectionManager getKeySelectionManager() + { + return null; + } + + /** + * This method returns number of elements in this JComboBox + * + * @return int number of elements in this JComboBox + */ + public int getItemCount() + { + return dataModel.getSize(); + } + + /** + * Returns elements located in the combo box at the given index. + * + * @param index index specifying location of the component to return. + * + * @return component in the combo box that is located in the given index. + */ + public Object getItemAt(int index) + { + return dataModel.getElementAt(index); + } + + /** + * createDefaultKeySelectionManager + * + * @return KeySelectionManager + */ + protected KeySelectionManager createDefaultKeySelectionManager() + { + return null; + } + + /** + * A string that describes this JComboBox. Normally only used for debugging. + * + * @return A string describing this JComboBox + */ + protected String paramString() + { + return "JComboBox"; + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJComboBox(); + + return accessibleContext; + } + + /** + * This methods adds specified ActionListener to this JComboBox. + * + * @param listener to add + */ + public void addActionListener(ActionListener listener) + { + listenerList.add(ActionListener.class, listener); + } + + /** + * This method removes specified ActionListener from this JComboBox. + * + * @param listener ActionListener + */ + public void removeActionListener(ActionListener listener) + { + listenerList.remove(ActionListener.class, listener); + } + + /** + * This method returns array of ActionListeners that are registered with + * this JComboBox. + * + * @since 1.4 + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) getListeners(ActionListener.class); + } + + /** + * This method registers given ItemListener with this JComboBox + * + * @param listener to remove + */ + public void addItemListener(ItemListener listener) + { + listenerList.add(ItemListener.class, listener); + } + + /** + * This method unregisters given ItemListener from this JComboBox + * + * @param listener to remove + */ + public void removeItemListener(ItemListener listener) + { + listenerList.remove(ItemListener.class, listener); + } + + /** + * This method returns array of ItemListeners that are registered with this + * JComboBox. + * + * @since 1.4 + */ + public ItemListener[] getItemListeners() + { + return (ItemListener[]) getListeners(ItemListener.class); + } + + /** + * Adds PopupMenuListener to combo box to listen to the events fired by the + * combo box's popup menu containing its list of items + * + * @param listener to add + */ + public void addPopupMenuListener(PopupMenuListener listener) + { + listenerList.add(PopupMenuListener.class, listener); + } + + /** + * Removes PopupMenuListener to combo box to listen to the events fired by + * the combo box's popup menu containing its list of items + * + * @param listener to add + */ + public void removePopupMenuListener(PopupMenuListener listener) + { + listenerList.remove(PopupMenuListener.class, listener); + } + + /** + * Returns array of PopupMenuListeners that are registered with combo box. + */ + public PopupMenuListener[] getPopupMenuListeners() + { + return (PopupMenuListener[]) getListeners(PopupMenuListener.class); + } + + /** + * AccessibleJComboBox + */ + protected class AccessibleJComboBox extends AccessibleJComponent + implements AccessibleAction, AccessibleSelection + { + private static final long serialVersionUID = 8217828307256675666L; + + protected AccessibleJComboBox() + { + } + + public int getAccessibleChildrenCount() + { + return 0; + } + + public Accessible getAccessibleChild(int value0) + { + return null; + } + + public AccessibleSelection getAccessibleSelection() + { + return null; + } + + public Accessible getAccessibleSelection(int value0) + { + return null; + } + + public boolean isAccessibleChildSelected(int value0) + { + return false; + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.COMBO_BOX; + } + + public AccessibleAction getAccessibleAction() + { + return null; + } + + public String getAccessibleActionDescription(int value0) + { + return null; + } + + public int getAccessibleActionCount() + { + return 0; + } + + public boolean doAccessibleAction(int value0) + { + return false; + } + + public int getAccessibleSelectionCount() + { + return 0; + } + + public void addAccessibleSelection(int value0) + { + } + + public void removeAccessibleSelection(int value0) + { + } + + public void clearAccessibleSelection() + { + } + + public void selectAllAccessibleSelection() + { + } + } +} diff --git a/libjava/classpath/javax/swing/JComponent.java b/libjava/classpath/javax/swing/JComponent.java new file mode 100644 index 0000000..42a5317 --- /dev/null +++ b/libjava/classpath/javax/swing/JComponent.java @@ -0,0 +1,2680 @@ +/* JComponent.java -- Every component in swing inherits from this class. + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTEvent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.dnd.DropTarget; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusEvent; +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; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.io.Serializable; +import java.util.EventListener; +import java.util.Hashtable; +import java.util.Locale; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleExtendedComponent; +import javax.accessibility.AccessibleKeyBinding; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.swing.border.Border; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.event.EventListenerList; +import javax.swing.event.SwingPropertyChangeSupport; +import javax.swing.plaf.ComponentUI; + +/** + * Every component in swing inherits from this class (JLabel, JButton, etc). + * It contains generic methods to manage events, properties and sizes. Actual + * drawing of the component is channeled to a look-and-feel class that is + * implemented elsewhere. + * + * @author Ronald Veldema (rveldema&064;cs.vu.nl) + * @author Graydon Hoare (graydon&064;redhat.com) + */ +public abstract class JComponent extends Container implements Serializable +{ + private static final long serialVersionUID = -7908749299918704233L; + + /** + * Accessibility support is currently missing. + */ + protected AccessibleContext accessibleContext; + + public abstract class AccessibleJComponent + extends AccessibleAWTContainer + implements AccessibleExtendedComponent + { + protected class AccessibleFocusHandler + implements FocusListener + { + protected AccessibleFocusHandler(){} + public void focusGained(FocusEvent event){} + public void focusLost(FocusEvent valevent){} + } + + protected class AccessibleContainerHandler + implements ContainerListener + { + protected AccessibleContainerHandler() {} + public void componentAdded(ContainerEvent event) {} + public void componentRemoved(ContainerEvent valevent) {} + } + + private static final long serialVersionUID = -7047089700479897799L; + + 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; } + } + + /** + * An explicit value for the component's preferred size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getPreferredSize} method on the {@link #ui} property. + */ + Dimension preferredSize; + + /** + * An explicit value for the component's minimum size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getMinimumSize} method on the {@link #ui} property. + */ + Dimension minimumSize; + + /** + * An explicit value for the component's maximum size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getMaximumSize} method on the {@link #ui} property. + */ + Dimension maximumSize; + + /** + * A value between 0.0 and 1.0 indicating the preferred horizontal + * alignment of the component, relative to its siblings. The values + * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link + * #RIGHT_ALIGNMENT} can also be used, as synonyms for 0.0, + * 0.5, and 1.0, respectively. Not all layout + * managers use this property. + * + * @see #getAlignmentX + * @see #setAlignmentX + * @see javax.swing.OverlayLayout + * @see javax.swing.BoxLayout + */ + float alignmentX = 0.5f; + + /** + * A value between 0.0 and 1.0 indicating the preferred vertical + * alignment of the component, relative to its siblings. The values + * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link + * #BOTTOM_ALIGNMENT} can also be used, as synonyms for 0.0, + * 0.5, and 1.0, respectively. Not all layout + * managers use this property. + * + * @see #getAlignmentY + * @see #setAlignmentY + * @see javax.swing.OverlayLayout + * @see javax.swing.BoxLayout + */ + float alignmentY = 0.5f; + + /** + * The border painted around this component. + * + * @see #paintBorder + */ + Border border; + + /** + * The text to show in the tooltip associated with this component. + * + * @see #setToolTipText + * @see #getToolTipText + */ + String toolTipText; + + /** + *

Whether to double buffer this component when painting. This flag + * should generally be false, except for top level + * components such as {@link JFrame} or {@link JApplet}.

+ * + *

All children of a double buffered component are painted into the + * double buffer automatically, so only the top widget in a window needs + * to be double buffered.

+ * + * @see #setDoubleBuffered + * @see #isDoubleBuffered + * @see #paintLock + * @see #paint + */ + boolean doubleBuffered = false; + + /** + * A set of flags indicating which debugging graphics facilities should + * be enabled on this component. The values should be a combination of + * {@link DebugGraphics.NONE_OPTION}, {@link DebugGraphics.LOG_OPTION}, + * {@link DebugGraphics.FLASH_OPTION}, or {@link + * DebugGraphics.BUFFERED_OPTION}. + * + * @see setDebugGraphicsOptions + * @see getDebugGraphicsOptions + * @see DebugGraphics + * @see getComponentGraphics + */ + int debugGraphicsOptions; + + /** + *

This property controls two independent behaviors simultaneously.

+ * + *

First, it controls whether to fill the background of this widget + * when painting its body. This affects calls to {@link + * JComponent#paintComponent}, which in turn calls {@link + * ComponentUI#update} on the component's {@link #ui} property. If the + * component is opaque during this call, the background will be filled + * before calling {@link ComponentUI#paint}. This happens merely as a + * convenience; you may fill the component's background yourself too, + * but there is no need to do so if you will be filling with the same + * color.

+ * + *

Second, it the opaque property informs swing's repaint system + * whether it will be necessary to paint the components "underneath" this + * component, in Z-order. If the component is opaque, it is considered to + * completely occlude components "underneath" it, so they will not be + * repainted along with the opaque component.

+ * + *

The default value for this property is false, but most + * components will want to set it to true when installing UI + * defaults in {@link ComponentUI#installUI}.

+ * + * @see #setOpaque + * @see #isOpaque + * @see #paintComponent + */ + boolean opaque = false; + + /** + * The user interface delegate for this component. Event delivery and + * repainting of the component are usually delegated to this object. + * + * @see #setUI + * @see #getUI + * @see #updateUI + */ + protected ComponentUI ui; + + /** + * A hint to the focus system that this component should or should not + * get focus. If this is false, swing will not try to + * request focus on this component; if true, swing might + * try to request focus, but the request might fail. Thus it is only + * a hint guiding swing's behavior. + * + * @see #requestFocus + * @see #isRequestFocusEnabled + * @see #setRequestFocusEnabled + */ + boolean requestFocusEnabled; + + /** + * Flag indicating behavior of this component when the mouse is dragged + * outside the component and the mouse stops moving. If + * true, synthetic mouse events will be delivered on regular + * timed intervals, continuing off in the direction the mouse exited the + * component, until the mouse is released or re-enters the component. + * + * @see setAutoscrolls + * @see getAutoscrolls + */ + boolean autoscrolls = false; + + /** + * Listeners for events other than {@link PropertyChangeEvent} are + * handled by this listener list. PropertyChangeEvents are handled in + * {@link #changeSupport}. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Support for {@link PropertyChangeEvent} events. This is constructed + * lazily when the component gets its first {@link + * PropertyChangeListener} subscription; until then it's an empty slot. + */ + private SwingPropertyChangeSupport changeSupport; + + + /** + * Storage for "client properties", which are key/value pairs associated + * with this component by a "client", such as a user application or a + * layout manager. This is lazily constructed when the component gets its + * first client property. + */ + private Hashtable clientProperties; + + private InputMap inputMap_whenFocused; + private InputMap inputMap_whenAncestorOfFocused; + private InputMap inputMap_whenInFocusedWindow; + private ActionMap actionMap; + /** @since 1.3 */ + private boolean verifyInputWhenFocusTarget; + private InputVerifier inputVerifier; + + 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 + */ + private static final Object paintLock = new Object(); + + /** + * The default locale of the component. + * + * @see #getDefaultLocale + * @see #setDefaultLocale + */ + private static Locale defaultLocale; + + public static final String TOOL_TIP_TEXT_KEY = "ToolTipText"; + + /** + * Constant used to indicate that no condition has been assigned to a + * particular action. + * + * @see #registerKeyboardAction + */ + public static final int UNDEFINED_CONDITION = -1; + + /** + * Constant used to indicate that an action should be performed only when + * the component has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_FOCUSED = 0; + + /** + * Constant used to indicate that an action should be performed only when + * the component is an ancestor of the component which has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1; + + /** + * Constant used to indicate that an action should be performed only when + * the component is in the window which has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_IN_FOCUSED_WINDOW = 2; + + /** + * Creates a new JComponent instance. + */ + public JComponent() + { + super(); + super.setLayout(new FlowLayout()); + setDropTarget(new DropTarget()); + defaultLocale = Locale.getDefault(); + debugGraphicsOptions = DebugGraphics.NONE_OPTION; + setRequestFocusEnabled(true); + } + + /** + * Helper to lazily construct and return the client properties table. + * + * @return The current client properties table + * + * @see #clientProperties + * @see #getClientProperty + * @see #putClientProperty + */ + private Hashtable getClientProperties() + { + if (clientProperties == null) + clientProperties = new Hashtable(); + return clientProperties; + } + + /** + * Get a client property associated with this component and a particular + * key. + * + * @param key The key with which to look up the client property + * + * @return A client property associated with this object and key + * + * @see #clientProperties + * @see #getClientProperties + * @see #putClientProperty + */ + public final Object getClientProperty(Object key) + { + return getClientProperties().get(key); + } + + /** + * Add a client property value to this component, associated + * with key. If there is an existing client property + * associated with key, it will be replaced. + * + * @param key The key of the client property association to add + * @param value The value of the client property association to add + * + * @see #clientProperties + * @see #getClientProperties + * @see #getClientProperty + */ + public final void putClientProperty(Object key, Object value) + { + getClientProperties().put(key, value); + } + + /** + * Unregister an AncestorListener. + * + * @param listener The listener to unregister + * + * @see addAncestorListener + */ + public void removeAncestorListener(AncestorListener listener) + { + listenerList.remove(AncestorListener.class, listener); + } + + /** + * Unregister a PropertyChangeListener. + * + * @param listener The listener to register + * + * @see #addPropertyChangeListener + * @see #changeSupport + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + if (changeSupport != null) + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Unregister a PropertyChangeListener. + * + * @param propertyName The property name to unregister the listener from + * @param listener The listener to unregister + * + * @see #addPropertyChangeListener + * @see #changeSupport + */ + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) + { + if (changeSupport != null) + changeSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * Unregister a VetoableChangeChangeListener. + * + * @param listener The listener to unregister + * + * @see #addVetoableChangeListener + */ + public void removeVetoableChangeListener(VetoableChangeListener listener) + { + listenerList.remove(VetoableChangeListener.class, listener); + } + + /** + * Register an AncestorListener. + * + * @param listener The listener to register + * + * @see #removeVetoableChangeListener + */ + public void addAncestorListener(AncestorListener listener) + { + listenerList.add(AncestorListener.class, listener); + } + + /** + * Register a PropertyChangeListener. This listener will + * receive any PropertyChangeEvent, regardless of property name. To + * listen to a specific property name, use {@link + * #addPropertyChangeListener(String,PropertyChangeListener)} instead. + * + * @param listener The listener to register + * + * @see #removePropertyChangeListener + * @see #changeSupport + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + if (changeSupport == null) + changeSupport = new SwingPropertyChangeSupport(this); + changeSupport.addPropertyChangeListener(listener); + } + + /** + * Register a PropertyChangeListener for a specific, named + * property. To listen to all property changes, regardless of name, use + * {@link #addPropertyChangeListener(PropertyChangeListener)} instead. + * + * @param propertyName The property name to listen to + * @param listener The listener to register + * + * @see #removePropertyChangeListener + * @see #changeSupport + */ + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) + { + listenerList.add(PropertyChangeListener.class, listener); + } + + /** + * Register a VetoableChangeListener. + * + * @param listener The listener to register + * + * @see #removeVetoableChangeListener + * @see #listenerList + */ + public void addVetoableChangeListener(VetoableChangeListener listener) + { + listenerList.add(VetoableChangeListener.class, listener); + } + + /** + * Return all registered listeners of a particular type. + * + * @param listenerType The type of listener to return + * + * @return All listeners in the {@link #listenerList} which + * are of the specified type + * + * @see #listenerList + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Return all registered AncestorListener objects. + * + * @return The set of AncestorListener objects in {@link + * #listenerList} + */ + public AncestorListener[] getAncestorListeners() + { + return (AncestorListener[]) getListeners(AncestorListener.class); + } + + /** + * Return all registered VetoableChangeListener objects. + * + * @return The set of VetoableChangeListener objects in {@link + * #listenerList} + */ + public VetoableChangeListener[] getVetoableChangeListeners() + { + return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class); + } + + /** + * Return all PropertyChangeListener objects registered to listen + * for a particular property. + * + * @param property The property to return the listeners of + * + * @return The set of PropertyChangeListener objects in + * {@link #changeSupport} registered to listen on the specified property + */ + public PropertyChangeListener[] getPropertyChangeListeners(String property) + { + return changeSupport == null ? new PropertyChangeListener[0] + : changeSupport.getPropertyChangeListeners(property); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with boolean values. + */ + public void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue), + Boolean.valueOf(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with byte values. + */ + public void firePropertyChange(String propertyName, byte oldValue, + byte newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Byte(oldValue), + new Byte(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with char values. + */ + public void firePropertyChange(String propertyName, char oldValue, + char newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Character(oldValue), + new Character(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with double values. + */ + public void firePropertyChange(String propertyName, double oldValue, + double newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Double(oldValue), + new Double(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with float values. + */ + public void firePropertyChange(String propertyName, float oldValue, + float newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Float(oldValue), + new Float(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with int values. + */ + public void firePropertyChange(String propertyName, int oldValue, + int newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Integer(oldValue), + new Integer(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with long values. + */ + public void firePropertyChange(String propertyName, long oldValue, + long newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Long(oldValue), + new Long(newValue)); + } + + /** + * Call {@link PropertyChangeListener#propertyChange} on all listeners + * registered to listen to a given property. Any method which changes + * the specified property of this component should call this method. + * + * @param propertyName The property which changed + * @param oldValue The old value of the property + * @param newValue The new value of the property + * + * @see #changeSupport + * @see #addPropertyChangeListener + * @see #removePropertyChangeListener + */ + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with short values. + */ + public void firePropertyChange(String propertyName, short oldValue, + short newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Short(oldValue), + new Short(newValue)); + } + + /** + * Call {@link VetoableChangeListener#vetoableChange} on all listeners + * registered to listen to a given property. Any method which changes + * the specified property of this component should call this method. + * + * @param propertyName The property which changed + * @param oldValue The old value of the property + * @param newValue The new value of the property + * + * @throws PropertyVetoException if the change was vetoed by a listener + * + * @see addVetoableChangeListener + * @see removeVetoableChangeListener + */ + protected void fireVetoableChange(String propertyName, Object oldValue, + Object newValue) + throws PropertyVetoException + { + VetoableChangeListener[] listeners = getVetoableChangeListeners(); + + PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue); + + for (int i = 0; i < listeners.length; i++) + listeners[i].vetoableChange(evt); + } + + /** + * Get the value of the accessibleContext property for this component. + * + * @return the current value of the property + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * Get the value of the {@link #alignmentX} property. + * + * @return The current value of the property. + * + * @see #setAlignmentX + * @see #alignmentY + */ + public float getAlignmentX() + { + return alignmentX; + } + + /** + * Get the value of the {@link #alignmentY} property. + * + * @return The current value of the property. + * + * @see #setAlignmentY + * @see #alignmentX + */ + public float getAlignmentY() + { + return alignmentY; + } + + /** + * Get the current value of the {@link #autoscrolls} property. + * + * @return The current value of the property + */ + public boolean getAutoscrolls() + { + return autoscrolls; + } + + /** + * Set the value of the {@link #border} property. + * + * @param newBorder The new value of the property + * + * @see #getBorder + */ + public void setBorder(Border newBorder) + { + Border oldBorder = border; + border = newBorder; + firePropertyChange("border", oldBorder, newBorder); + } + + /** + * Get the value of the {@link #border} property. + * + * @return The property's current value + * + * @see #setBorder + */ + public Border getBorder() + { + return border; + } + + /** + * Get the component's current bounding box. If a rectangle is provided, + * use this as the return value (adjusting its fields in place); + * otherwise (of null is provided) return a new {@link + * Rectangle}. + * + * @param rv Optional return value to use + * + * @return A rectangle bounding the component + */ + public Rectangle getBounds(Rectangle rv) + { + if (rv == null) + return new Rectangle(getX(), getY(), getWidth(), getHeight()); + else + { + rv.setBounds(getX(), getY(), getWidth(), getHeight()); + return rv; + } + } + + /** + * Prepares a graphics context for painting this object. If {@link + * #debugGraphicsOptions} is not equal to {@link + * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object + * wrapping the parameter. Otherwise configure the parameter with this + * component's foreground color and font. + * + * @param g The graphics context to wrap or configure + * + * @return A graphics context to paint this object with + * + * @see #debugGraphicsOptions + * @see #paint + */ + protected Graphics getComponentGraphics(Graphics g) + { + g.setFont (this.getFont()); + g.setColor (this.getForeground()); + return g; + } + + /** + * Get the value of the {@link #debugGraphicsOptions} property. + * + * @return The current value of the property. + * + * @see #setDebugGraphicsOptions + * @see #debugGraphicsOptions + */ + public int getDebugGraphicsOptions() + { + return 0; + } + + /** + * Get the component's insets, which are calculated from + * the {@link #border} property. If the border is null, + * calls {@link Container#getInsets}. + * + * @return The component's current insets + */ + public Insets getInsets() + { + if (border == null) + return super.getInsets(); + return getBorder().getBorderInsets(this); + } + + /** + * Get the component's insets, which are calculated from the {@link + * #border} property. If the border is null, calls {@link + * Container#getInsets}. The passed-in {@link Insets} value will be + * used as the return value, if possible. + * + * @param insets Return value object to reuse, if possible + * + * @return The component's current insets + */ + public Insets getInsets(Insets insets) + { + Insets t = getInsets(); + + if (insets == null) + return t; + + insets.left = t.left; + insets.right = t.right; + insets.top = t.top; + insets.bottom = t.bottom; + return insets; + } + + /** + * Get the component's location. The passed-in {@link Point} value + * will be used as the return value, if possible. + * + * @param rv Return value object to reuse, if possible + * + * @return The component's current location + */ + public Point getLocation(Point rv) + { + if (rv == null) + return new Point(getX(), getY()); + + rv.setLocation(getX(), getY()); + return rv; + } + + /** + * Get the component's maximum size. If the {@link #maximumSize} property + * has been explicitly set, it is returned. If the {@link #maximumSize} + * property has not been set but the {@link ui} property has been, the + * result of {@link ComponentUI#getMaximumSize} is returned. If neither + * property has been set, the result of {@link Container#getMaximumSize} + * is returned. + * + * @return The maximum size of the component + * + * @see #maximumSize + * @see #setMaximumSize + */ + public Dimension getMaximumSize() + { + if (maximumSize != null) + return maximumSize; + + if (ui != null) + { + Dimension s = ui.getMaximumSize(this); + if (s != null) + return s; + } + + Dimension p = super.getMaximumSize(); + return p; + } + + /** + * Get the component's minimum size. If the {@link #minimumSize} property + * has been explicitly set, it is returned. If the {@link #minimumSize} + * property has not been set but the {@link ui} property has been, the + * result of {@link ComponentUI#getMinimumSize} is returned. If neither + * property has been set, the result of {@link Container#getMinimumSize} + * is returned. + * + * @return The minimum size of the component + * + * @see #minimumSize + * @see #setMinimumSize + */ + public Dimension getMinimumSize() + { + if (minimumSize != null) + return minimumSize; + + if (ui != null) + { + Dimension s = ui.getMinimumSize(this); + if (s != null) + return s; + } + + Dimension p = super.getMinimumSize(); + return p; + } + + /** + * Get the component's preferred size. If the {@link #preferredSize} + * property has been explicitly set, it is returned. If the {@link + * #preferredSize} property has not been set but the {@link ui} property + * has been, the result of {@link ComponentUI#getPreferredSize} is + * returned. If neither property has been set, the result of {@link + * Container#getPreferredSize} is returned. + * + * @return The preferred size of the component + * + * @see #preferredSize + * @see #setPreferredSize + */ + public Dimension getPreferredSize() + { + Dimension prefSize = null; + if (preferredSize != null) + prefSize = preferredSize; + + else if (ui != null) + { + Dimension s = ui.getPreferredSize(this); + if (s != null) + prefSize = s; + } + + if (prefSize == null) + prefSize = super.getPreferredSize(); + // make sure that prefSize is not smaller than minSize + if (minimumSize != null && prefSize != null + && (minimumSize.width > prefSize.width + || minimumSize.height > prefSize.height)) + prefSize = new Dimension(Math.max(minimumSize.width, prefSize.width), + Math.max(minimumSize.height, prefSize.height)); + return prefSize; + } + + /** + * Checks if a maximum size was explicitely set on the component. + * + * @return true if a maximum size was set, + * false otherwise + * + * @since 1.3 + */ + public boolean isMaximumSizeSet() + { + return maximumSize != null; + } + + /** + * Checks if a minimum size was explicitely set on the component. + * + * @return true if a minimum size was set, + * false otherwise + * + * @since 1.3 + */ + public boolean isMinimumSizeSet() + { + return minimumSize != null; + } + + /** + * Checks if a preferred size was explicitely set on the component. + * + * @return true if a preferred size was set, + * false otherwise + * + * @since 1.3 + */ + public boolean isPreferredSizeSet() + { + return preferredSize != null; + } + + /** + * Return the value of the {@link #nextFocusableComponent} property. + * + * @return The current value of the property, or null + * if none has been set. + * + * @deprecated See {@link java.awt.FocusTraversalPolicy} + */ + public Component getNextFocusableComponent() + { + return null; + } + + /** + * Return the set of {@link KeyStroke} objects which are registered + * to initiate actions on this component. + * + * @return An array of the registered keystrokes + */ + public KeyStroke[] getRegisteredKeyStrokes() + { + return null; + } + + /** + * Returns the first ancestor of this component which is a {@link JRootPane}. + * Equivalent to calling SwingUtilities.getRootPane(this);. + * + * @return An ancestral JRootPane, or null if none exists. + */ + public JRootPane getRootPane() + { + JRootPane p = SwingUtilities.getRootPane(this); + return p; + } + + /** + * Get the component's size. The passed-in {@link Dimension} value + * will be used as the return value, if possible. + * + * @param rv Return value object to reuse, if possible + * + * @return The component's current size + */ + public Dimension getSize(Dimension rv) + { + if (rv == null) + return new Dimension(getWidth(), getHeight()); + else + { + rv.setSize(getWidth(), getHeight()); + return rv; + } + } + + /** + * Return the {@link #toolTip} property of this component, creating it and + * setting it if it is currently null. This method can be + * overridden in subclasses which wish to control the exact form of + * tooltip created. + * + * @return The current toolTip + */ + public JToolTip createToolTip() + { + JToolTip toolTip = new JToolTip(); + toolTip.setComponent(this); + toolTip.setTipText(toolTipText); + + return toolTip; + } + + /** + * Return the location at which the {@link #toolTip} property should be + * displayed, when triggered by a particular mouse event. + * + * @param event The event the tooltip is being presented in response to + * + * @return The point at which to display a tooltip, or null + * if swing is to choose a default location. + */ + public Point getToolTipLocation(MouseEvent event) + { + return null; + } + + /** + * Set the value of the {@link #toolTipText} property. + * + * @param text The new property value + * + * @see #getToolTipText + */ + public void setToolTipText(String text) + { + if (text == null) + { + ToolTipManager.sharedInstance().unregisterComponent(this); + toolTipText = null; + return; + } + + // XXX: The tip text doesn't get updated unless you set it to null + // and then to something not-null. This is consistent with the behaviour + // of Sun's ToolTipManager. + + String oldText = toolTipText; + toolTipText = text; + + if (oldText == null) + ToolTipManager.sharedInstance().registerComponent(this); + } + + /** + * Get the value of the {@link #toolTipText} property. + * + * @return The current property value + * + * @see #setToolTipText + */ + public String getToolTipText() + { + return toolTipText; + } + + /** + * Get the value of the {@link #toolTipText} property, in response to a + * particular mouse event. + * + * @param event The mouse event which triggered the tooltip + * + * @return The current property value + * + * @see #setToolTipText + */ + public String getToolTipText(MouseEvent event) + { + return getToolTipText(); + } + + /** + * Return the top level ancestral container (usually a {@link + * java.awt.Window} or {@link java.awt.Applet}) which this component is + * contained within, or null if no ancestors exist. + * + * @return The top level container, if it exists + */ + public Container getTopLevelAncestor() + { + Container c = getParent(); + for (Container peek = c; peek != null; peek = peek.getParent()) + c = peek; + return c; + } + + /** + * Compute the component's visible rectangle, which is defined + * recursively as either the component's bounds, if it has no parent, or + * the intersection of the component's bounds with the visible rectangle + * of its parent. + * + * @param rect The return value slot to place the visible rectangle in + */ + public void computeVisibleRect(Rectangle rect) + { + Component c = getParent(); + if (c != null && c instanceof JComponent) + { + ((JComponent) c).computeVisibleRect(rect); + rect.translate(-getX(), -getY()); + Rectangle2D.intersect(rect, + new Rectangle(0, 0, getWidth(), getHeight()), + rect); + } + else + rect.setRect(0, 0, getWidth(), getHeight()); + } + + /** + * Return the component's visible rectangle in a new {@link Rectangle}, + * rather than via a return slot. + * + * @return The component's visible rectangle + * + * @see #computeVisibleRect(Rectangle) + */ + public Rectangle getVisibleRect() + { + Rectangle r = new Rectangle(); + computeVisibleRect(r); + return r; + } + + /** + *

Requests that this component receive input focus, giving window + * focus to the top level ancestor of this component. Only works on + * displayable, focusable, visible components.

+ * + *

This method should not be called by clients; it is intended for + * focus implementations. Use {@link Component#requestFocus} instead.

+ * + * @see {@link Component#requestFocus} + */ + public void grabFocus() + { + } + + /** + * Get the value of the {@link #doubleBuffered} property. + * + * @return The property's current value + */ + public boolean isDoubleBuffered() + { + return doubleBuffered; + } + + /** + * Return true if the provided component has no native peer; + * in other words, if it is a "lightweight component". + * + * @param c The component to test for lightweight-ness + * + * @return Whether or not the component is lightweight + */ + public static boolean isLightweightComponent(Component c) + { + return c.getPeer() instanceof LightweightPeer; + } + + /** + * Return true if you wish this component to manage its own + * focus. In particular: if you want this component to be sent + * TAB and SHIFT+TAB key events, and to not + * have its children considered as focus transfer targets. If + * true, focus traversal around this component changes to + * CTRL+TAB and CTRL+SHIFT+TAB. + * + * @return true if you want this component to manage its own + * focus, otherwise (by default) false + * + * @deprecated 1.4 Use {@link Component.setFocusTraversalKeys(int,Set)} and + * {@link Container.setFocusCycleRoot(boolean)} instead + */ + public boolean isManagingFocus() + { + return false; + } + + /** + * Return the current value of the {@link opaque} property. + * + * @return The current property value + */ + public boolean isOpaque() + { + return opaque; + } + + /** + * Return true if the component can guarantee that none of its + * children will overlap in Z-order. This is a hint to the painting system. + * The default is to return true, but some components such as + * {@link JLayeredPane} should override this to return false. + * + * @return Whether the component tiles its children + */ + public boolean isOptimizedDrawingEnabled() + { + return true; + } + + /** + * Return true if this component is currently painting a tile. + * + * @return Whether the component is painting a tile + */ + public boolean isPaintingTile() + { + return false; + } + + /** + * Get the value of the {@link #requestFocusEnabled} property. + * + * @return The current value of the property + */ + public boolean isRequestFocusEnabled() + { + return requestFocusEnabled; + } + + /** + * Return true if this component is a validation root; this + * will cause calls to {@link #invalidate} in this component's children + * to be "captured" at this component, and not propagate to its parents. + * For most components this should return false, but some + * components such as {@link JViewPort} will want to return + * true. + * + * @return Whether this component is a validation root + */ + public boolean isValidateRoot() + { + return false; + } + + /** + *

Paint the component. This is a delicate process, and should only be + * called from the repaint thread, under control of the {@link + * RepaintManager}. Client code should usually call {@link #repaint} to + * trigger painting.

+ * + *

This method will acquire a double buffer from the {@link + * RepaintManager} if the component's {@link #doubleBuffered} property is + * true and the paint call is the + * first recursive paint call inside swing.

+ * + *

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 paint.

+ * + *

The body of the paint call involves calling {@link + * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in + * order. If you want to customize painting behavior, you should override + * one of these methods rather than paint.

+ * + *

For more details on the painting sequence, see + * this article.

+ * + * @param g The graphics context to paint with + * + * @see #paintImmediately + */ + public void paint(Graphics g) + { + Graphics g2 = g; + Image doubleBuffer = null; + RepaintManager rm = RepaintManager.currentManager(this); + + if (isDoubleBuffered() + && (rm.isDoubleBufferingEnabled()) + && (! Thread.holdsLock(paintLock))) + { + doubleBuffer = rm.getOffscreenBuffer(this, getWidth(), getHeight()); + } + + synchronized (paintLock) + { + if (doubleBuffer != null) + { + g2 = doubleBuffer.getGraphics(); + g2.setClip(g.getClipBounds()); + } + + g2 = getComponentGraphics(g2); + paintComponent(g2); + paintBorder(g2); + paintChildren(g2); + + if (doubleBuffer != null) + g.drawImage(doubleBuffer, 0, 0, (ImageObserver) null); + } + } + + /** + * Paint the component's border. This usually means calling {@link + * Border#paintBorder} on the {@link #border} property, if it is + * non-null. You may override this if you wish to customize + * border painting behavior. The border is painted after the component's + * body, but before the component's children. + * + * @param g The graphics context with which to paint the border + * + * @see #paint + * @see #paintChildren + * @see #paintComponent + */ + protected void paintBorder(Graphics g) + { + if (getBorder() != null) + getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight()); + } + + /** + * Paint the component's children. This usually means calling {@link + * Container#paint}, which recursively calls {@link #paint} on any of the + * component's children, with appropriate changes to coordinate space and + * clipping region. You may override this if you wish to customize + * children painting behavior. The children are painted after the + * component's body and border. + * + * @param g The graphics context with which to paint the children + * + * @see #paint + * @see #paintBorder + * @see #paintComponent + */ + protected void paintChildren(Graphics g) + { + super.paint(g); + } + + /** + * Paint the component's body. This usually means calling {@link + * ComponentUI#update} on the {@link #ui} property of the component, if + * it is non-null. You may override this if you wish to + * customize the component's body-painting behavior. The component's body + * is painted first, before the border and children. + * + * @param g The graphics context with which to paint the body + * + * @see #paint + * @see #paintBorder + * @see #paintChildren + */ + protected void paintComponent(Graphics g) + { + if (ui != null) + { + Graphics g2 = g; + if (!(g instanceof Graphics2D)) + g2 = g.create(); + ui.update(getComponentGraphics(g2), this); + if (!(g instanceof Graphics2D)) + g2.dispose(); + } + } + + /** + * A variant of {@link #paintImmediately(Rectangle)} which takes + * integer parameters. + * + * @param x The left x coordinate of the dirty region + * @param y The top y coordinate of the dirty region + * @param w The width of the dirty region + * @param h The height of the dirty region + */ + public void paintImmediately(int x, int y, int w, int h) + { + paintImmediately(new Rectangle(x, y, w, h)); + } + + /** + * Transform the provided dirty rectangle for this component into the + * appropriate ancestral {@link JRootPane} and call {@link #paint} on + * that root pane. This method is called from the {@link RepaintManager} + * and should always be called within the painting thread. + * + * @param r The dirty rectangle to paint + */ + public void paintImmediately(Rectangle r) + { + Component root = SwingUtilities.getRoot(this); + if (root == null || ! root.isShowing()) + return; + Graphics g = root.getGraphics(); + if (g == null) + return; + + Rectangle clip = SwingUtilities.convertRectangle(this, r, root); + g.setClip(clip); + root.paint(g); + g.dispose(); + } + + /** + * Return a string representation for this component, for use in + * debugging. + * + * @return A string describing this component. + */ + protected String paramString() + { + StringBuffer sb = new StringBuffer(); + sb.append(super.paramString()); + sb.append(",alignmentX=").append(getAlignmentX()); + sb.append(",alignmentY=").append(getAlignmentY()); + sb.append(",border="); + if (getBorder() != null) + sb.append(getBorder()); + sb.append(",maximumSize="); + if (getMaximumSize() != null) + sb.append(getMaximumSize()); + sb.append(",minimumSize="); + if (getMinimumSize() != null) + sb.append(getMinimumSize()); + sb.append(",preferredSize="); + if (getPreferredSize() != null) + sb.append(getPreferredSize()); + return sb.toString(); + } + + /** + * A variant of {@link + * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which + * provides null for the command name. + */ + public void registerKeyboardAction(ActionListener act, + KeyStroke stroke, + int cond) + { + registerKeyboardAction(act, null, stroke, cond); + } + + /* + * There is some charmingly undocumented behavior sun seems to be using + * to simulate the old register/unregister keyboard binding API. It's not + * clear to me why this matters, but we shall endeavour to follow suit. + * + * Two main thing seem to be happening when you do registerKeyboardAction(): + * + * - no actionMap() entry gets created, just an entry in inputMap() + * + * - the inputMap() entry is a proxy class which invokes the the + * binding's actionListener as a target, and which clobbers the command + * name sent in the ActionEvent, providing the binding command name + * instead. + * + * This much you can work out just by asking the input and action maps + * what they contain after making bindings, and watching the event which + * gets delivered to the recipient. Beyond that, it seems to be a + * sun-private solution so I will only immitate it as much as it matters + * to external observers. + */ + private static class ActionListenerProxy + extends AbstractAction + { + ActionListener target; + String bindingCommandName; + + public ActionListenerProxy(ActionListener li, + String cmd) + { + target = li; + bindingCommandName = cmd; + } + + public void actionPerformed(ActionEvent e) + { + ActionEvent derivedEvent = new ActionEvent(e.getSource(), + e.getID(), + bindingCommandName, + e.getModifiers()); + target.actionPerformed(derivedEvent); + } + } + + + /** + * An obsolete method to register a keyboard action on this component. + * You should use getInputMap and getActionMap + * to fetch mapping tables from keystrokes to commands, and commands to + * actions, respectively, and modify those mappings directly. + * + * @param anAction The action to be registered + * @param aCommand The command to deliver in the delivered {@link + * java.awt.ActionEvent} + * @param aKeyStroke The keystroke to register on + * @param aCondition One of the values {@link #UNDEFINED_CONDITION}, + * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or + * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must + * be met for the action to be fired + * + * @see #unregisterKeyboardAction + * @see #getConditionForKeystroke + * @see #resetKeyboardActiond + */ + public void registerKeyboardAction(ActionListener act, + String cmd, + KeyStroke stroke, + int cond) + { + getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd)); + } + + public final void setInputMap(int condition, InputMap map) + { + enableEvents(AWTEvent.KEY_EVENT_MASK); + switch (condition) + { + case WHEN_FOCUSED: + inputMap_whenFocused = map; + break; + + case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: + inputMap_whenAncestorOfFocused = map; + break; + + case WHEN_IN_FOCUSED_WINDOW: + inputMap_whenInFocusedWindow = map; + break; + + case UNDEFINED_CONDITION: + default: + throw new IllegalArgumentException(); + } + } + + public final InputMap getInputMap(int condition) + { + enableEvents(AWTEvent.KEY_EVENT_MASK); + switch (condition) + { + case WHEN_FOCUSED: + if (inputMap_whenFocused == null) + inputMap_whenFocused = new InputMap(); + return inputMap_whenFocused; + + case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: + if (inputMap_whenAncestorOfFocused == null) + inputMap_whenAncestorOfFocused = new InputMap(); + return inputMap_whenAncestorOfFocused; + + case WHEN_IN_FOCUSED_WINDOW: + if (inputMap_whenInFocusedWindow == null) + inputMap_whenInFocusedWindow = new InputMap(); + return inputMap_whenInFocusedWindow; + + case UNDEFINED_CONDITION: + default: + return null; + } + } + + public final InputMap getInputMap() + { + return getInputMap(WHEN_FOCUSED); + } + + public final ActionMap getActionMap() + { + if (actionMap == null) + actionMap = new ActionMap(); + return actionMap; + } + + public final void setActionMap(ActionMap map) + { + actionMap = map; + } + + /** + * Return the condition that determines whether a registered action + * occurs in response to the specified keystroke. + * + * @param aKeyStroke The keystroke to return the condition of + * + * @return One of the values {@link #UNDEFINED_CONDITION}, {@link + * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link + * #WHEN_IN_FOCUSED_WINDOW} + * + * @deprecated As of 1.3 KeyStrokes can be registered with multiple + * simultaneous conditions. + * + * @see #registerKeyboardAction + * @see #unregisterKeyboardAction + * @see #resetKeyboardActiond + */ + public int getConditionForKeyStroke(KeyStroke ks) + { + if (inputMap_whenFocused != null + && inputMap_whenFocused.get(ks) != null) + return WHEN_FOCUSED; + else if (inputMap_whenAncestorOfFocused != null + && inputMap_whenAncestorOfFocused.get(ks) != null) + return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT; + else if (inputMap_whenInFocusedWindow != null + && inputMap_whenInFocusedWindow.get(ks) != null) + return WHEN_IN_FOCUSED_WINDOW; + else + return UNDEFINED_CONDITION; + } + + /** + * Get the ActionListener (typically an {@link Action} object) which is + * associated with a particular keystroke. + * + * @param aKeyStroke The keystroke to retrieve the action of + * + * @return The action associated with the specified keystroke + * + * @deprecated Use {@link #getActionMap()} + */ + public ActionListener getActionForKeyStroke(KeyStroke ks) + { + Object cmd = getInputMap().get(ks); + if (cmd != null) + { + if (cmd instanceof ActionListenerProxy) + return (ActionListenerProxy) cmd; + else if (cmd instanceof String) + return getActionMap().get(cmd); + } + return null; + } + + /** + * A hook for subclasses which want to customize event processing. + */ + protected void processComponentKeyEvent(KeyEvent e) + { + } + + /** + * Override the default key dispatch system from Component to hook into + * the swing {@link InputMap} / {@link ActionMap} system. + * + * See + * this report for more details, it's somewhat complex. + */ + protected void processKeyEvent(KeyEvent e) + { + // let the AWT event processing send KeyEvents to registered listeners + super.processKeyEvent(e); + processComponentKeyEvent(e); + + // FIXME: this needs to be elaborated significantly, to do all the + // focus / ancestor / window searching for the various binding modes. + if (! e.isConsumed() && + processKeyBinding(KeyStroke.getKeyStrokeForEvent(e), + e, WHEN_FOCUSED, e.getID() == KeyEvent.KEY_PRESSED)) + e.consume(); + } + + protected boolean processKeyBinding(KeyStroke ks, + KeyEvent e, + int condition, + boolean pressed) + { + if (isEnabled()) + { + Action act = null; + InputMap map = getInputMap(condition); + if (map != null) + { + Object cmd = map.get(ks); + if (cmd != null) + { + if (cmd instanceof ActionListenerProxy) + act = (Action) cmd; + else + act = (Action) getActionMap().get(cmd); + } + } + if (act != null && act.isEnabled()) + return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers()); + } + return false; + } + + /** + * Remove a keyboard action registry. + * + * @param stroke The keystroke to unregister + * + * @see #registerKeyboardAction + * @see #getConditionForKeystroke + * @see #resetKeyboardActiond + */ + public void unregisterKeyboardAction(KeyStroke aKeyStroke) + { + // FIXME: Must be implemented. + } + + + /** + * Reset all keyboard action registries. + * + * @see #registerKeyboardAction + * @see #unregisterKeyboardAction + * @see #getConditionForKeystroke + */ + public void resetKeyboardActions() + { + if (inputMap_whenFocused != null) + inputMap_whenFocused.clear(); + if (inputMap_whenAncestorOfFocused != null) + inputMap_whenAncestorOfFocused.clear(); + if (inputMap_whenInFocusedWindow != null) + inputMap_whenInFocusedWindow.clear(); + if (actionMap != null) + actionMap.clear(); + } + + /** + * Mark the described region of this component as dirty in the current + * {@link RepaintManager}. This will queue an asynchronous repaint using + * the system painting thread in the near future. + * + * @param tm ignored + * @param x coordinate of the region to mark as dirty + * @param y coordinate of the region to mark as dirty + * @param width dimension of the region to mark as dirty + * @param height dimension of the region to mark as dirty + */ + public void repaint(long tm, int x, int y, int width, int height) + { + Rectangle dirty = new Rectangle(x, y, width, height); + Rectangle vis = getVisibleRect(); + dirty = dirty.intersection(vis); + RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y, + dirty.width, + dirty.height); + } + + /** + * Mark the described region of this component as dirty in the current + * {@link RepaintManager}. This will queue an asynchronous repaint using + * the system painting thread in the near future. + * + * @param r The rectangle to mark as dirty + */ + public void repaint(Rectangle r) + { + repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(), + (int) r.getHeight()); + } + + /** + * Request focus on the default component of this component's {@link + * FocusTraversalPolicy}. + * + * @return The result of {@link #requestFocus} + * + * @deprecated Use {@link #requestFocus()} on the default component provided + * from the {@link FocusTraversalPolicy} instead. + */ + public boolean requestDefaultFocus() + { + return false; + } + + /** + * Queue a an invalidation and revalidation of this component, using + * {@link RepaintManager#addInvalidComponent}. + */ + public void revalidate() + { + invalidate(); + RepaintManager.currentManager(this).addInvalidComponent(this); + } + + /** + * Calls scrollRectToVisible on the component's parent. + * Components which can service this call should override. + * + * @param r The rectangle to make visible + */ + public void scrollRectToVisible(Rectangle r) + { + Component p = getParent(); + if (p instanceof JComponent) + ((JComponent) p).scrollRectToVisible(r); + } + + /** + * Set the value of the {@link #alignmentX} property. + * + * @param a The new value of the property + */ + public void setAlignmentX(float a) + { + alignmentX = a; + } + + /** + * Set the value of the {@link #alignmentY} property. + * + * @param a The new value of the property + */ + public void setAlignmentY(float a) + { + alignmentY = a; + } + + /** + * Set the value of the {@link #autoscrolls} property. + * + * @param a The new value of the property + */ + public void setAutoscrolls(boolean a) + { + autoscrolls = a; + } + + /** + * Set the value of the {@link #debugGraphicsOptions} property. + * + * @param debugOptions The new value of the property + */ + public void setDebugGraphicsOptions(int debugOptions) + { + debugGraphicsOptions = debugOptions; + } + + /** + * Set the value of the {@link #doubleBuffered} property. + * + * @param db The new value of the property + */ + public void setDoubleBuffered(boolean db) + { + doubleBuffered = db; + } + + /** + * Set the value of the {@link #enabled} property. + * + * @param enable The new value of the property + */ + public void setEnabled(boolean enable) + { + boolean oldEnabled = isEnabled(); + super.setEnabled(enable); + firePropertyChange("enabled", oldEnabled, enable); + } + + /** + * Set the value of the {@link #font} property. + * + * @param f The new value of the property + */ + public void setFont(Font f) + { + super.setFont(f); + } + + /** + * Set the value of the {@link #background} property. + * + * @param bg The new value of the property + */ + public void setBackground(Color bg) + { + super.setBackground(bg); + } + + /** + * Set the value of the {@link #foreground} property. + * + * @param fg The new value of the property + */ + public void setForeground(Color fg) + { + super.setForeground(fg); + } + + /** + * Set the value of the {@link #maximumSize} property. + * + * @param max The new value of the property + */ + public void setMaximumSize(Dimension max) + { + Dimension oldMaximumSize = maximumSize; + maximumSize = max; + firePropertyChange("maximumSize", oldMaximumSize, maximumSize); + } + + /** + * Set the value of the {@link #minimumSize} property. + * + * @param min The new value of the property + */ + public void setMinimumSize(Dimension min) + { + Dimension oldMinimumSize = minimumSize; + minimumSize = min; + firePropertyChange("minimumSize", oldMinimumSize, minimumSize); + } + + /** + * Set the value of the {@link #preferredSize} property. + * + * @param pref The new value of the property + */ + public void setPreferredSize(Dimension pref) + { + Dimension oldPreferredSize = preferredSize; + preferredSize = pref; + firePropertyChange("preferredSize", oldPreferredSize, preferredSize); + } + + /** + * Set the specified component to be the next component in the + * focus cycle, overriding the {@link FocusTraversalPolicy} for + * this component. + * + * @param aComponent The component to set as the next focusable + * + * @deprecated Use FocusTraversalPolicy instead + */ + public void setNextFocusableComponent(Component aComponent) + { + } + + /** + * Set the value of the {@link #requestFocusEnabled} property. + * + * @param e The new value of the property + */ + public void setRequestFocusEnabled(boolean e) + { + requestFocusEnabled = e; + } + + /** + * Get the value of the {@link #transferHandler} property. + * + * @return The current value of the property + * + * @see ComponentUI#setTransferHandler + */ + + public TransferHandler getTransferHandler() + { + return transferHandler; + } + + /** + * Set the value of the {@link #transferHandler} property. + * + * @param newHandler The new value of the property + * + * @see ComponentUI#getTransferHandler + */ + + public void setTransferHandler(TransferHandler newHandler) + { + if (transferHandler == newHandler) + return; + + TransferHandler oldHandler = transferHandler; + transferHandler = newHandler; + firePropertyChange("transferHandler", oldHandler, newHandler); + } + + /** + * Set the value of the {@link #opaque} property. + * + * @param isOpaque The new value of the property + * + * @see ComponentUI#update + */ + public void setOpaque(boolean isOpaque) + { + boolean oldOpaque = opaque; + opaque = isOpaque; + firePropertyChange("opaque", oldOpaque, opaque); + } + + /** + * Set the value of the visible property. + * + * @param v The new value of the property + */ + public void setVisible(boolean v) + { + super.setVisible(v); + } + + /** + * Call {@link paint}. + * + * @param g The graphics context to paint into + */ + public void update(Graphics g) + { + paint(g); + } + + /** + * Get the value of the UIClassID property. This property should be a key + * in the {@link UIDefaults} table managed by {@link UIManager}, the + * value of which is the name of a class to load for the component's + * {@link ui} property. + * + * @return A "symbolic" name which will map to a class to use for the + * component's UI, such as "ComponentUI" + * + * @see #setUI + * @see #updateUI + */ + public String getUIClassID() + { + return "ComponentUI"; + } + + /** + * Install a new UI delegate as the component's {@link ui} property. In + * the process, this will call {@link ComponentUI.uninstallUI} on any + * existing value for the {@link ui} property, and {@link + * ComponentUI.installUI} on the new UI delegate. + * + * @param newUI The new UI delegate to install + * + * @see #updateUI + * @see #getUIClassID + */ + protected void setUI(ComponentUI newUI) + { + if (ui != null) + ui.uninstallUI(this); + + ComponentUI oldUI = ui; + ui = newUI; + + if (ui != null) + ui.installUI(this); + + firePropertyChange("UI", oldUI, newUI); + + } + + /** + * This method should be overridden in subclasses. In JComponent, the + * method does nothing. In subclasses, it should a UI delegate + * (corresponding to the symbolic name returned from {@link + * getUIClassID}) from the {@link UIManager}, and calls {@link setUI} + * with the new delegate. + */ + public void updateUI() + { + System.out.println("update UI not overwritten in class: " + this); + } + + public static Locale getDefaultLocale() + { + return defaultLocale; + } + + public static void setDefaultLocale(Locale l) + { + defaultLocale = l; + } + + /** + * Returns the currently set input verifier for this component. + * + * @return the input verifier, or null if none + */ + public InputVerifier getInputVerifier() + { + return inputVerifier; + } + + /** + * Sets the input verifier to use by this component. + * + * @param verifier the input verifier, or null + */ + public void setInputVerifier(InputVerifier verifier) + { + InputVerifier oldVerifier = inputVerifier; + inputVerifier = verifier; + firePropertyChange("inputVerifier", oldVerifier, verifier); + } + + /** + * @since 1.3 + */ + public boolean getVerifyInputWhenFocusTarget() + { + return verifyInputWhenFocusTarget; + } + + /** + * @since 1.3 + */ + public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget) + { + if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget) + return; + + this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget; + firePropertyChange("verifyInputWhenFocusTarget", + ! verifyInputWhenFocusTarget, + verifyInputWhenFocusTarget); + } + + /** + * Requests that this component gets the input focus if the + * requestFocusEnabled property is set to true. + * This also means that this component's top-level window becomes + * the focused window, if that is not already the case. + * + * The preconditions that have to be met to become a focus owner is that + * the component must be displayable, visible and focusable. + * + * Note that this signals only a request for becoming focused. There are + * situations in which it is not possible to get the focus. So developers + * should not assume that the component has the focus until it receives + * a {@link java.awt.event.FocusEvent} with a value of + * {@link java.awt.event.FocusEvent.FOCUS_GAINED}. + * + * @see {@link Component#requestFocus()} + */ + public void requestFocus() + { + if (isRequestFocusEnabled()) + super.requestFocus(); + } + + /** + * This method is overridden to make it public so that it can be used + * by look and feel implementations. + * + * You should not use this method directly. Instead you are strongly + * encouraged to call {@link #requestFocus} or {@link #requestFocusInWindow} + * instead. + * + * @param temporary if the focus change is temporary + * + * @return false if the focus change request will definitly + * fail, true if it will likely succeed + * + * @see {@link Component#requestFocus(boolean)} + * + * @since 1.4 + */ + public boolean requestFocus(boolean temporary) + { + return super.requestFocus(temporary); + } + + /** + * Requests that this component gets the input focus if the top level + * window that contains this component has the focus and the + * requestFocusEnabled property is set to true. + * + * The preconditions that have to be met to become a focus owner is that + * the component must be displayable, visible and focusable. + * + * Note that this signals only a request for becoming focused. There are + * situations in which it is not possible to get the focus. So developers + * should not assume that the component has the focus until it receives + * a {@link java.awt.event.FocusEvent} with a value of + * {@link java.awt.event.FocusEvent.FOCUS_GAINED}. + * + * @return false if the focus change request will definitly + * fail, true if it will likely succeed + * + * @see {@link Component#requestFocusInWindow()} + */ + public boolean requestFocusInWindow() + { + if (isRequestFocusEnabled()) + return super.requestFocusInWindow(); + else + return false; + } + + /** + * This method is overridden to make it public so that it can be used + * by look and feel implementations. + * + * You should not use this method directly. Instead you are strongly + * encouraged to call {@link #requestFocus} or {@link #requestFocusInWindow} + * instead. + * + * @param temporary if the focus change is temporary + * + * @return false if the focus change request will definitly + * fail, true if it will likely succeed + * + * @see {@link Component#requestFocus(boolean)} + * + * @since 1.4 + */ + public boolean requestFocusInWindow(boolean temporary) + { + return super.requestFocusInWindow(temporary); + } + + /** + * Receives notification if this component is added to a parent component. + * + * Notification is sent to all registered AncestorListeners about the + * new parent. + * + * This method sets up ActionListeners for all registered KeyStrokes of + * this component in the chain of parent components. + * + * A PropertyChange event is fired to indicate that the ancestor property + * has changed. + * + * This method is used internally and should not be used in applications. + */ + public void addNotify() + { + 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); + } + + // fire property change event for 'ancestor' + firePropertyChange("ancestor", null, parent); + } + + /** + * Receives notification that this component no longer has a parent. + * + * This method sends an AncestorEvent to all registered AncestorListeners, + * notifying them that the parent is gone. + * + * The keybord actions of this component are removed from the parent and + * its ancestors. + * + * A PropertyChangeEvent is fired to indicate that the 'ancestor' property + * has changed. + * + * This method is called before the component is actually removed from + * its parent, so the parent is still visible through {@link #getParent}. + */ + public void removeNotify() + { + 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); + } + + // fire property change event for 'ancestor' + firePropertyChange("ancestor", parent, null); + } + + /** + * Returns true if the coordinates (x, y) lie within + * the bounds of this component and false otherwise. + * x and y are relative to the coordinate space of the component. + * + * @param x the X coordinate of the point to check + * @param y the Y coordinate of the point to check + * + * @return true if the specified point lies within the bounds + * of this component, false otherwise + */ + public boolean contains(int x, int y) + { + if (ui == null) + return super.contains(x, y); + else + return ui.contains(this, x, y); + } + + /** + * Disables this component. + * + * @deprecated replaced by {@link #setEnabled(boolean)} + */ + public void disable() + { + super.disable(); + } + + /** + * Enables this component. + * + * @deprecated replaced by {@link #setEnabled(boolean)} + */ + public void enable() + { + super.enable(); + } + + /** + * Returns the Graphics context for this component. This can be used + * to draw on a component. + * + * @return the Graphics context for this component + */ + public Graphics getGraphics() + { + return super.getGraphics(); + } + + /** + * Returns the X coordinate of the upper left corner of this component. + * Prefer this method over {@link #getBounds} or {@link #getLocation} + * because it does not cause any heap allocation. + * + * @return the X coordinate of the upper left corner of the component + */ + public int getX() + { + return super.getX(); + } + + /** + * Returns the Y coordinate of the upper left corner of this component. + * Prefer this method over {@link #getBounds} or {@link #getLocation} + * because it does not cause any heap allocation. + * + * @return the Y coordinate of the upper left corner of the component + */ + public int getY() + { + return super.getY(); + } + + /** + * Returns the height of this component. Prefer this method over + * {@link #getBounds} or {@link #getSize} because it does not cause + * any heap allocation. + * + * @return the height of the component + */ + public int getHeight() + { + return super.getHeight(); + } + + /** + * Returns the width of this component. Prefer this method over + * {@link #getBounds} or {@link #getSize} because it does not cause + * any heap allocation. + * + * @return the width of the component + */ + public int getWidth() + { + return super.getWidth(); + } + + /** + * Return all PropertyChangeListener objects registered. + * + * @return The set of PropertyChangeListener objects + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + if (changeSupport == null) + return new PropertyChangeListener[0]; + else + return changeSupport.getPropertyChangeListeners(); + } + + /** + * Prints this component to the given Graphics context. A call to this + * method results in calls to the methods {@link #printComponent}, + * {@link #printBorder} and {@link printChildren} in this order. + * + * Double buffering is temporarily turned off so the painting goes directly + * to the supplied Graphics context. + * + * @param g the Graphics context to print onto + */ + public void print(Graphics g) + { + boolean doubleBufferState = isDoubleBuffered(); + setDoubleBuffered(false); + printComponent(g); + printBorder(g); + printChildren(g); + setDoubleBuffered(doubleBufferState); + } + + /** + * Prints this component to the given Graphics context. This invokes + * {@link #print}. + * + * @param g the Graphics context to print onto + */ + public void printAll(Graphics g) + { + print(g); + } + + /** + * Prints this component to the specified Graphics context. The default + * behaviour is to invoke {@link #paintComponent}. Override this + * if you want special behaviour for printing. + * + * @param g the Graphics context to print onto + * + * @since 1.3 + */ + public void printComponent(Graphics g) + { + paintComponent(g); + } + + /** + * Print this component's children to the specified Graphics context. + * The default behaviour is to invoke {@link #paintChildren}. Override this + * if you want special behaviour for printing. + * + * @param g the Graphics context to print onto + * + * @since 1.3 + */ + public void printChildren(Graphics g) + { + paintChildren(g); + } + + /** + * Print this component's border to the specified Graphics context. + * The default behaviour is to invoke {@link #paintBorder}. Override this + * if you want special behaviour for printing. + * + * @param g the Graphics context to print onto + * + * @since 1.3 + */ + public void printBorder(Graphics g) + { + paintBorder(g); + } + + /** + * Processes mouse motion event, like dragging and moving. + * + * @param ev the MouseEvent describing the mouse motion + */ + protected void processMouseMotionEvent(MouseEvent ev) + { + super.processMouseMotionEvent(ev); + } + + /** + * Moves and resizes the component. + * + * @param x the new horizontal location + * @param y the new vertial location + * @param w the new width + * @param h the new height + */ + public void reshape(int x, int y, int w, int h) + { + super.reshape(x, y, w, h); + } +} diff --git a/libjava/classpath/javax/swing/JDesktopPane.java b/libjava/classpath/javax/swing/JDesktopPane.java new file mode 100644 index 0000000..ff51211 --- /dev/null +++ b/libjava/classpath/javax/swing/JDesktopPane.java @@ -0,0 +1,331 @@ +/* JDesktopPane.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.beans.PropertyVetoException; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.plaf.DesktopPaneUI; + +/** + * JDesktopPane is a container (usually for JInternalFrames) that simulates a + * desktop. Typically, the user will create JInternalFrames and place thme in + * a JDesktopPane. The user can then interact with JInternalFrames like they + * usually would with JFrames. The actions (minimize, maximize, close, etc) + * are done by using a DesktopManager that is associated with the + * JDesktopPane. + */ +public class JDesktopPane extends JLayeredPane implements Accessible +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = 766333777224038726L; + + /** + * This specifies that when dragged, a JInternalFrame should be completely + * visible. + * + * @specnote final since 1.5.0. + */ + public static final int LIVE_DRAG_MODE = 0; + + /** + * This specifies that when dragged, a JInternalFrame should only be visible + * as an outline. + * + * @specnote final since 1.5.0. + */ + public static final int OUTLINE_DRAG_MODE = 1; + + /** The selected frame in the JDesktopPane. */ + private transient JInternalFrame selectedFrame; + + /** The JDesktopManager to use for acting on JInternalFrames. */ + transient DesktopManager desktopManager; + + /** The drag mode used by the JDesktopPane. */ + private transient int dragMode = LIVE_DRAG_MODE; + + /** + * AccessibleJDesktopPane + */ + protected class AccessibleJDesktopPane extends AccessibleJComponent + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = 6079388927946077570L; + + /** + * Constructor AccessibleJDesktopPane + */ + protected AccessibleJDesktopPane() + { + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.DESKTOP_PANE; + } + } + + /** + * Creates a new JDesktopPane object. + */ + public JDesktopPane() + { + setLayout(null); + updateUI(); + } + + /** + * This method returns the UI used with the JDesktopPane. + * + * @return The UI used with the JDesktopPane. + */ + public DesktopPaneUI getUI() + { + return (DesktopPaneUI) ui; + } + + /** + * This method sets the UI used with the JDesktopPane. + * + * @param ui The UI to use with the JDesktopPane. + */ + public void setUI(DesktopPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method sets the drag mode to use with the JDesktopPane. + * + * @param mode The drag mode to use. + * + * @throws IllegalArgumentException If the drag mode given is not + * LIVE_DRAG_MODE or OUTLINE_DRAG_MODE. + */ + public void setDragMode(int mode) + { + if ((mode != LIVE_DRAG_MODE) && (mode != OUTLINE_DRAG_MODE)) + throw new IllegalArgumentException("Drag mode not valid."); + + // FIXME: Unsupported mode. + if (mode == OUTLINE_DRAG_MODE) + // throw new IllegalArgumentException("Outline drag modes are + // unsupported."); + mode = LIVE_DRAG_MODE; + + dragMode = mode; + } + + /** + * This method returns the drag mode used with the JDesktopPane. + * + * @return The drag mode used with the JDesktopPane. + */ + public int getDragMode() + { + return dragMode; + } + + /** + * This method returns the DesktopManager used with the JDesktopPane. + * + * @return The DesktopManager to use with the JDesktopPane. + */ + public DesktopManager getDesktopManager() + { + return desktopManager; + } + + /** + * This method sets the DesktopManager to use with the JDesktopPane. + * + * @param manager The DesktopManager to use with the JDesktopPane. + */ + public void setDesktopManager(DesktopManager manager) + { + desktopManager = manager; + } + + /** + * This method restores the UI used with the JDesktopPane to the default. + */ + public void updateUI() + { + setUI((DesktopPaneUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns a String identifier that allows the UIManager to know + * which class will act as JDesktopPane's UI. + * + * @return A String identifier for the UI class to use. + */ + public String getUIClassID() + { + return "DesktopPaneUI"; + } + + /** + * This method returns all JInternalFrames that are in the JDesktopPane. + * + * @return All JInternalFrames that are in the JDesktopPane. + */ + public JInternalFrame[] getAllFrames() + { + return getFramesFromComponents(getComponents()); + } + + /** + * This method returns the currently selected frame in the JDesktopPane. + * + * @return The currently selected frame in the JDesktopPane. + */ + public JInternalFrame getSelectedFrame() + { + return selectedFrame; + } + + /** + * This method sets the selected frame in the JDesktopPane. + * + * @param frame The selected frame in the JDesktopPane. + */ + public void setSelectedFrame(JInternalFrame frame) + { + if (selectedFrame != null) + { + try + { + selectedFrame.setSelected(false); + } + catch (PropertyVetoException e) + { + } + } + selectedFrame = null; + + try + { + if (frame != null) + frame.setSelected(true); + + selectedFrame = frame; + } + catch (PropertyVetoException e) + { + } + } + + /** + * This method returns all the JInternalFrames in the given layer. + * + * @param layer The layer to grab frames in. + * + * @return All JInternalFrames in the given layer. + */ + public JInternalFrame[] getAllFramesInLayer(int layer) + { + return getFramesFromComponents(getComponentsInLayer(layer)); + } + + /** + * This method always returns true to indicate that it is not transparent. + * + * @return true. + */ + public boolean isOpaque() + { + return true; + } + + /** + * This method returns a String that describes the JDesktopPane. + * + * @return A String that describes the JDesktopPane. + */ + protected String paramString() + { + return "JDesktopPane"; + } + + /** + * This method returns all the JInternalFrames in the given Component array. + * + * @param components An array to search for JInternalFrames in. + * + * @return An array of JInternalFrames found in the Component array. + */ + private static JInternalFrame[] getFramesFromComponents(Component[] components) + { + int count = 0; + + for (int i = 0; i < components.length; i++) + if (components[i] instanceof JInternalFrame) + count++; + + JInternalFrame[] value = new JInternalFrame[count]; + for (int i = 0, j = 0; i < components.length && j != count; i++) + if (components[i] instanceof JInternalFrame) + value[j++] = (JInternalFrame) components[i]; + return value; + } + + /** + * getAccessibleContext + * + * @return AccessibleContext + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJDesktopPane(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JDialog.java b/libjava/classpath/javax/swing/JDialog.java new file mode 100644 index 0000000..83865f8 --- /dev/null +++ b/libjava/classpath/javax/swing/JDialog.java @@ -0,0 +1,588 @@ +/* JDialog.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.IllegalComponentStateException; +import java.awt.LayoutManager; +import java.awt.event.WindowEvent; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; + +/** + * Unlike JComponent derivatives, JDialog inherits from java.awt.Dialog. But + * also lets a look-and-feel component to its work. + * + * @author Ronald Veldema (rveldema_AT_cs.vu.nl) + */ +public class JDialog extends Dialog implements Accessible, WindowConstants, + RootPaneContainer +{ + private static final long serialVersionUID = -864070866424508218L; + + /** DOCUMENT ME! */ + protected AccessibleContext accessibleContext; + + /** The single RootPane in the Dialog. */ + protected JRootPane rootPane; + + /** + * Whether checking is enabled on the RootPane. + * + * @specnote Should be false to comply with J2SE 5.0 + */ + protected boolean rootPaneCheckingEnabled = false; + + /** The default action taken when closed. */ + private int close_action = HIDE_ON_CLOSE; + + /** 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. + */ + public JDialog() + { + this(SwingUtilities.getOwnerFrame(), "", false, null); + } + + /** + * Creates a new non-modal JDialog with no title + * using the given owner. + * + * @param owner The owner of the JDialog. + */ + public JDialog(Dialog owner) + { + this(owner, "", false, null); + } + + /** + * Creates a new JDialog with no title using the + * given modal setting and owner. + * + * @param owner The owner of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Dialog owner, boolean modal) + { + this(owner, "", modal, null); + } + + /** + * Creates a new non-modal JDialog using the + * given title and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + */ + public JDialog(Dialog owner, String title) + { + this(owner, title, false, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Dialog owner, String title, boolean modal) + { + this(owner, title, modal, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, owner and graphics configuration. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + * @param gc The Graphics Configuration to use. + */ + public JDialog(Dialog owner, String title, boolean modal, + GraphicsConfiguration gc) + { + super(owner, title, modal, gc); + dialogInit(); + } + + /** + * Creates a new non-modal JDialog with no title + * using the given owner. + * + * @param owner The owner of the JDialog. + */ + public JDialog(Frame owner) + { + this(owner, "", false, null); + } + + /** + * Creates a new JDialog with no title using the + * given modal setting and owner. + * + * @param owner The owner of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Frame owner, boolean modal) + { + this(owner, "", modal, null); + } + + /** + * Creates a new non-modal JDialog using the + * given title and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + */ + public JDialog(Frame owner, String title) + { + this(owner, title, false, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Frame owner, String title, boolean modal) + { + this(owner, title, modal, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, owner and graphics configuration. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + * @param gc The Graphics Configuration to use. + */ + public JDialog(Frame owner, String title, boolean modal, + GraphicsConfiguration gc) + { + super((owner == null) ? SwingUtilities.getOwnerFrame() : owner, + title, modal, gc); + dialogInit(); + } + + /** + * This method is called to initialize the + * JDialog. It sets the layout used, the locale, + * and creates the RootPane. + */ + protected void dialogInit() + { + // FIXME: Do a check on GraphicsEnvironment.isHeadless() + setLocale(JComponent.getDefaultLocale()); + getRootPane(); // Will do set/create. + invalidate(); + // Now that initStageDone is true, adds and layouts apply to contentPane, + // not top-level. + initStageDone = true; + } + + /** + * This method returns whether JDialogs will have their + * window decorations provided by the Look and Feel. + * + * @return Whether the window decorations are Look and Feel provided. + */ + public static boolean isDefaultLookAndFeelDecorated() + { + return decorated; + } + + /** + * This method sets whether JDialogs will have their + * window decorations provided by the Look and Feel. + * + * @param defaultLookAndFeelDecorated Whether the window + * decorations are Look and Feel provided. + */ + public static void setDefaultLookAndFeelDecorated(boolean defaultLookAndFeelDecorated) + { + decorated = defaultLookAndFeelDecorated; + } + + /** + * This method returns the preferred size of + * the JDialog. + * + * @return The preferred size. + */ + public Dimension getPreferredSize() + { + Dimension d = super.getPreferredSize(); + return d; + } + + /** + * This method returns the JMenuBar used + * in this JDialog. + * + * @return The JMenuBar in the JDialog. + */ + public JMenuBar getJMenuBar() + { + return getRootPane().getJMenuBar(); + } + + /** + * This method sets the JMenuBar used + * in this JDialog. + * + * @param menubar The JMenuBar to use. + */ + public void setJMenuBar(JMenuBar menubar) + { + getRootPane().setJMenuBar(menubar); + } + + /** + * This method sets the LayoutManager used in the JDialog. + * This method will throw an Error if rootPaneChecking is + * enabled. + * + * @param manager The LayoutManager to use. + */ + public void setLayout(LayoutManager manager) + { + // 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); + } + else + super.setLayout(manager); + } + + /** + * This method sets the JLayeredPane used in the JDialog. + * If the given JLayeredPane is null, then this method + * will throw an Error. + * + * @param layeredPane The JLayeredPane to use. + */ + public void setLayeredPane(JLayeredPane layeredPane) + { + if (layeredPane == null) + throw new IllegalComponentStateException("layeredPane cannot be null."); + getRootPane().setLayeredPane(layeredPane); + } + + /** + * This method returns the JLayeredPane used with this JDialog. + * + * @return The JLayeredPane used with this JDialog. + */ + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } + + /** + * This method returns the JRootPane used with this JDialog. + * + * @return The JRootPane used with this JDialog. + */ + public JRootPane getRootPane() + { + if (rootPane == null) + setRootPane(createRootPane()); + return rootPane; + } + + /** + * This method sets the JRootPane used with this JDialog. + * + * @param root The JRootPane to use. + */ + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); + + rootPane = root; + rootPane.show(); + add(rootPane); + } + + /** + * This method creates a new JRootPane. + * + * @return A new JRootPane. + */ + protected JRootPane createRootPane() + { + return new JRootPane(); + } + + /** + * This method returns the ContentPane + * in the JRootPane. + * + * @return The ContentPane in the JRootPane. + */ + public Container getContentPane() + { + return getRootPane().getContentPane(); + } + + /** + * This method sets the ContentPane to use with this + * JDialog. If the ContentPane given is null, this method + * will throw an exception. + * + * @param contentPane The ContentPane to use with the JDialog. + */ + public void setContentPane(Container contentPane) + { + if (contentPane == null) + throw new IllegalComponentStateException("contentPane cannot be null."); + getRootPane().setContentPane(contentPane); + } + + /** + * This method returns the GlassPane for this JDialog. + * + * @return The GlassPane for this JDialog. + */ + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + /** + * This method sets the GlassPane for this JDialog. + * + * @param glassPane The GlassPane for this JDialog. + */ + public void setGlassPane(Component glassPane) + { + getRootPane().setGlassPane(glassPane); + } + + /** + * This method is called when a component is added to the + * the JDialog. Calling this method with rootPaneCheckingEnabled + * will cause an Error to be thrown. + * + * @param comp The component to add. + * @param constraints The constraints. + * @param index The position of the component. + */ + protected void addImpl(Component comp, Object constraints, int index) + { + // If 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); + else + { + if (isRootPaneCheckingEnabled()) + throw new Error("Do not add directly to JDialog." + + " Use getContentPane().add instead."); + getContentPane().add(comp, constraints, index); + } + } + + /** + * This method removes a component from the JDialog. + * + * @param comp The component to remove. + */ + public void remove(Component comp) + { + // If we're removing the root pane, use super.remove. Otherwise + // pass it on to the content pane instead. + if (comp == rootPane) + super.remove(rootPane); + else + getContentPane().remove(comp); + } + + /** + * This method returns whether rootPane checking is enabled. + * + * @return Whether rootPane checking is enabled. + */ + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + /** + * This method sets whether rootPane checking is enabled. + * + * @param enabled Whether rootPane checking is enabled. + */ + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + /** + * This method simply calls paint and returns. + * + * @param g The Graphics object to paint with. + */ + public void update(Graphics g) + { + paint(g); + } + + + /** + * This method handles window events. This allows the JDialog + * to honour its default close operation. + * + * @param e The WindowEvent. + */ + protected void processWindowEvent(WindowEvent e) + { + // System.out.println("PROCESS_WIN_EV-1: " + e); + super.processWindowEvent(e); + // System.out.println("PROCESS_WIN_EV-2: " + e); + switch (e.getID()) + { + case WindowEvent.WINDOW_CLOSING: + { + switch (getDefaultCloseOperation()) + { + case DISPOSE_ON_CLOSE: + { + dispose(); + break; + } + case HIDE_ON_CLOSE: + { + setVisible(false); + break; + } + case DO_NOTHING_ON_CLOSE: + break; + } + break; + } + case WindowEvent.WINDOW_CLOSED: + case WindowEvent.WINDOW_OPENED: + case WindowEvent.WINDOW_ICONIFIED: + case WindowEvent.WINDOW_DEICONIFIED: + case WindowEvent.WINDOW_ACTIVATED: + case WindowEvent.WINDOW_DEACTIVATED: + break; + } + } + + /** + * This method sets the action to take + * when the JDialog is closed. + * + * @param operation The action to take. + */ + public void setDefaultCloseOperation(int operation) + { + /* Reference implementation allows invalid operations + to be specified. If so, getDefaultCloseOperation + must return the invalid code, and the behaviour + defaults to DO_NOTHING_ON_CLOSE. processWindowEvent + above handles this */ + close_action = operation; + } + + /** + * This method returns the action taken when + * the JDialog is closed. + * + * @return The action to take. + */ + public int getDefaultCloseOperation() + { + return close_action; + } + + /** + * This method returns a String describing the JDialog. + * + * @return A String describing the JDialog. + */ + protected String paramString() + { + return "JDialog"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/JEditorPane.java b/libjava/classpath/javax/swing/JEditorPane.java new file mode 100644 index 0000000..63c79ff --- /dev/null +++ b/libjava/classpath/javax/swing/JEditorPane.java @@ -0,0 +1,333 @@ +/* JEditorPane.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Dimension; +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.accessibility.AccessibleContext; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.EditorKit; +import javax.swing.text.JTextComponent; + + +public class JEditorPane extends JTextComponent +{ + private static final long serialVersionUID = 3140472492599046285L; + + private URL page; + private EditorKit editorKit; + + boolean focus_root; + + public JEditorPane() + { + setEditorKit(createDefaultEditorKit()); + } + + public JEditorPane(String url) throws IOException + { + this(new URL(url)); + } + + public JEditorPane(String type, String text) + { + setEditorKit(createEditorKitForContentType(type)); + setText(text); + } + + public JEditorPane(URL url) throws IOException + { + this(); + setPage(url); + } + + protected EditorKit createDefaultEditorKit() + { + return new DefaultEditorKit(); + } + + public static EditorKit createEditorKitForContentType(String type) + { + return new DefaultEditorKit(); + } + + /** + * Sends a given HyperlinkEvent to all registered listeners. + * + * @param event the event to send + */ + public void fireHyperlinkUpdate(HyperlinkEvent event) + { + HyperlinkListener[] listeners = getHyperlinkListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].hyperlinkUpdate(event); + } + + public AccessibleContext getAccessibleContext() + { + return null; + } + + public final String getContentType() + { + return getEditorKit().getContentType(); + } + + /** + * Returns the EditorKit. If there is no EditorKit set this method + * calls createDefaultEditorKit() and setEditorKit() first. + */ + public EditorKit getEditorKit() + { + if (editorKit == null) + setEditorKit(createDefaultEditorKit()); + return editorKit; + } + + public static String getEditorKitClassNameForContentType(String type) + { + return "text/plain"; + } + + public EditorKit getEditorKitForContentType(String type) + { + return editorKit; + } + + /** + * Returns the preferred size for the JEditorPane. + */ + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + public boolean getScrollableTracksViewportHeight() + { + return false; + } + + public boolean getScrollableTracksViewportWidth() + { + return false; + } + + public URL getPage() + { + return page; + } + + protected InputStream getStream(URL page) + throws IOException + { + return page.openStream(); + } + + public String getText() + { + return super.getText(); + } + + public String getUIClassID() + { + return "EditorPaneUI"; + } + + public boolean isFocusCycleRoot() + { + return focus_root; + } + + protected String paramString() + { + return "JEditorPane"; + } + + /** + * This method initializes from a stream. + */ + public void read(InputStream in, Object desc) + throws IOException + { + } + + /** + * Establishes the default bindings of type to classname. + */ + public static void registerEditorKitForContentType(String type, + String classname) + { + } + + /** + * Establishes the default bindings of type to classname. + */ + public static void registerEditorKitForContentType(String type, + String classname, + ClassLoader loader) + { + } + + /** + * Replaces the currently selected content with new content represented + * by the given string. + */ + public void replaceSelection(String content) + { + } + + /** + * Scrolls the view to the given reference location (that is, the value + * returned by the UL.getRef method for the URL being displayed). + */ + public void scrollToReference(String reference) + { + } + + public final void setContentType(String type) + { + if (editorKit != null + && editorKit.getContentType().equals(type)) + return; + + EditorKit kit = getEditorKitForContentType(type); + + if (kit != null) + setEditorKit(kit); + } + + public void setEditorKit(EditorKit newValue) + { + if (editorKit == newValue) + return; + + if (editorKit != null) + editorKit.deinstall(this); + + EditorKit oldValue = editorKit; + editorKit = newValue; + + if (editorKit != null) + { + editorKit.install(this); + setDocument(editorKit.createDefaultDocument()); + } + + firePropertyChange("editorKit", oldValue, newValue); + invalidate(); + repaint(); + } + + public void setEditorKitForContentType(String type, EditorKit k) + { + // FIXME: editorKitCache.put(type, kit); + } + + /** + * Sets the current URL being displayed. + */ + public void setPage(String url) throws IOException + { + setPage(new URL(url)); + } + + /** + * Sets the current URL being displayed. + */ + public void setPage(URL page) throws IOException + { + if (page == null) + throw new IOException("invalid url"); + + try + { + this.page = page; + getEditorKit().read(page.openStream(), getDocument(), 0); + } + catch (BadLocationException e) + { + // Ignored. '0' is always a valid offset. + } + } + + public void setText(String t) + { + super.setText(t); + } + + /** + * Add a HyperlinkListener object to this editor pane. + * + * @param listener the listener to add + */ + public void addHyperlinkListener(HyperlinkListener listener) + { + listenerList.add(HyperlinkListener.class, listener); + } + + /** + * Removes a HyperlinkListener object to this editor pane. + * + * @param listener the listener to remove + */ + public void removeHyperlinkListener(HyperlinkListener listener) + { + listenerList.remove(HyperlinkListener.class, listener); + } + + /** + * Returns all added HyperlinkListener objects. + * + * @return array of listeners + * + * @since 1.4 + */ + public HyperlinkListener[] getHyperlinkListeners() + { + return (HyperlinkListener[]) getListeners(HyperlinkListener.class); + } +} diff --git a/libjava/classpath/javax/swing/JFileChooser.java b/libjava/classpath/javax/swing/JFileChooser.java new file mode 100644 index 0000000..17292fa --- /dev/null +++ b/libjava/classpath/javax/swing/JFileChooser.java @@ -0,0 +1,1190 @@ +/* JFileChooser.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Frame; +import java.awt.HeadlessException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.JDialog; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.FileChooserUI; + + +/** + * DOCUMENT ME! + */ +public class JFileChooser extends JComponent implements Accessible +{ + private static final long serialVersionUID = 3162921138695327837L; + + /** DOCUMENT ME! */ + public static final int OPEN_DIALOG = 0; + + /** DOCUMENT ME! */ + public static final int SAVE_DIALOG = 1; + + /** DOCUMENT ME! */ + public static final int CUSTOM_DIALOG = 2; + + /** DOCUMENT ME! */ + public static final int CANCEL_OPTION = 1; + + /** DOCUMENT ME! */ + public static final int APPROVE_OPTION = 0; + + /** DOCUMENT ME! */ + public static final int ERROR_OPTION = -1; + + /** DOCUMENT ME! */ + public static final int FILES_ONLY = 0; + + /** DOCUMENT ME! */ + public static final int DIRECTORIES_ONLY = 1; + + /** DOCUMENT ME! */ + public static final int FILES_AND_DIRECTORIES = 2; + + /** DOCUMENT ME! */ + public static final String CANCEL_SELECTION = "CancelSelection"; + + /** DOCUMENT ME! */ + public static final String APPROVE_SELECTION = "ApproveSelection"; + + /** DOCUMENT ME! */ + public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = + "ApproveButtonTextChangedProperty"; + + /** DOCUMENT ME! */ + public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = + "ApproveButtonToolTipTextChangedProperty"; + + /** DOCUMENT ME! */ + public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = + "ApproveButtonMnemonicChangedProperty"; + + /** DOCUMENT ME! */ + public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = + "ControlButtonsAreShownChangedProperty"; + + /** DOCUMENT ME! */ + public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged"; + + /** DOCUMENT ME! */ + public static final String SELECTED_FILE_CHANGED_PROPERTY = + "SelectedFileChangedProperty"; + + /** DOCUMENT ME! */ + public static final String SELECTED_FILES_CHANGED_PROPERTY = + "SelectedFilesChangedProperty"; + + /** DOCUMENT ME! */ + public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = + "MultiSelectionEnabledChangedProperty"; + + /** DOCUMENT ME! */ + public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = + "FileSystemViewChanged"; + + /** DOCUMENT ME! */ + public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged"; + + /** DOCUMENT ME! */ + public static final String FILE_HIDING_CHANGED_PROPERTY = + "FileHidingChanged"; + + /** DOCUMENT ME! */ + public static final String FILE_FILTER_CHANGED_PROPERTY = + "fileFilterChanged"; + + /** DOCUMENT ME! */ + public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = + "fileSelectionChanged"; + + /** DOCUMENT ME! */ + public static final String ACCESSORY_CHANGED_PROPERTY = + "AccessoryChangedProperty"; + + /** DOCUMENT ME! */ + public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = + "acceptAllFileFilterUsedChanged"; + + /** DOCUMENT ME! */ + public static final String DIALOG_TITLE_CHANGED_PROPERTY = + "DialogTitleChangedProperty"; + + /** DOCUMENT ME! */ + public static final String DIALOG_TYPE_CHANGED_PROPERTY = + "DialogTypeChangedProperty"; + + /** DOCUMENT ME! */ + public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = + "ChoosableFileFilterChangedProperty"; + + /** DOCUMENT ME! */ + protected AccessibleContext accessibleContext; + + /** DOCUMENT ME! */ + private FileSystemView fsv; + + /** DOCUMENT ME! */ + private JComponent accessory; + + /** DOCUMENT ME! */ + private int approveButtonMnemonic = 0; + + /** DOCUMENT ME! */ + private String approveButtonText; + + /** DOCUMENT ME! */ + private String approveButtonToolTipText; + + /** DOCUMENT ME! */ + private ArrayList choosableFilters = new ArrayList(); + + /** DOCUMENT ME! */ + private boolean isAcceptAll = true; + + /** DOCUMENT ME! */ + private String dialogTitle; + + /** DOCUMENT ME! */ + private int dialogType = OPEN_DIALOG; + + /** DOCUMENT ME! */ + private int retval = ERROR_OPTION; + + /** DOCUMENT ME! */ + private boolean multiSelection = false; + + /** DOCUMENT ME! */ + private boolean fileHiding = true; + + /** DOCUMENT ME! */ + private int fileSelectionMode = FILES_AND_DIRECTORIES; + + /** DOCUMENT ME! */ + private FileView fv = null; + + /** DOCUMENT ME! */ + private boolean controlButtonsShown = true; + + /** DOCUMENT ME! */ + private File currentDir = null; + + /** DOCUMENT ME! */ + private FileFilter currentFilter = null; + + /** DOCUMENT ME! */ + private File[] selectedFiles; + + /** DOCUMENT ME! */ + private File selectedFile; + + /** + * Creates a new JFileChooser object. + */ + public JFileChooser() + { + setup(null); + setCurrentDirectory(null); + } + + /** + * Creates a new JFileChooser object. + * + * @param currentDirectoryPath DOCUMENT ME! + */ + public JFileChooser(String currentDirectoryPath) + { + setup(null); + setCurrentDirectory(fsv.createFileObject(currentDirectoryPath)); + } + + /** + * Creates a new JFileChooser object with the specified directory and + * FileSystemView. + * + * @param currentDirectoryPath the directory that should initially be + * shown the filechooser + * @param fsv the FileSystemView object to use + */ + public JFileChooser(String currentDirectoryPath, FileSystemView fsv) + { + setup(fsv); + setCurrentDirectory(fsv.createFileObject(currentDirectoryPath)); + } + + /** + * Creates a new JFileChooser object. + * + * @param currentDirectory DOCUMENT ME! + */ + public JFileChooser(File currentDirectory) + { + setup(null); + setCurrentDirectory(currentDirectory); + } + + /** + * Creates a new JFileChooser object. + * + * @param fsv DOCUMENT ME! + */ + public JFileChooser(FileSystemView fsv) + { + setup(fsv); + setCurrentDirectory(null); + } + + /** + * Creates a new JFileChooser object. + * + * @param currentDirectory DOCUMENT ME! + * @param fsv DOCUMENT ME! + */ + public JFileChooser(File currentDirectory, FileSystemView fsv) + { + setup(fsv); + setCurrentDirectory(currentDirectory); + } + + /** + * DOCUMENT ME! + * + * @param view DOCUMENT ME! + */ + protected void setup(FileSystemView view) + { + if (view == null) + view = FileSystemView.getFileSystemView(); + setFileSystemView(view); + updateUI(); + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setDragEnabled(boolean b) + { + // FIXME: Implement + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean getDragEnabled() + { + // FIXME: Implement + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getSelectedFile() + { + return selectedFile; + } + + /** + * DOCUMENT ME! + * + * @param file DOCUMENT ME! + */ + public void setSelectedFile(File file) + { + if (selectedFile != file) + { + File old = selectedFile; + selectedFile = file; + firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, old, selectedFile); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File[] getSelectedFiles() + { + if (selectedFiles != null) + return selectedFiles; + if (selectedFile != null) + return new File[] { selectedFile }; + return null; + } + + /** + * DOCUMENT ME! + * + * @param selectedFiles DOCUMENT ME! + */ + public void setSelectedFiles(File[] selectedFiles) + { + if (this.selectedFiles != selectedFiles) + { + File[] old = this.selectedFiles; + this.selectedFiles = selectedFiles; + firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, old, selectedFiles); + } + + if (selectedFiles != null) + setSelectedFile(selectedFiles[0]); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getCurrentDirectory() + { + return currentDir; + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + */ + public void setCurrentDirectory(File dir) + { + if (currentDir != dir || dir == null) + { + if (dir == null) + dir = fsv.getDefaultDirectory(); + + File old = currentDir; + currentDir = dir; + firePropertyChange(DIRECTORY_CHANGED_PROPERTY, old, currentDir); + } + } + + /** + * DOCUMENT ME! + */ + public void changeToParentDirectory() + { + setCurrentDirectory(fsv.getParentDirectory(currentDir)); + } + + /** + * DOCUMENT ME! + */ + public void rescanCurrentDirectory() + { + getUI().rescanCurrentDirectory(this); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + */ + public void ensureFileIsVisible(File f) + { + getUI().ensureFileIsVisible(this, f); + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws HeadlessException DOCUMENT ME! + */ + public int showOpenDialog(Component parent) throws HeadlessException + { + JDialog d = createDialog(parent); + + // FIXME: Remove when we get ancestor property + d.setTitle("Open"); + setDialogType(OPEN_DIALOG); + + retval = ERROR_OPTION; + + d.pack(); + d.show(); + return retval; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws HeadlessException DOCUMENT ME! + */ + public int showSaveDialog(Component parent) throws HeadlessException + { + JDialog d = createDialog(parent); + setDialogType(SAVE_DIALOG); + + retval = ERROR_OPTION; + + d.pack(); + d.show(); + return retval; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * @param approveButtonText DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws HeadlessException DOCUMENT ME! + */ + public int showDialog(Component parent, String approveButtonText) + throws HeadlessException + { + JDialog d = createDialog(parent); + setApproveButtonText(approveButtonText); + setDialogType(CUSTOM_DIALOG); + + retval = ERROR_OPTION; + + d.pack(); + d.show(); + return retval; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws HeadlessException DOCUMENT ME! + */ + protected JDialog createDialog(Component parent) throws HeadlessException + { + Frame toUse = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent); + if (toUse == null) + toUse = SwingUtilities.getOwnerFrame(); + + JDialog dialog = new JDialog(toUse); + setSelectedFile(null); + dialog.getContentPane().add(this); + dialog.setModal(true); + dialog.invalidate(); + dialog.repaint(); + + return dialog; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean getControlButtonsAreShown() + { + return controlButtonsShown; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setControlButtonsAreShown(boolean b) + { + if (controlButtonsShown != b) + { + controlButtonsShown = b; + firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, + ! controlButtonsShown, controlButtonsShown); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getDialogType() + { + return dialogType; + } + + /** + * DOCUMENT ME! + * + * @param dialogType DOCUMENT ME! + */ + public void setDialogType(int dialogType) + { + if (dialogType != OPEN_DIALOG && dialogType != SAVE_DIALOG + && dialogType != CUSTOM_DIALOG) + throw new IllegalArgumentException("Choose allowable dialogType."); + + if (this.dialogType != dialogType) + { + int old = this.dialogType; + this.dialogType = dialogType; + firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, old, this.dialogType); + } + } + + /** + * DOCUMENT ME! + * + * @param dialogTitle DOCUMENT ME! + */ + public void setDialogTitle(String dialogTitle) + { + if (this.dialogTitle != dialogTitle) + { + String old = this.dialogTitle; + this.dialogTitle = dialogTitle; + firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, old, this.dialogTitle); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDialogTitle() + { + return dialogTitle; + } + + /** + * DOCUMENT ME! + * + * @param toolTipText DOCUMENT ME! + */ + public void setApproveButtonToolTipText(String toolTipText) + { + if (approveButtonToolTipText != toolTipText) + { + String oldText = approveButtonToolTipText; + approveButtonToolTipText = toolTipText; + firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, + oldText, approveButtonToolTipText); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonToolTipText() + { + return approveButtonToolTipText; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getApproveButtonMnemonic() + { + return approveButtonMnemonic; + } + + /** + * DOCUMENT ME! + * + * @param mnemonic DOCUMENT ME! + */ + public void setApproveButtonMnemonic(int mnemonic) + { + if (approveButtonMnemonic != mnemonic) + { + int oldMnemonic = approveButtonMnemonic; + approveButtonMnemonic = mnemonic; + firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, + oldMnemonic, approveButtonMnemonic); + } + } + + /** + * DOCUMENT ME! + * + * @param mnemonic DOCUMENT ME! + */ + public void setApproveButtonMnemonic(char mnemonic) + { + setApproveButtonMnemonic((int) Character.toUpperCase(mnemonic)); + } + + /** + * DOCUMENT ME! + * + * @param approveButtonText DOCUMENT ME! + */ + public void setApproveButtonText(String approveButtonText) + { + if (this.approveButtonText != approveButtonText) + { + String oldText = this.approveButtonText; + this.approveButtonText = approveButtonText; + firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldText, + this.approveButtonText); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonText() + { + return approveButtonText; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileFilter[] getChoosableFileFilters() + { + return (FileFilter[]) choosableFilters.toArray(new FileFilter[0]); + } + + /** + * DOCUMENT ME! + * + * @param filter DOCUMENT ME! + */ + public void addChoosableFileFilter(FileFilter filter) + { + FileFilter[] old = getChoosableFileFilters(); + choosableFilters.add(filter); + FileFilter[] newFilters = getChoosableFileFilters(); + firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old, newFilters); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean removeChoosableFileFilter(FileFilter f) + { + FileFilter[] old = getChoosableFileFilters(); + if (! choosableFilters.remove(f)) + return false; + FileFilter[] newFilters = getChoosableFileFilters(); + firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old, newFilters); + return true; + } + + /** + * DOCUMENT ME! + */ + public void resetChoosableFileFilters() + { + choosableFilters.clear(); + choosableFilters.add(getUI().getAcceptAllFileFilter(this)); + setFileFilter((FileFilter) choosableFilters.get(0)); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileFilter getAcceptAllFileFilter() + { + return getUI().getAcceptAllFileFilter(this); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isAcceptAllFileFilterUsed() + { + return isAcceptAll; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setAcceptAllFileFilterUsed(boolean b) + { + if (isAcceptAll != b) + { + isAcceptAll = b; + firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, + ! isAcceptAll, isAcceptAll); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JComponent getAccessory() + { + return accessory; + } + + /** + * DOCUMENT ME! + * + * @param newAccessory DOCUMENT ME! + */ + public void setAccessory(JComponent newAccessory) + { + if (accessory != newAccessory) + { + JComponent old = accessory; + accessory = newAccessory; + firePropertyChange(ACCESSORY_CHANGED_PROPERTY, old, accessory); + } + } + + /** + * DOCUMENT ME! + * + * @param mode DOCUMENT ME! + */ + public void setFileSelectionMode(int mode) + { + if (mode != FILES_ONLY && mode != DIRECTORIES_ONLY + && mode != FILES_AND_DIRECTORIES) + throw new IllegalArgumentException("Choose a correct file selection mode."); + if (fileSelectionMode != mode) + { + int old = fileSelectionMode; + fileSelectionMode = mode; + firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, old, + fileSelectionMode); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getFileSelectionMode() + { + return fileSelectionMode; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isFileSelectionEnabled() + { + return (fileSelectionMode == FILES_ONLY + || fileSelectionMode == FILES_AND_DIRECTORIES); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isDirectorySelectionEnabled() + { + return (fileSelectionMode == DIRECTORIES_ONLY + || fileSelectionMode == FILES_AND_DIRECTORIES); + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setMultiSelectionEnabled(boolean b) + { + if (multiSelection != b) + { + multiSelection = b; + firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, + ! multiSelection, multiSelection); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isMultiSelectionEnabled() + { + return multiSelection; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isFileHidingEnabled() + { + return fileHiding; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setFileHidingEnabled(boolean b) + { + if (fileHiding != b) + { + fileHiding = b; + firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, ! fileHiding, + fileHiding); + } + } + + /** + * DOCUMENT ME! + * + * @param filter DOCUMENT ME! + */ + public void setFileFilter(FileFilter filter) + { + if (currentFilter != filter) + { + FileFilter old = currentFilter; + currentFilter = filter; + firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, old, currentFilter); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileFilter getFileFilter() + { + return currentFilter; + } + + /** + * DOCUMENT ME! + * + * @param fileView DOCUMENT ME! + */ + public void setFileView(FileView fileView) + { + if (fv != fileView) + { + FileView old = fv; + fv = fileView; + firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, old, fv); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileView getFileView() + { + return fv; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private FileView getInternalFileView() + { + if (fv == null) + return getUI().getFileView(this); + return fv; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getName(File f) + { + return getInternalFileView().getName(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDescription(File f) + { + return getInternalFileView().getDescription(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getTypeDescription(File f) + { + return getInternalFileView().getTypeDescription(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getIcon(File f) + { + return getInternalFileView().getIcon(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isTraversable(File f) + { + return getFileSystemView().isTraversable(f).booleanValue(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean accept(File f) + { + if (f == null) + return false; + return getFileFilter().accept(f); + } + + /** + * DOCUMENT ME! + * + * @param fsv DOCUMENT ME! + */ + public void setFileSystemView(FileSystemView fsv) + { + if (this.fsv != fsv) + { + FileSystemView old = this.fsv; + this.fsv = fsv; + firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, old, this.fsv); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileSystemView getFileSystemView() + { + return fsv; + } + + /** + * DOCUMENT ME! + */ + public void approveSelection() + { + retval = APPROVE_OPTION; + fireActionPerformed(APPROVE_SELECTION); + } + + /** + * DOCUMENT ME! + */ + public void cancelSelection() + { + retval = CANCEL_OPTION; + fireActionPerformed(CANCEL_SELECTION); + } + + /** + * DOCUMENT ME! + * + * @param l DOCUMENT ME! + */ + public void addActionListener(ActionListener l) + { + listenerList.add(ActionListener.class, l); + } + + /** + * DOCUMENT ME! + * + * @param l DOCUMENT ME! + */ + public void removeActionListener(ActionListener l) + { + try + { + listenerList.remove(ActionListener.class, l); + } + catch (IllegalArgumentException e) + { + e.printStackTrace(); + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) getListeners(ActionListener.class); + } + + /** + * DOCUMENT ME! + * + * @param command DOCUMENT ME! + */ + protected void fireActionPerformed(String command) + { + ActionListener[] list = getActionListeners(); + ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, + command); + + for (int i = 0; i < list.length; i++) + list[i].actionPerformed(event); + } + + /** + * DOCUMENT ME! + */ + public void updateUI() + { + setUI((FileChooserUI) UIManager.getUI(this)); + revalidate(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return "FileChooserUI"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileChooserUI getUI() + { + return (FileChooserUI) ui; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected String paramString() + { + return "JFileChooser"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/JFormattedTextField.java b/libjava/classpath/javax/swing/JFormattedTextField.java new file mode 100644 index 0000000..f8230f6 --- /dev/null +++ b/libjava/classpath/javax/swing/JFormattedTextField.java @@ -0,0 +1,347 @@ +/* JFormattedTextField.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.event.FocusEvent; +import java.io.Serializable; +import java.text.Format; +import java.text.ParseException; +import java.util.Date; + +import javax.swing.text.DateFormatter; +import javax.swing.text.DefaultFormatter; +import javax.swing.text.Document; +import javax.swing.text.DocumentFilter; +import javax.swing.text.NavigationFilter; + +/** + * @author Michael Koch + * @since 1.4 + */ +public class JFormattedTextField extends JTextField +{ + private static final long serialVersionUID = 5464657870110180632L; + + public abstract static class AbstractFormatter implements Serializable + { + private static final long serialVersionUID = -5193212041738979680L; + + private JFormattedTextField textField; + + public AbstractFormatter () + { + //Do nothing here. + } + + protected Object clone () + throws CloneNotSupportedException + { + throw new InternalError ("not implemented"); + } + + protected Action[] getActions () + { + return textField.getActions(); + } + + protected DocumentFilter getDocumentFilter () + { + throw new InternalError ("not implemented"); + } + + protected JFormattedTextField getFormattedTextField () + { + return textField; + } + + protected NavigationFilter getNavigationFilter () + { + return textField.getNavigationFilter(); + } + + public void install(JFormattedTextField textField) + { + if (this.textField != null) + uninstall(); + + this.textField = textField; + } + + public void uninstall () + { + this.textField = null; + } + + protected void invalidEdit () + { + textField.invalidEdit(); + } + + protected void setEditValid (boolean valid) + { + textField.editValid = valid; + } + + public abstract Object stringToValue (String text) + throws ParseException; + + public abstract String valueToString (Object value) + throws ParseException; + } + + public abstract static class AbstractFormatterFactory + { + public AbstractFormatterFactory () + { + // Do nothing here. + } + + public abstract AbstractFormatter getFormatter (JFormattedTextField tf); + } + + static class FormatterFactoryWrapper extends AbstractFormatterFactory + { + AbstractFormatter formatter; + + public FormatterFactoryWrapper(AbstractFormatter formatter) + { + this.formatter = formatter; + } + + public AbstractFormatter getFormatter(JFormattedTextField tf) + { + return formatter; + } + } + + public static final int COMMIT = 0; + public static final int COMMIT_OR_REVERT = 1; + public static final int REVERT = 2; + public static final int PERSIST = 3; + + private Object value; + private int focusLostBehavior = COMMIT_OR_REVERT; + private AbstractFormatterFactory formatterFactory; + // Package-private to avoid an accessor method. + boolean editValid = true; + + public JFormattedTextField () + { + this((AbstractFormatterFactory) null, null); + } + + public JFormattedTextField (Format format) + { + throw new InternalError ("not implemented"); + } + + public JFormattedTextField (AbstractFormatter formatter) + { + this(new FormatterFactoryWrapper(formatter), null); + } + + public JFormattedTextField (AbstractFormatterFactory factory) + { + this(factory, null); + } + + public JFormattedTextField (AbstractFormatterFactory factory, Object value) + { + this.formatterFactory = factory; + this.value = value; + } + + public JFormattedTextField (Object value) + { + this.value = value; + } + + public void commitEdit () + throws ParseException + { + throw new InternalError ("not implemented"); + } + + public Action[] getActions () + { + // FIXME: Add JFormattedTextField specific actions + return super.getActions(); + } + + public int getFocusLostBehavior() + { + return focusLostBehavior; + } + + public AbstractFormatter getFormatter () + { + if (formatterFactory == null) + return null; + + return formatterFactory.getFormatter(this); + } + + public AbstractFormatterFactory getFormatterFactory () + { + return formatterFactory; + } + + public String getUIClassID () + { + return "FormattedTextFieldUI"; + } + + public Object getValue () + { + return value; + } + + protected void invalidEdit () + { + UIManager.getLookAndFeel().provideErrorFeedback(this); + } + + public boolean isEditValid () + { + return editValid; + } + + protected void processFocusEvent (FocusEvent evt) + { + // it's safe to simply call super for now, until it gets clear + // what this method is supposed to do + // throw new InternalError ("not implemented"); + super.processFocusEvent(evt); + } + + public void setDocument(Document newDocument) + { + Document oldDocument = getDocument(); + + if (oldDocument == newDocument) + return; + + super.setDocument(newDocument); + } + + public void setFocusLostBehavior(int behavior) + { + if (behavior != COMMIT + && behavior != COMMIT_OR_REVERT + && behavior != PERSIST + && behavior != REVERT) + throw new IllegalArgumentException("invalid behavior"); + + this.focusLostBehavior = behavior; + } + + protected void setFormatter (AbstractFormatter formatter) + { + AbstractFormatter oldFormatter = null; + + if (formatterFactory != null) + oldFormatter = formatterFactory.getFormatter(this); + + if (oldFormatter == formatter) + return; + + setFormatterFactory(new FormatterFactoryWrapper(formatter)); + firePropertyChange("formatter", oldFormatter, formatter); + } + + public void setFormatterFactory (AbstractFormatterFactory factory) + { + if (formatterFactory == factory) + return; + + AbstractFormatterFactory oldFactory = formatterFactory; + formatterFactory = factory; + firePropertyChange("formatterFactory", oldFactory, factory); + } + + public void setValue (Object newValue) + { + if (value == newValue) + return; + + // format value + AbstractFormatter formatter = createFormatter(newValue); + try + { + setText(formatter.valueToString(newValue)); + } + catch (ParseException ex) + { + // TODO: what should we do with this? + } + + Object oldValue = value; + value = newValue; + firePropertyChange("value", oldValue, newValue); + } + + /** + * A helper method that attempts to create a formatter that is suitable + * to format objects of the type like value. + * + * If formatterFactory is not null and the returned formatter + * is also not null then this formatter is used. Otherwise we + * try to create one based on the type of value. + * + * @param value an object which should be formatted by the formatter + * + * @return a formatter able to format objects of the class of + * value + */ + AbstractFormatter createFormatter(Object value) + { + AbstractFormatter formatter = null; + if (formatterFactory != null + && formatterFactory.getFormatter(this) != null) + formatter = formatterFactory.getFormatter(this); + else + { + if (value instanceof Date) + formatter = new DateFormatter(); + else + formatter = new DefaultFormatter(); + } + return formatter; + } +} diff --git a/libjava/classpath/javax/swing/JFrame.java b/libjava/classpath/javax/swing/JFrame.java new file mode 100644 index 0000000..d8b10d5 --- /dev/null +++ b/libjava/classpath/javax/swing/JFrame.java @@ -0,0 +1,349 @@ +/* JFrame.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.LayoutManager; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; + +import javax.accessibility.AccessibleContext; + +/** + * Unlike JComponent derivatives, JFrame inherits from + * java.awt.Frame. But also lets a look-and-feel component to its work. + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JFrame extends Frame + implements WindowConstants, RootPaneContainer +{ + private static final long serialVersionUID = -3362141868504252139L; + private static boolean defaultLookAndFeelDecorated; + private int close_action = HIDE_ON_CLOSE; + protected AccessibleContext accessibleContext; + protected JRootPane rootPane; + + /** + * @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; + + public JFrame() + { + super("JFrame"); + frameInit(); + } + + public JFrame(String title) + { + super(title); + frameInit(); + } + + /** + * Creates a new JFrame in the specified {@link GraphicsConfiguration} + * and with an empty title. + * + * @param gc the GraphicsConfiguration that is used for + * the new JFrame + * + * @see Frame(GraphicsConfiguration) + */ + public JFrame(GraphicsConfiguration gc) + { + super(gc); + frameInit(); + } + + /** + * Creates a new JFrame in the specified {@link GraphicsConfiguration} + * and with the specified title. + * + * @param title the title for the new JFrame + * @param gc the GraphicsConfiguration that is used for + * the new JFrame + * + * @see Frame(String, GraphicsConfiguration) + */ + public JFrame(String title, GraphicsConfiguration gc) + { + super(title, gc); + frameInit(); + } + + protected void frameInit() + { + super.setLayout(new BorderLayout(1, 1)); + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + getRootPane(); // will do set/create + // We're now done the init stage. + initStageDone = true; + } + + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + public JMenuBar getJMenuBar() + { + return getRootPane().getJMenuBar(); + } + + public void setJMenuBar(JMenuBar menubar) + { + getRootPane().setJMenuBar(menubar); + } + + public void setLayout(LayoutManager manager) + { + // 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); + } + else + super.setLayout(manager); + } + + public void setLayeredPane(JLayeredPane layeredPane) + { + getRootPane().setLayeredPane(layeredPane); + } + + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } + + public JRootPane getRootPane() + { + if (rootPane == null) + setRootPane(createRootPane()); + return rootPane; + } + + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); + + rootPane = root; + add(rootPane, BorderLayout.CENTER); + } + + protected JRootPane createRootPane() + { + return new JRootPane(); + } + + public Container getContentPane() + { + return getRootPane().getContentPane(); + } + + public void setContentPane(Container contentPane) + { + getRootPane().setContentPane(contentPane); + } + + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + public void setGlassPane(Component glassPane) + { + getRootPane().setGlassPane(glassPane); + } + + protected void addImpl(Component comp, Object constraints, int index) + { + // 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); + else + { + if (isRootPaneCheckingEnabled()) + throw new Error("rootPaneChecking is enabled - adding components " + + "disallowed."); + getContentPane().add(comp,constraints,index); + } + } + + public void remove(Component comp) + { + // If we're removing the root pane, use super.remove. Otherwise + // pass it on to the content pane instead. + if (comp==rootPane) + super.remove(rootPane); + else + getContentPane().remove(comp); + } + + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + public void update(Graphics g) + { + paint(g); + } + + protected void processKeyEvent(KeyEvent e) + { + super.processKeyEvent(e); + } + + public static void setDefaultLookAndFeelDecorated(boolean decorated) + { + defaultLookAndFeelDecorated = decorated; + } + + public static boolean isDefaultLookAndFeelDecorated() + { + return defaultLookAndFeelDecorated; + } + + public AccessibleContext getAccessibleContext() + { + return accessibleContext; + } + + public int getDefaultCloseOperation() + { + return close_action; + } + + protected String paramString() + { + return "JFrame"; + } + + protected void processWindowEvent(WindowEvent e) + { + super.processWindowEvent(e); + switch (e.getID()) + { + case WindowEvent.WINDOW_CLOSING: + { + switch (close_action) + { + case EXIT_ON_CLOSE: + { + System.exit(0); + break; + } + case DISPOSE_ON_CLOSE: + { + dispose(); + break; + } + case HIDE_ON_CLOSE: + { + setVisible(false); + break; + } + case DO_NOTHING_ON_CLOSE: + break; + } + break; + } + case WindowEvent.WINDOW_CLOSED: + case WindowEvent.WINDOW_OPENED: + case WindowEvent.WINDOW_ICONIFIED: + case WindowEvent.WINDOW_DEICONIFIED: + case WindowEvent.WINDOW_ACTIVATED: + case WindowEvent.WINDOW_DEACTIVATED: + break; + } + } + + /** + * Defines what happens when this frame is closed. Can be one off + * EXIT_ON_CLOSE, + * DISPOSE_ON_CLOSE, + * HIDE_ON_CLOSE or + * DO_NOTHING_ON_CLOSE. + * The default is HIDE_ON_CLOSE. + * When EXIT_ON_CLOSE is specified this method calls + * SecurityManager.checkExit(0) which might throw a + * SecurityException. When the specified operation is + * not one of the above a IllegalArgumentException is + * thrown. + */ + public void setDefaultCloseOperation(int operation) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null && operation == EXIT_ON_CLOSE) + sm.checkExit(0); + + if (operation != EXIT_ON_CLOSE && operation != DISPOSE_ON_CLOSE + && operation != HIDE_ON_CLOSE && operation != DO_NOTHING_ON_CLOSE) + throw new IllegalArgumentException("defaultCloseOperation must be EXIT_ON_CLOSE, HIDE_ON_CLOSE, DISPOSE_ON_CLOSE, or DO_NOTHING_ON_CLOSE"); + + close_action = operation; + } +} diff --git a/libjava/classpath/javax/swing/JInternalFrame.java b/libjava/classpath/javax/swing/JInternalFrame.java new file mode 100644 index 0000000..b504aaa --- /dev/null +++ b/libjava/classpath/javax/swing/JInternalFrame.java @@ -0,0 +1,1754 @@ +/* JInternalFrame.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.KeyboardFocusManager; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.beans.PropertyVetoException; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleValue; +import javax.swing.event.InternalFrameEvent; +import javax.swing.event.InternalFrameListener; +import javax.swing.plaf.DesktopIconUI; +import javax.swing.plaf.InternalFrameUI; + +/** + * This class implements a Swing widget that looks and acts like a native + * frame. The frame can be dragged, resized, closed, etc. Typically, + * JInternalFrames are placed in JDesktopPanes. The actions that the + * JInternalFrame performs (maximizing, minimizing, etc.) are performed by a + * DesktopManager. As with regular frames, components are added by calling + * frame.getContentPane().add. + */ +public class JInternalFrame extends JComponent implements Accessible, + WindowConstants, + RootPaneContainer +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -5425177187760785402L; + + /** + * DOCUMENT ME! + */ + protected class AccessibleJInternalFrame extends AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = 5931936924175476797L; + + /** + * Creates a new AccessibleJInternalFrame object. + */ + protected AccessibleJInternalFrame() + { + super(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getAccessibleName() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMaximumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param n DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean setCurrentAccessibleValue(Number n) + { + return false; + } + } + + /** + * This class represents the JInternalFrame while it is iconified. + */ + public static class JDesktopIcon extends JComponent implements Accessible + { + /** + * DOCUMENT ME! + */ + protected class AccessibleJDesktopIcon extends AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = 5035560458941637802L; + + /** + * Creates a new AccessibleJDesktopIcon object. + */ + protected AccessibleJDesktopIcon() + { + super(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMaximumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param n DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean setCurrentAccessibleValue(Number n) + { + return false; + } + } + + private static final long serialVersionUID = 4672973344731387687L; + + /** The JInternalFrame this DesktopIcon represents. */ + JInternalFrame frame; + + /** + * Creates a new JDesktopIcon object for representing the given frame. + * + * @param f The JInternalFrame to represent. + */ + public JDesktopIcon(JInternalFrame f) + { + frame = f; + updateUI(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJDesktopIcon(); + return accessibleContext; + } + + /** + * This method returns the JDesktopPane this JDesktopIcon is in. + * + * @return The JDesktopPane this JDesktopIcon is in. + */ + public JDesktopPane getDesktopPane() + { + JDesktopPane p = (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class, + this); + return p; + } + + /** + * This method returns the JInternalFrame this JDesktopIcon represents. + * + * @return The JInternalFrame this JDesktopIcon represents. + */ + public JInternalFrame getInternalFrame() + { + return frame; + } + + /** + * This method returns the UI that is responsible for the JDesktopIcon. + * + * @return The UI that is responsible for the JDesktopIcon. + */ + public DesktopIconUI getUI() + { + return (DesktopIconUI) ui; + } + + /** + * This method returns the String identifier that is used to determine + * which class is used for JDesktopIcon's UI. + * + * @return A String identifier for the UI class. + */ + public String getUIClassID() + { + return "DesktopIconUI"; + } + + /** + * This method sets the JInternalFrame that this JDesktopIcon represents. + * + * @param f The JInternalFrame that this JDesktopIcon represents. + */ + public void setInternalFrame(JInternalFrame f) + { + frame = f; + } + + /** + * This method sets the UI used for this JDesktopIcon. + * + * @param ui The UI to use. + */ + public void setUI(DesktopIconUI ui) + { + super.setUI(ui); + } + + /** + * This method restores the UI property to the defaults. + */ + public void updateUI() + { + setUI((DesktopIconUI) UIManager.getUI(this)); + } + } + + /** + * The property fired in a PropertyChangeEvent when the contentPane property + * changes. + */ + public static final String CONTENT_PANE_PROPERTY = "contentPane"; + + /** + * The property fired in a PropertyChangeEvent when the frameIcon property + * changes. + */ + public static final String FRAME_ICON_PROPERTY = "frameIcon"; + + /** + * The property fired in a PropertyChangeEvent when the glassPane property + * changes. + */ + public static final String GLASS_PANE_PROPERTY = "glassPane"; + + /** + * The property fired in a PropertyChangeEvent when the closed property + * changes. + */ + public static final String IS_CLOSED_PROPERTY = "closed"; + + /** + * The property fired in a PropertyChangeEvent when the icon property + * changes. + */ + public static final String IS_ICON_PROPERTY = "icon"; + + /** + * The property fired in a PropertyChangeEvent when the maximum property + * changes. + */ + public static final String IS_MAXIMUM_PROPERTY = "maximum"; + + /** + * The property fired in a PropertyChangeEvent when the selected property + * changes. + */ + public static final String IS_SELECTED_PROPERTY = "selected"; + + /** + * The property fired in a PropertyChangeEvent when the layeredPane property + * changes. + */ + public static final String LAYERED_PANE_PROPERTY = "layeredPane"; + + /** + * The property fired in a PropertyChangeEvent when the jMenuBar property + * changes. + */ + public static final String MENU_BAR_PROPERTY = "JMenuBar"; + + /** + * The property fired in a PropertyChangeEvent when the rootPane property + * changes. + */ + public static final String ROOT_PANE_PROPERTY = "rootPane"; + + /** + * The property fired in a PropertyChangeEvent when the title property + * changes. + */ + public static final String TITLE_PROPERTY = "title"; + + /** Whether the JInternalFrame is closable. */ + protected boolean closable; + + /** Whether the JInternalFrame can be iconified. */ + protected boolean iconable; + + /** Whether the JInternalFrame is closed. */ + protected boolean isClosed; + + /** Whether the JInternalFrame has been iconified. */ + protected boolean isIcon; + + /** Whether the JInternalFrame has been maximized. */ + protected boolean isMaximum; + + /** Whether the JInternalFrame is the active frame. */ + protected boolean isSelected; + + /** Whether the JInternalFrame can be maximized. */ + protected boolean maximizable; + + /** + * Whether the JInternalFrame has rootPaneChecking enabled. + * + * @specnote Should be 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; + + /** Whether the JInternalFrame is resizable. */ + protected boolean resizable; + + /** + * The JDesktopIcon that represents the JInternalFrame while it is + * iconified. + */ + protected JDesktopIcon desktopIcon; + + /** The icon used in the JMenuBar in the TitlePane. */ + protected Icon frameIcon; + + /** The rootPane of the JInternalFrame. */ + protected JRootPane rootPane; + + /** The title on the TitlePane of the JInternalFrame. */ + protected String title; + + /** The bounds of the JInternalFrame before it was maximized. */ + private transient Rectangle storedBounds; + + /** The Component that receives focus by default. */ + private transient Component defaultFocus; + + /** The default close action taken, */ + private transient int defaultCloseOperation = DISPOSE_ON_CLOSE; + + /** Whether the JInternalFrame has become visible for the very first time. */ + private transient boolean isFirstTimeVisible = true; + + /** + * Whether the JInternalFrame is in the transition from being a maximized + * frame back to a regular sized frame. + */ + private transient boolean maxTransition = false; + + /** DOCUMENT ME! */ + private transient boolean wasIcon = false; + + /** + * Creates a new JInternalFrame object that has no title, and is + * non-resizable, non-maximizable, non-iconifiable, and non-closable. + */ + public JInternalFrame() + { + this(null, false, false, false, false); + } + + /** + * Creates a new JInternalFrame object with the given title and is + * non-resizable, non-maximizable, non-iconifiable, and non-closable. + * + * @param title The title displayed in the JInternalFrame. + */ + public JInternalFrame(String title) + { + this(title, false, false, false, false); + } + + /** + * Creates a new JInternalFrame object with the given title and resizable + * properties. The JInternalFrame is non-maximizable, non-iconifiable, and + * non-closable. + * + * @param title The title displayed in the JInternalFrame. + * @param resizable Whether the JInternalFrame is resizable. + */ + public JInternalFrame(String title, boolean resizable) + { + this(title, resizable, false, false, false); + } + + /** + * Creates a new JInternalFrame object with the given title, resizable, and + * closable properties. The JInternalFrame is non-maximizable and + * non-iconifiable. + * + * @param title The title displayed in the JInternalFrame. + * @param resizable Whether the JInternalFrame is resizable. + * @param closable Whether the JInternalFrame is closable. + */ + public JInternalFrame(String title, boolean resizable, boolean closable) + { + this(title, resizable, closable, false, false); + } + + /** + * Creates a new JInternalFrame object with the given title, resizable, + * closable and maximizable properties. The JInternalFrame is + * non-iconifiable. + * + * @param title The title displayed in the JInternalFrame. + * @param resizable Whether the JInternalFrame is resizable. + * @param closable Whether the JInternalFrame is closable. + * @param maximizable Whether the JInternalFrame is maximizable. + */ + public JInternalFrame(String title, boolean resizable, boolean closable, + boolean maximizable) + { + this(title, resizable, closable, maximizable, false); + } + + /** + * Creates a new JInternalFrame object with the given title, resizable, + * closable, maximizable and iconifiable properties. + * + * @param title The title displayed in the JInternalFrame. + * @param resizable Whether the JInternalFrame is resizable. + * @param closable Whether the JInternalFrame is closable. + * @param maximizable Whether the JInternalFrame is maximizable. + * @param iconifiable Whether the JInternalFrame is iconifiable. + */ + public JInternalFrame(String title, boolean resizable, boolean closable, + boolean maximizable, boolean iconifiable) + { + this.title = title; + this.resizable = resizable; + this.closable = closable; + this.maximizable = maximizable; + this.iconable = iconifiable; + storedBounds = new Rectangle(); + setRootPane(createRootPane()); + updateUI(); + initStageDone = true; // Done the init stage, now adds go to content pane. + } + + /** + * This method adds Components to this Container. For JInternalFrames, + * instead of calling add directly on the JInternalFrame, it should be + * called with JInternalFrame.getContentPane().add. If root pane checking + * is enabled, calling this method will cause an exception to be thrown. + * + * @param comp The Component to add. + * @param constraints The constraints on the Component added. + * @param index The position to place the Component. + * + * @throws Error DOCUMENT ME! + */ + protected void addImpl(Component comp, Object constraints, int index) + { + // 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); + else + { + if (isRootPaneCheckingEnabled()) + throw new Error("Do not use add() on JInternalFrame directly. Use " + + "getContentPane().add() instead"); + getContentPane().add(comp, constraints, index); + } + } + + /** + * This method adds an InternalFrameListener to this JInternalFrame. + * + * @param l The listener to add. + */ + public void addInternalFrameListener(InternalFrameListener l) + { + listenerList.add(InternalFrameListener.class, l); + } + + /** + * This method is used to create a root pane for the JInternalFrame. This + * method is called by the constructors. + * + * @return A root pane for the JInternalFrame to use. + */ + protected JRootPane createRootPane() + { + return new JRootPane(); + } + + /** + * This method makes this JInternalFrame invisible, unselected and closed. + * If this JInternalFrame is not closed already, it will fire an + * INTERNAL_FRAME_CLoSED event. This method is similar to setClosed but it + * doesn't give vetoable listeners a chance to veto and it will not fire an + * INTERNAL_FRAME_CLOSING event. + */ + public void dispose() + { + hide(); + JDesktopPane pane = getDesktopPane(); + if (pane != null) + pane.setSelectedFrame(null); + else + { + try + { + setSelected(false); + } + catch (PropertyVetoException e) + { + // Do nothing if they don't want to be unselected. + } + } + isClosed = true; + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED); + removeNotify(); + } + + /** + * This method is used for closing this JInternalFrame. It fires an + * INTERNAL_FRAME_CLOSING event and then performs the action specified by + * the default close operation. + */ + public void doDefaultCloseAction() + { + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); + switch (getDefaultCloseOperation()) + { + case HIDE_ON_CLOSE: + hide(); + break; + case DISPOSE_ON_CLOSE: + dispose(); + break; + } + } + + /** + * This method fires an InternalFrameEvent to the listeners. + * + * @param id The type of event being fired. See InternalFrameEvent. + */ + protected void fireInternalFrameEvent(int id) + { + Object[] ifListeners = listenerList.getListenerList(); + InternalFrameEvent evt = new InternalFrameEvent(this, id); + switch (id) + { + case InternalFrameEvent.INTERNAL_FRAME_CLOSING: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]) + .internalFrameClosing(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]) + .internalFrameActivated(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_CLOSED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]).internalFrameClosed(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]) + .internalFrameDeactivated(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]) + .internalFrameDeiconified(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]) + .internalFrameIconified(evt); + } + break; + case InternalFrameEvent.INTERNAL_FRAME_OPENED: + for (int i = ifListeners.length - 2; i >= 0; i -= 2) + { + if (ifListeners[i] == InternalFrameListener.class) + ((InternalFrameListener) ifListeners[i + 1]).internalFrameOpened(evt); + } + break; + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJInternalFrame(); + return accessibleContext; + } + + /** + * This method returns the Content Pane for this JInternalFrame. + * + * @return The Content Pane for this JInternalFrame. + */ + public Container getContentPane() + { + return getRootPane().getContentPane(); + } + + /** + * This method returns the default action taken when this JInternalFrame is + * closed. + * + * @return The default action taken when this JInternalFrame is closed. + */ + public int getDefaultCloseOperation() + { + return defaultCloseOperation; + } + + /** + * This method returns the JDesktopIcon that represents this JInternalFrame + * while it is iconified. + * + * @return The JDesktopIcon that represents this JInternalFrame while it is + * iconified. + */ + public JDesktopIcon getDesktopIcon() + { + if (desktopIcon == null) + desktopIcon = new JDesktopIcon(this); + return desktopIcon; + } + + /** + * This method searches this JInternalFrame ancestors for an instance of + * JDesktopPane. If one is found, it is returned. If none is found, then it + * will search the JDesktopIcon for a JDesktopPane. + * + * @return The JDesktopPane that this JInternalFrame belongs to. + */ + public JDesktopPane getDesktopPane() + { + JDesktopPane value = (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class, + this); + if (value == null && desktopIcon != null) + value = desktopIcon.getDesktopPane(); + return value; + } + + /** + * This method returns null because this must always be the root of a focus + * traversal. + * + * @return always null + * + * @since 1.4 + */ + public final Container getFocusCycleRootAncestor() + { + // as defined. + return null; + } + + /** + * This method returns the child Component that will receive focus if this + * JInternalFrame is selected. + * + * @return The child Component that will receive focus. + */ + public Component getFocusOwner() + { + if (isSelected()) + { + Component focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if (SwingUtilities.isDescendingFrom(focus, this)) + { + defaultFocus = focus; + return focus; + } + } + return null; + } + + /** + * This method returns the Frame Icon (the icon used in the JInternalFrame + * TitlePane and iconified frame). + * + * @return The Frame Icon. + */ + public Icon getFrameIcon() + { + return frameIcon; + } + + /** + * This method returns the Glass Pane used with this JInternalFrame. + * + * @return The Glass Pane used with this JInternalFrame. + */ + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + /** + * This method returns an array of InternalFrameListeners that are listening + * to this JInternalFrame. + * + * @return An array of InternalFrameListeners that are listening to this + * JInternalFrame. + */ + public InternalFrameListener[] getInternalFrameListeners() + { + return (InternalFrameListener[]) listenerList.getListeners(InternalFrameListener.class); + } + + /** + * This method returns the JMenuBar for this JInternalFrame. + * + * @return The JMenuBar for this JInternalFrame. + */ + public JMenuBar getJMenuBar() + { + return getRootPane().getJMenuBar(); + } + + /** + * This method returns the layer that this JInternalFrame resides in. + * + * @return The layer that this JInternalFrame resides in. + */ + public int getLayer() + { + JDesktopPane pane = getDesktopPane(); + if (pane != null) + // The cast here forces the call to the instance method getLayer() + // instead of the static method (this would lead to infinite + // recursion). + return pane.getLayer((Component) this); + return -1; + } + + /** + * This method returns the LayeredPane for this JInternalFrame. + * + * @return The LayeredPane for this JInternalFrame. + */ + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } + + /** + * This method is deprecated. This method returns the JMenuBar for this + * JInternalFrame. + * + * @return The JMenuBar for this JInternalFrame. + * + * @deprecated 1.0.3 + */ + public JMenuBar getMenuBar() + { + return getJMenuBar(); + } + + /** + * This method returns the child Component that will receive focus when the + * JInternalFrame is selected. If the JInternalFrame is selected, this + * method returns getFocusOwner(). Otherwise, it will return the child + * Component that most recently requested focus. If that is null, then the + * initial focus Component is returned. If that is null, then the default + * focus component is returned. + * + * @return The most recent focus owner. + */ + public Component getMostRecentFocusOwner() + { + if (isSelected()) + return getFocusOwner(); + else + return defaultFocus; + } + + /** + * This method returns the bounds of the JInternalFrame if it is not + * maximized. If it is maximized, it returns the bounds of the + * JInternalFrame before it was maximized (the bounds that it will be + * restored to). + * + * @return A Rectangle that contains this JInternalFrame's normal bounds (or + * just its bounds if it is not maximized). + */ + public Rectangle getNormalBounds() + { + if (! isMaximum() && ! maxTransition) + return getBounds(); + else + return storedBounds; + } + + /** + * This method returns the Root Pane for this JInternalFrame. + * + * @return The Root Pane for this JInternalFrame. + */ + public JRootPane getRootPane() + { + return rootPane; + } + + /** + * This method sets the title of the JInternalFrame. + * + * @return The String displayed in the TitlePane of this JInternalFrame. + */ + public String getTitle() + { + return title; + } + + /** + * This method returns the UI used to represent the JInternalFrame. + * + * @return The UI used to represent the JInternalFrame. + */ + public InternalFrameUI getUI() + { + return (InternalFrameUI) ui; + } + + /** + * This method returns a String identifier that is used to determine which + * class acts as the JInternalFrame's UI. + * + * @return A String identifier to determine a UI class. + */ + public String getUIClassID() + { + return "InternalFrameUI"; + } + + /** + * This method returns null. + * + * @return null. + */ + public final String getWarningString() + { + // as defined. + return null; + } + + /** + * This method deselects this JInternalFrame and hides it. + */ + public void hide() + { + JDesktopPane pane = getDesktopPane(); + if (pane != null) + pane.setSelectedFrame(null); + else + { + try + { + setSelected(false); + } + catch (PropertyVetoException e) + { + // Do nothing. + } + } + super.hide(); + } + + /** + * This method returns whether this JInternalFrame is closable. + * + * @return Whether this JInternalFrame is closable. + */ + public boolean isClosable() + { + return closable; + } + + /** + * This method returns whether this JInternalFrame has been closed. + * + * @return Whether this JInternalFrame is closed. + */ + public boolean isClosed() + { + return isClosed; + } + + /** + * This must always return true. + * + * @return always true + * + * @since 1.4 + */ + public final boolean isFocusCycleRoot() + { + return true; + } + + /** + * This method returns whether this JInternalFrame is currently iconified. + * + * @return Whether this JInternalFrame is currently iconified. + */ + public boolean isIcon() + { + return isIcon; + } + + /** + * This method returns whether the JInternalFrame can be iconified. + * + * @return Whether the JInternalFrame can be iconified. + */ + public boolean isIconifiable() + { + return iconable; + } + + /** + * This method returns whether this JInternalFrame can be maximized. + * + * @return Whether this JInternalFrame can be maximized. + */ + public boolean isMaximizable() + { + return maximizable; + } + + /** + * This method returns whether this JInternalFrame is currently maximized. + * + * @return Whether this JInternalFrame is maximized. + */ + public boolean isMaximum() + { + return isMaximum; + } + + /** + * This method returns whether this JInternalFrame is resizable. + * + * @return Whether this JInternalFrame is resizable. + */ + public boolean isResizable() + { + return resizable; + } + + /** + * This method returns whether root pane checking is enabled. If root pane + * checking is enabled, then calls to addImpl and setLayout will throw + * exceptions. + * + * @return Whether root pane checking is enabled. + */ + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + /** + * This method returns whether this JInternalFrame is selected. + * + * @return Whether this JInternalFrame is selected. + */ + public boolean isSelected() + { + return isSelected; + } + + /** + * A helper method that moves this JInternalFrame to the back if the parent + * is a JLayeredPane. + */ + public void moveToBack() + { + if (getParent() instanceof JLayeredPane) + ((JLayeredPane) getParent()).moveToBack(this); + } + + /** + * A helper method that moves this JInternalFrame to the front if the parent + * is a JLayeredPane. + */ + public void moveToFront() + { + if (getParent() instanceof JLayeredPane) + ((JLayeredPane) getParent()).moveToFront(this); + } + + /** + * This method causes the children of this JInternalFrame to be laid out. + * Before it begins, if this JInternalFrame is an icon, then it will be + * deiconified. If it is maximized, then it will be restored. If either + * operation fails, then this method will return. + */ + public void pack() + { + try + { + if (isIcon()) + setIcon(false); + else if (isMaximum()) + setMaximum(false); + } + catch (PropertyVetoException e) + { + // Do nothing if they don't want to be restored first. + } + setSize(getPreferredSize()); + } + + /** + * This method is overridden to allow for speedier painting while this + * JInternalFramme is being dragged. + * + * @param g The Graphics object to paint with. + */ + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + } + + /** + * This method returns a String describing this JInternalFrame. + * + * @return A String describing this JInternalFrame. + */ + protected String paramString() + { + return "JInternalFrame"; + } + + /** + * This method removes the given Component from the Container. + * + * @param comp The Component to remove. + */ + public void remove(Component comp) + { + // If we're removing the root pane, use super.remove. Otherwise + // pass it on to the content pane instead. + if (comp==rootPane) + super.remove(comp); + else + getContentPane().remove(comp); + } + + /** + * This method removes an InternalFrameListener from this JInternalFrame. + * + * @param l The listener to remove. + */ + public void removeInternalFrameListener(InternalFrameListener l) + { + listenerList.remove(InternalFrameListener.class, l); + } + + /** + * This method resizes and positions this JInternalFrame. It also forces a + * relayout of the Container. + * + * @param x The x position of this JInternalFrame. + * @param y The y position of this JInternalFrame. + * @param width The width of this JInternalFrame. + * @param height The height of this JInternalFrame. + */ + public void reshape(int x, int y, int width, int height) + { + super.reshape(x, y, width, height); + invalidate(); + doLayout(); + } + + /** + * This method gives focus to the last child Component that had focus. This + * is used by the UI when this JInternalFrame is activated. + */ + public void restoreSubcomponentFocus() + { + Component c = getMostRecentFocusOwner(); + if (c != null) + c.requestFocus(); + } + + /** + * This method sets whether this JInternalFrame can be closed. + * + * @param b Whether this JInternalFrame can be closed. + */ + public void setClosable(boolean b) + { + closable = b; + } + + /** + * This method closes the JInternalFrame if the given boolean is true. If it + * is false, then the result of this method is unspecified. If the + * JInternalFrame is closed, this method does nothing. This method will + * first fire an INTERNAL_FRAME_CLOSING event and give a chance for veto + * listeners to cancel the close. If no listener vetoes the change, the + * closed property is set to true and the JInternalFrame is hidden and + * unselected. The method will finish by firing an INTERNAL_FRAME_CLOSED + * event. + * + * @param b Whether the JInternalFrame will be closed. + * + * @throws PropertyVetoException If a VetoableChangeListener vetoes the change. + */ + public void setClosed(boolean b) throws PropertyVetoException + { + if (b && ! isClosed()) + { + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); + fireVetoableChange(IS_CLOSED_PROPERTY, false, true); + + isClosed = b; + + firePropertyChange(IS_CLOSED_PROPERTY, false, true); + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED); + } + } + + /** + * This method sets the Container to be used as a Content Pane for this + * JInternalFrame. + * + * @param c The Container to use as a Content Pane. + */ + public void setContentPane(Container c) + { + if (c != getContentPane()) + { + Container old = getContentPane(); + getRootPane().setContentPane(c); + firePropertyChange(CONTENT_PANE_PROPERTY, old, c); + } + } + + /** + * This method sets the action taken when this JInternalFrame is closed. + * + * @param operation One of DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE or + * DISPOSE_ON_CLOSE. + * + * @throws Error If the given operation is not one of the allowed modes. + */ + public void setDefaultCloseOperation(int operation) + { + /* Reference implementation allows invalid operations to be specified. + In that case, behaviour defaults to DO_NOTHING_ON_CLOSE. + processWindowEvent handles the behaviour. getDefaultCloseOperation + must return the invalid operator code. */ + defaultCloseOperation = operation; + } + + /** + * This method sets the JDesktopIcon that represents this JInternalFrame + * while it is iconified. + * + * @param d The JDesktopIcon that represents this JInternalFrame while it is + * iconified. + */ + public void setDesktopIcon(JDesktopIcon d) + { + d.setInternalFrame(this); + desktopIcon = d; + } + + /** + * This method does nothing because this must be the root of a focus + * traversal cycle. + * + * @param focusCycleRoot Not used. + */ + public final void setFocusCycleRoot(boolean focusCycleRoot) + { + // Do nothing + } + + /** + * This method sets the Icon to be used in two places. The first is icon + * that is painted at the top left corner of the JInternalFrame when it is + * not iconified (clicking on that icon will activate the TitlePane + * JMenuBar). When the JInternalFrame is iconified, it will be the icon + * displayed in the JDesktopIcon. If no icon is set, the JInternalFrame + * will use a Look and Feel default. + * + * @param icon The Icon used in the TitlePane JMenuBar and iconified frames. + */ + public void setFrameIcon(Icon icon) + { + if (icon != frameIcon) + { + Icon old = frameIcon; + frameIcon = icon; + firePropertyChange(FRAME_ICON_PROPERTY, old, frameIcon); + } + } + + /** + * This method sets the Glass Pane used with this JInternalFrame. + * + * @param glass The Glass Pane to use with this JInternalFrame. + */ + public void setGlassPane(Component glass) + { + if (glass != getGlassPane()) + { + Component old = getGlassPane(); + getRootPane().setGlassPane(glass); + firePropertyChange(GLASS_PANE_PROPERTY, old, glass); + } + } + + /** + * This method iconifies or deiconifies this JInternalFrame given the + * boolean argument. If the JInternalFrame becomes iconified, it will fire + * an INTERNAL_FRAME_ICONIFIED event. If the JInternalFrame becomes + * deiconified, it will fire anINTERNAL_FRAME_DEICONIFIED event. + * + * @param b Whether this JInternalFrame is to be iconified or deiconified. + * + * @throws PropertyVetoException DOCUMENT ME! + */ + public void setIcon(boolean b) throws PropertyVetoException + { + if (b != isIcon()) + { + fireVetoableChange(IS_ICON_PROPERTY, b, isIcon); + + isIcon = b; + + firePropertyChange(IS_ICON_PROPERTY, ! isIcon, isIcon); + if (b) + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED); + else + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED); + } + } + + /** + * This method sets whether the JInternalFrame can be iconified. (This means + * that the JInternalFrame can be turned into an icon if minimized). + * + * @param b Whether the JInternalFrame can be iconified. + */ + public void setIconifiable(boolean b) + { + iconable = b; + } + + /** + * This method sets the JMenuBar to be used with this JInternalFrame. + * + * @param b The JMenuBar to be used with this JInternalFrame. + */ + public void setJMenuBar(JMenuBar b) + { + getRootPane().setJMenuBar(b); + } + + /** + * A helper method that set the layer that this JInternalFrame resides in. + * Using this version of the method means that the user should not set it + * to values that are already defined in JLayeredPane. If predefined values + * are to be used, the user should use the setLayer(Integer) version. + * + * @param layer The layer to place this JInternalFrame in. + */ + public void setLayer(int layer) + { + setLayer(new Integer(layer)); + } + + /** + * A helper method that sets the layer that this JInternalFrame resides in. + * Calling this version of the method should use layer values that are + * already defined in JLayeredPane. + * + * @param layer The layer to place this JInternalFrame in. + */ + public void setLayer(Integer layer) + { + JDesktopPane p = getDesktopPane(); + if (p != null) + { + int pos = p.getPosition(this); + p.setLayer(this, layer.intValue(), pos); + } + } + + /** + * This method sets the JLayeredPane to use with this JInternalFrame. + * + * @param layered The JLayeredPane to use as a layeredPane. + */ + public void setLayeredPane(JLayeredPane layered) + { + if (layered != getLayeredPane()) + { + JLayeredPane old = getLayeredPane(); + getRootPane().setLayeredPane(layered); + firePropertyChange(LAYERED_PANE_PROPERTY, old, layered); + } + } + + /** + * This method sets whether the JInternalFrame can be maximized. + * + * @param b Whether this JInternalFrame can be maximized. + */ + public void setMaximizable(boolean b) + { + maximizable = b; + } + + /** + * This method sets the Layout Manager used in the JInternalFrame. SetLayout + * should not be called on the JInternalFrame directly. Instead, it should + * be called with JInternalFrame.getContentPane().setLayout. Calls to this + * method with root pane checking enabled will cause exceptions to be + * thrown. + * + * @param manager The Layout Manager to be used with the JInternalFrame. + * + * @throws Error If rootPaneChecking is enabled. + */ + public void setLayout(LayoutManager manager) + { + // 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); + } + else + super.setLayout(manager); + } + + /** + * This method sets the JInternalFrame to maximized (if the given argument + * is true) or restores the JInternalFrame to its normal bounds otherwise. + * + * @param b Whether this JInteralFrame will be maximized or restored. + * + * @throws PropertyVetoException If a VetoableChangeListener vetoes the change. + */ + public void setMaximum(boolean b) throws PropertyVetoException + { + if (b != isMaximum()) + { + fireVetoableChange(IS_MAXIMUM_PROPERTY, b, isMaximum); + isMaximum = b; + if (b) + setNormalBounds(getBounds()); + maxTransition = ! b; + firePropertyChange(IS_MAXIMUM_PROPERTY, ! isMaximum, isMaximum); + maxTransition = false; + } + } + + /** + * This method is deprecated. This method sets the JMenuBar used with this + * JInternalFrame. + * + * @param m The JMenuBar to use with this JInternalFrame. + * + * @deprecated 1.0.3 + */ + public void setMenuBar(JMenuBar m) + { + setJMenuBar(m); + } + + /** + * This method sets the bounds that this JInternalFrame will be restored to. + * + * @param r The bounds that this JInternalFrame will be restored to. + */ + public void setNormalBounds(Rectangle r) + { + storedBounds.setBounds(r.x, r.y, r.width, r.height); + } + + /** + * This method sets whether the JInternalFrame can be resized by a user + * action (like dragging at the frame borders). + * + * @param b Whether this JInternalFramer can be resized. + */ + public void setResizable(boolean b) + { + resizable = b; + } + + /** + * This method sets the Root Pane for this JInternalFrame. + * + * @param root The Root Pane for this JInternalFrame. + */ + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); + + rootPane = root; + add(root); + } + + /** + * This method sets whether root pane checking is enabled. If root pane + * checking is enabled, then calls to addImpl and setLayout will throw + * exceptions. + * + * @param enabled Whether root pane checking is enabled. + */ + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + /** + * This method sets whether this JInternalFrame is the selected frame in the + * JDesktopPane (or other container). When selected, a JInternalFrame will + * have focus and paint its TitlePane differently (usually a different + * colour). If this method selects the frame, this JInternalFrame will fire + * an INTERNAL_FRAME_ACTIVATED event. If it deselects this frame, it will + * fire an INTERNAL_FRAME_DEACTIVATED event. + * + * @param selected Whether this JInternalFrame will become selected or + * deselected. + * + * @throws PropertyVetoException If a VetoableChangeListener vetoes the change. + */ + public void setSelected(boolean selected) throws PropertyVetoException + { + if (selected != isSelected()) + { + fireVetoableChange(IS_SELECTED_PROPERTY, selected, isSelected); + + if (! selected) + defaultFocus = getMostRecentFocusOwner(); + + isSelected = selected; + + if (selected) + restoreSubcomponentFocus(); + + firePropertyChange(IS_SELECTED_PROPERTY, ! isSelected, isSelected); + + if (isSelected) + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED); + else + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED); + } + } + + /** + * This method sets the title displayed in the TitlePane of this + * JInternalFrame. + * + * @param title The title displayed. + */ + public void setTitle(String title) + { + if (title == null && this.title == null) + return; + if (title == null || this.title == null || ! this.title.equals(title)) + { + String old = title; + this.title = title; + firePropertyChange(TITLE_PROPERTY, old, this.title); + } + } + + /** + * This method displays the JInternalFrame. If it is not visible, this + * method will bring this JInternalFrame to the front, make it visible and + * select it. If this is the first time this JInternalFrame is made + * visible, an INTERNAL_FRAME_OPENED event will be fired. + */ + public void show() + { + if (! isVisible()) + { + moveToFront(); + super.show(); + + JDesktopPane pane = getDesktopPane(); + if (pane != null) + pane.setSelectedFrame(this); + else + { + try + { + setSelected(true); + } + catch (PropertyVetoException e) + { + // Do nothing. if they don't want to be selected. + } + } + if (isFirstTimeVisible) + { + isFirstTimeVisible = false; + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED); + } + } + } + + /** + * This method is used to set the UI responsible for the JInternalFrame. + * + * @param ui The UI responsible for the JInternalFrame. + */ + public void setUI(InternalFrameUI ui) + { + super.setUI(ui); + } + + /** + * This method causes the JInternalFrame to be brough to back in the + * z-order. + */ + public void toBack() + { + moveToBack(); + } + + /** + * This method causes the JInternalFrame to be brought to front in the + * z-order. + */ + public void toFront() + { + moveToFront(); + } + + /** + * This method resets the UI to the Look and Feel defaults. + */ + public void updateUI() + { + setUI((InternalFrameUI) UIManager.getUI(this)); + } + + /** + * This helper method allows JInternalFrames to signal that they were + * iconned for the first time. + * + * @param b Whether the JInternalFrame was iconned. + * @param ID The identifier of the property change event to fire if the + * JInternalFrame is iconned for the first time. + */ + void setWasIcon(boolean b, String ID) + { + if (b && ! wasIcon) + { + wasIcon = b; + firePropertyChange(ID, ! b, b); + } + } + + /** + * This helper method returns whether the JInternalFrame has been iconned + * once already. + * + * @return Whether the JInternalFrame has been iconned once already. + */ + boolean getWasIcon() + { + return wasIcon; + } + + /** + * This method is a convenience method to fire vetoable property changes. + * + * @param name The identifier of the property change. + * @param oldValue The old value. + * @param newValue The new value. + * + * @throws PropertyVetoException Fired if a vetoable change listener vetoes + * the change. + */ + private void fireVetoableChange(String name, boolean oldValue, + boolean newValue) + throws PropertyVetoException + { + super.fireVetoableChange(name, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); + } +} diff --git a/libjava/classpath/javax/swing/JLabel.java b/libjava/classpath/javax/swing/JLabel.java new file mode 100644 index 0000000..088f7d6 --- /dev/null +++ b/libjava/classpath/javax/swing/JLabel.java @@ -0,0 +1,647 @@ +/* JLabel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.KeyEvent; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.plaf.LabelUI; + +/** + * A swing widget that displays a text message and/or an icon. + */ +public class JLabel extends JComponent implements Accessible, SwingConstants +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = 5496508283662221534L; + + /** + * The Component the label will give focus to when its mnemonic is + * activated. + */ + protected Component labelFor; + + /** The label's text. */ + private transient String text; + + /** Where the label will be positioned horizontally. */ + private transient int horizontalAlignment = LEADING; + + /** Where the label text will be placed horizontally relative to the icon. */ + private transient int horizontalTextPosition = TRAILING; + + /** Where the label will be positioned vertically. */ + private transient int verticalAlignment = CENTER; + + /** Where the label text will be place vertically relative to the icon. */ + private transient int verticalTextPosition = CENTER; + + /** The icon painted when the label is enabled. */ + private transient Icon icon; + + /** The icon painted when the label is disabled. */ + private transient Icon disabledIcon; + + /** The label's mnemnonic key. */ + private transient int displayedMnemonic = KeyEvent.VK_UNDEFINED; + + /** The index of the menemonic character in the text. */ + private transient int displayedMnemonicIndex = -1; + + /** The gap between the icon and the text. */ + private transient int iconTextGap = 4; + + /** + * Creates a new vertically centered, horizontally on the leading edge + * JLabel object with text and no icon. + */ + public JLabel() + { + this(null, null, LEADING); + } + + /** + * Creates a new vertically and horizontally centered + * JLabel object with no text and the given icon. + * + * @param image The icon to use with the label. + */ + public JLabel(Icon image) + { + this(null, image, CENTER); + } + + /** + * Creates a new vertically centered JLabel object with no text and the + * given icon and horizontal alignment. By default, the text is TRAILING + * the image. + * + * @param image The icon to use with the label. + * @param horizontalAlignment The horizontal alignment of the label. + */ + public JLabel(Icon image, int horizontalAlignment) + { + this(null, image, horizontalAlignment); + } + + /** + * Creates a new horizontally leading and vertically centered JLabel + * object with no icon and the given text. + * + * @param text The text to use with the label. + */ + public JLabel(String text) + { + this(text, null, LEADING); + } + + /** + * Creates a new vertically centered JLabel object with no icon and the + * given text and horizontal alignment. + * + * @param text The text to use with the label. + * @param horizontalAlignment The horizontal alignment of the label. + */ + public JLabel(String text, int horizontalAlignment) + { + this(text, null, horizontalAlignment); + } + + /** + * Creates a new vertically centered JLabel object with the given text, + * icon, and horizontal alignment. + * + * @param text The text to use with the label. + * @param icon The icon to use with the label. + * @param horizontalAlignment The horizontal alignment of the label. + */ + public JLabel(String text, Icon icon, int horizontalAlignment) + { + this.text = text; + this.icon = icon; + this.horizontalAlignment = horizontalAlignment; + updateUI(); + } + + /** + * This method returns the label's UI delegate. + * + * @return The label's UI delegate. + */ + public LabelUI getUI() + { + return (LabelUI) ui; + } + + /** + * This method sets the label's UI delegate. + * + * @param ui The label's UI delegate. + */ + public void setUI(LabelUI ui) + { + super.setUI(ui); + } + + /** + * This method resets the label's UI delegate to the default UI for the + * current look and feel. + */ + public void updateUI() + { + setUI((LabelUI) UIManager.getUI(this)); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for this label. + * + * @return The UIClass identifier. "LabelUI" + */ + public String getUIClassID() + { + return "LabelUI"; + } + + /** + * This method is used primarily for debugging purposes and returns a string + * that can be used to represent this label. + * + * @return A string to represent this label. + */ + protected String paramString() + { + return "JLabel"; + } + + /** + * This method returns the label text. + * + * @return The label text. + */ + public String getText() + { + return text; + } + + /** + * This method changes the "text" property. The given text will be painted + * in the label. + * + * @param newText The label's text. + */ + public void setText(String newText) + { + if (text != newText) + { + String oldText = text; + text = newText; + firePropertyChange("text", oldText, newText); + + if (text != null && text.length() <= displayedMnemonicIndex) + setDisplayedMnemonicIndex(text.length() - 1); + } + } + + /** + * This method returns the active icon. The active icon is painted when the + * label is enabled. + * + * @return The active icon. + */ + public Icon getIcon() + { + return icon; + } + + /** + * This method changes the "icon" property. This icon (the active icon) will + * be the one displayed when the label is enabled. + * + * @param newIcon The active icon. + */ + public void setIcon(Icon newIcon) + { + if (icon != newIcon) + { + Icon oldIcon = icon; + icon = newIcon; + firePropertyChange("icon", oldIcon, newIcon); + } + } + + /** + * This method returns the disabled icon. The disabled icon is painted when + * the label is disabled. If the disabled icon is null and the active icon + * is an ImageIcon, this method returns a grayed version of the icon. The + * grayed version of the icon becomes the disabledIcon. + * + * @return The disabled icon. + */ + public Icon getDisabledIcon() + { + if (disabledIcon == null && icon instanceof ImageIcon) + disabledIcon = new ImageIcon(GrayFilter.createDisabledImage(((ImageIcon) icon) + .getImage())); + + return disabledIcon; + } + + /** + * This method changes the "disabledIcon" property. This icon (the disabled + * icon) will be the one displayed when the label is disabled. + * + * @param newIcon The disabled icon. + */ + public void setDisabledIcon(Icon newIcon) + { + if (disabledIcon != newIcon) + { + Icon oldIcon = disabledIcon; + disabledIcon = newIcon; + firePropertyChange("disabledIcon", oldIcon, newIcon); + } + } + + /** + * This method sets the keycode that will be the label's mnemonic. If the + * label is used as a label for another component, the label will give + * focus to that component when the mnemonic is activated. + * + * @param mnemonic The keycode to use for the mnemonic. + */ + public void setDisplayedMnemonic(int mnemonic) + { + if (displayedMnemonic != mnemonic) + { + firePropertyChange("displayedMnemonic", + displayedMnemonic, mnemonic); + displayedMnemonic = mnemonic; + + if (text != null) + setDisplayedMnemonicIndex(text.toUpperCase().indexOf(mnemonic)); + } + } + + /** + * This method sets the character that will be the mnemonic used. If the + * label is used as a label for another component, the label will give + * focus to that component when the mnemonic is activated. + * + * @param mnemonic The character to use for the mnemonic. + */ + public void setDisplayedMnemonic(char mnemonic) + { + setDisplayedMnemonic((int) Character.toUpperCase(mnemonic)); + } + + /** + * This method returns the keycode that is used for the label's mnemonic. + * + * @return The keycode that is used for the label's mnemonic. + */ + public int getDisplayedMnemonic() + { + return (int) displayedMnemonic; + } + + /** + * This method sets which character in the text will be the underlined + * character. If the given index is -1, then this indicates that there is + * no mnemonic. If the index is less than -1 or if the index is equal to + * the length, this method will throw an IllegalArgumentException. + * + * @param newIndex The index of the character to underline. + * + * @throws IllegalArgumentException If index less than -1 or index equals + * length. + */ + public void setDisplayedMnemonicIndex(int newIndex) + throws IllegalArgumentException + { + if (newIndex < -1 || (text != null && newIndex >= text.length())) + throw new IllegalArgumentException(); + + if (newIndex == -1 + || text == null + || text.charAt(newIndex) != displayedMnemonic) + newIndex = -1; + + if (newIndex != displayedMnemonicIndex) + { + int oldIndex = displayedMnemonicIndex; + displayedMnemonicIndex = newIndex; + firePropertyChange("displayedMnemonicIndex", + oldIndex, newIndex); + } + } + + /** + * This method returns which character in the text will be the underlined + * character. + * + * @return The index of the character that will be underlined. + */ + public int getDisplayedMnemonicIndex() + { + return displayedMnemonicIndex; + } + + /** + * This method ensures that the key is valid as a horizontal alignment. + * Valid keys are: LEFT, CENTER, RIGHT, LEADING, TRAILING + * + * @param key The key to check. + * @param message The message of the exception to be thrown if the key is + * invalid. + * + * @return The key if it's valid. + * + * @throws IllegalArgumentException If the key is invalid. + */ + protected int checkHorizontalKey(int key, String message) + { + if (key != LEFT && key != CENTER && key != RIGHT && key != LEADING + && key != TRAILING) + throw new IllegalArgumentException(message); + else + return key; + } + + /** + * This method ensures that the key is valid as a vertical alignment. Valid + * keys are: TOP, CENTER, and BOTTOM. + * + * @param key The key to check. + * @param message The message of the exception to be thrown if the key is + * invalid. + * + * @return The key if it's valid. + * + * @throws IllegalArgumentException If the key is invalid. + */ + protected int checkVerticalKey(int key, String message) + { + if (key != TOP && key != BOTTOM && key != CENTER) + throw new IllegalArgumentException(message); + else + return key; + } + + /** + * This method returns the gap between the icon and the text. + * + * @return The gap between the icon and the text. + */ + public int getIconTextGap() + { + return iconTextGap; + } + + /** + * This method changes the "iconTextGap" property. The iconTextGap + * determines how much space there is between the icon and the text. + * + * @param newGap The gap between the icon and the text. + */ + public void setIconTextGap(int newGap) + { + if (iconTextGap != newGap) + { + firePropertyChange("iconTextGap", iconTextGap, newGap); + iconTextGap = newGap; + } + } + + /** + * This method returns the vertical alignment of the label. + * + * @return The vertical alignment of the label. + */ + public int getVerticalAlignment() + { + return verticalAlignment; + } + + /** + * This method changes the "verticalAlignment" property of the label. The + * vertical alignment determines how where the label will be placed + * vertically. If the alignment is not valid, it will default to the + * center. + * + * @param alignment The vertical alignment of the label. + */ + public void setVerticalAlignment(int alignment) + { + if (alignment == verticalAlignment) + return; + + int oldAlignment = verticalAlignment; + verticalAlignment = checkVerticalKey(alignment, "verticalAlignment"); + firePropertyChange("verticalAlignment", oldAlignment, verticalAlignment); + } + + /** + * This method returns the horziontal alignment of the label. + * + * @return The horizontal alignment of the label. + */ + public int getHorizontalAlignment() + { + return horizontalAlignment; + } + + /** + * This method changes the "horizontalAlignment" property. The horizontal + * alignment determines where the label will be placed horizontally. + * + * @param alignment The horizontal alignment of the label. + */ + public void setHorizontalAlignment(int alignment) + { + if (horizontalAlignment == alignment) + return; + + int oldAlignment = horizontalAlignment; + horizontalAlignment = checkHorizontalKey(alignment, "horizontalAlignment"); + firePropertyChange("horizontalAlignment", oldAlignment, + horizontalAlignment); + } + + /** + * This method returns the vertical text position of the label. + * + * @return The vertical text position of the label. + */ + public int getVerticalTextPosition() + { + return verticalTextPosition; + } + + /** + * This method changes the "verticalTextPosition" property of the label. The + * vertical text position determines where the text will be placed + * vertically relative to the icon. + * + * @param textPosition The vertical text position. + */ + public void setVerticalTextPosition(int textPosition) + { + if (textPosition != verticalTextPosition) + { + int oldPos = verticalTextPosition; + verticalTextPosition = checkVerticalKey(textPosition, + "verticalTextPosition"); + firePropertyChange("verticalTextPosition", oldPos, + verticalTextPosition); + } + } + + /** + * This method returns the horizontal text position of the label. + * + * @return The horizontal text position. + */ + public int getHorizontalTextPosition() + { + return horizontalTextPosition; + } + + /** + * This method changes the "horizontalTextPosition" property of the label. + * The horizontal text position determines where the text will be placed + * horizontally relative to the icon. + * + * @param textPosition The horizontal text position. + */ + public void setHorizontalTextPosition(int textPosition) + { + if (textPosition != horizontalTextPosition) + { + int oldPos = horizontalTextPosition; + horizontalTextPosition = checkHorizontalKey(textPosition, + "horizontalTextPosition"); + firePropertyChange("horizontalTextPosition", oldPos, + horizontalTextPosition); + } + } + + /** + * This method simply returns false if the current icon image (current icon + * will depend on whether the label is enabled) is not equal to the passed + * in image. + * + * @param img The image to check. + * @param infoflags The bitwise inclusive OR of ABORT, ALLBITS, ERROR, + * FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, and WIDTH + * @param x The x position + * @param y The y position + * @param w The width + * @param h The height + * + * @return Whether the current icon image is equal to the image given. + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, + int h) + { + Icon currIcon = isEnabled() ? icon : disabledIcon; + + // XXX: Is this the correct way to check for image equality? + if (currIcon != null && currIcon instanceof ImageIcon) + return (((ImageIcon) currIcon).getImage() == img); + + return false; + } + + /** + * This method returns the component that the label gives focus to when the + * mnemonic is activated. + * + * @return The component that gets focus when the label's mnemonic is + * activated. + */ + public Component getLabelFor() + { + return labelFor; + } + + /** + * This method changes the "labelFor" property. The component that the label + * is acting as a label for will request focus when the label's mnemonic + * is activated. + * + * @param c The component that gets focus when the label's mnemonic is + * activated. + */ + public void setLabelFor(Component c) + { + if (c != labelFor) + { + Component oldLabelFor = labelFor; + labelFor = c; + firePropertyChange("labelFor", oldLabelFor, labelFor); + } + } + + /** + * This method overrides setFont so that we can call for a repaint after the + * font is changed. + * + * @param f The font for this label. + */ + public void setFont(Font f) + { + super.setFont(f); + repaint(); + } + + /** + * DOCUMENT ME! + * + * @return + */ + public AccessibleContext getAccessibleContext() + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/JLayeredPane.java b/libjava/classpath/javax/swing/JLayeredPane.java new file mode 100644 index 0000000..c9a4fd4 --- /dev/null +++ b/libjava/classpath/javax/swing/JLayeredPane.java @@ -0,0 +1,622 @@ +/* JLayeredPane.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; + +import javax.accessibility.Accessible; + +/** + *

The "Layered Pane" is a container which divides its children into 6 (or + * more) disjoint sets. the pre-defined sets are:

+ * + * + * + *

A child is in exactly one of these layers at any time, though there may + * be other layers if someone creates them.

+ * + *

The purpose of this class is to translate this view of "layers" into a + * contiguous array of components: the one held in our ancestor, + * {@link java.awt.Container}.

+ * + *

There is a precise set of words we will use to refer to numbers within + * this class:

+ * + *
+ *
Component Index:
+ *
An offset into the component array held in our ancestor, + * {@link java.awt.Container}, from [0 .. component.length). The drawing + * rule with indices is that 0 is drawn last.
+ * + *
Layer Number:
+ *
A general int specifying a layer within this component. Negative + * numbers are drawn first, then layer 0, then positive numbered layers, in + * ascending order.
+ * + *
Position:
+ *
An offset into a layer's "logical drawing order". Layer position 0 + * is drawn last. Layer position -1 is a synonym for the first layer + * position (the logical "bottom").
+ *
+ * + *

Note: the layer numbering order is the reverse of the + * component indexing and position order

+ * + * @author Graydon Hoare (graydon@redhat.com) + */ +public class JLayeredPane extends JComponent implements Accessible +{ + private static final long serialVersionUID = 5534920399324590459L; + + public static final String LAYER_PROPERTY = "layeredContainerLayer"; + + public static Integer FRAME_CONTENT_LAYER = new Integer (-30000); + + public static Integer DEFAULT_LAYER = new Integer (0); + public static Integer PALETTE_LAYER = new Integer (100); + public static Integer MODAL_LAYER = new Integer (200); + public static Integer POPUP_LAYER = new Integer (300); + public static Integer DRAG_LAYER = new Integer (400); + + TreeMap layers; // Layer Number (Integer) -> Layer Size (Integer) + Hashtable componentToLayer; // Component -> Layer Number (Integer) + + public JLayeredPane() + { + layers = new TreeMap (); + componentToLayer = new Hashtable (); + } + + + /** + * Looks up the layer a child component is currently assigned to. + * + * @param c the component to look up. + * @return the layer the component is currently assigned to, in this container. + * @throws IllegalArgumentException if the component is not a child of this container. + */ + public int getLayer(Component c) + { + Component myComp = c; + while(! componentToLayer.containsKey(myComp)) + { + myComp = myComp.getParent(); + if (myComp == null) + break; + } + if (myComp == null) + throw new IllegalArgumentException + ("component is not in this JLayeredPane"); + Integer layerObj = (Integer) componentToLayer.get(myComp); + return layerObj.intValue(); + } + + /** + * Looks up the layer of comp in the component's nearest + * JLayeredPane ancestor. If comp is not contained + * in a JLayeredPane, the value 0 (default layer) is returned. + * + * @param comp the component for which the layer is looked up + * + * @return the layer of comp in its nearest JLayeredPane + * ancestor + */ + public static int getLayer(JComponent comp) + { + JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass + (JLayeredPane.class, comp); + if (lp == null) + return 0; + else + // The cast here forces the call to the instance method getLayer() + // instead of the static method (this would lead to infinite + // recursion). + return lp.getLayer((Component) comp); + } + + /** + * Returns the first JLayeredPane that contains the Component + * comp or null if comp is + * not contained in a JLayeredPane. + * + * @param comp the component for which we are searching the JLayeredPane + * ancestor + * + * @return the first JLayeredPane that contains the Component + * comp or null if comp is + * not contained in a JLayeredPane + */ + public static JLayeredPane getLayeredPaneAbove(Component comp) + { + JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass + (JLayeredPane.class, comp); + return lp; + } + + /** + *

Returns a pair of ints representing a half-open interval + * [top, bottom), which is the range of component indices + * the provided layer number corresponds to.

+ * + *

Note that "bottom" is not included in the interval of + * component indices in this layer: a layer with 0 elements in it has + * ret[0] == ret[1].

+ * + * @param layer the layer to look up. + * @return the half-open range of indices this layer spans. + * @throws IllegalArgumentException if layer does not refer to an active layer + * in this container. + */ + private int[] layerToRange (Integer layer) + { + int[] ret = new int[2]; + 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()) + { + ret[0] = ret[1] - layerSz.intValue (); + return ret; + } + else + { + ret[1] -= layerSz.intValue (); + } + } + // should have found the layer during iteration + throw new IllegalArgumentException (); + } + + /** + * Increments the recorded size of a given layer. + * + * @param layer the layer number to increment. + * @see #incrLayer() + */ + private void incrLayer(Integer layer) + { + int sz = 1; + if (layers.containsKey (layer)) + sz += ((Integer)(layers.get (layer))).intValue (); + layers.put (layer, new Integer(sz)); + } + + /** + * Decrements the recorded size of a given layer. + * + * @param layer the layer number to decrement. + * @see #decrLayer() + */ + private void decrLayer(Integer layer) + { + int sz = 0; + if (layers.containsKey (layer)) + sz = ((Integer)(layers.get (layer))).intValue () - 1; + layers.put (layer, new Integer(sz)); + } + + /** + * Return the greatest layer number currently in use, in this container. + * This number may legally be positive or negative. + * + * @return the least layer number. + * @see #lowestLayer() + */ + public int highestLayer() + { + if (layers.size() == 0) + return 0; + return ((Integer)(layers.lastKey ())).intValue (); + } + + /** + * Return the least layer number currently in use, in this container. + * This number may legally be positive or negative. + * + * @return the least layer number. + * @see #highestLayer() + */ + public int lowestLayer() + { + if (layers.size() == 0) + return 0; + return ((Integer)(layers.firstKey ())).intValue (); + } + + /** + * Moves a component to the "front" of its layer. The "front" is a + * synonym for position 0, which is also the last position drawn in each + * layer, so is usually the component which occludes the most other + * components in its layer. + * + * @param c the component to move to the front of its layer. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #moveToBack() + */ + public void moveToFront(Component c) + { + setPosition (c, 0); + } + + /** + *

Moves a component to the "back" of its layer. The "back" is a + * synonym for position N-1 (also known as position -1), where N is the + * size of the layer.

+ * + *

The "back" of a layer is the first position drawn, so the component at + * the "back" is usually the component which is occluded by the most + * other components in its layer.

+ * + * @param c the component to move to the back of its layer. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #moveToFront() + */ + public void moveToBack(Component c) + { + setPosition (c, -1); + } + + /** + * Return the position of a component within its layer. Positions are assigned + * from the "front" (position 0) to the "back" (position N-1), and drawn from + * the back towards the front. + * + * @param c the component to get the position of. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #setPosition() + */ + public int getPosition(Component c) + { + int layer = getLayer (c); + int[] range = layerToRange(new Integer(layer)); + int top = range[0]; + int bot = range[1]; + Component[] comps = getComponents (); + for (int i = top; i < bot; ++i) + { + if (comps[i] == c) + return i - top; + } + // should have found it + throw new IllegalArgumentException (); + } + + /** + * Change the position of a component within its layer. Positions are assigned + * from the "front" (position 0) to the "back" (position N-1), and drawn from + * the back towards the front. + * + * @param c the component to change the position of. + * @param position the position to assign the component to. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #getPosition() + */ + public void setPosition(Component c, int position) + { + int layer = getLayer (c); + int[] range = layerToRange(new Integer(layer)); + if (range[0] == range[1]) + throw new IllegalArgumentException (); + + int top = range[0]; + int bot = range[1]; + if (position == -1) + position = (bot - top) - 1; + int targ = Math.min(top + position, bot-1); + int curr = -1; + + Component[] comps = getComponents(); + for (int i = top; i < bot; ++i) + { + if (comps[i] == c) + { + curr = i; + break; + } + } + if (curr == -1) + // should have found it + throw new IllegalArgumentException(); + + super.swapComponents (curr, targ); + revalidate(); + repaint(); + } + + /** + * Return an array of all components within a layer of this + * container. Components are ordered front-to-back, with the "front" + * element (which draws last) at position 0 of the returned array. + * + * @param layer the layer to return components from. + * @return the components in the layer. + */ + public Component[] getComponentsInLayer(int layer) + { + int[] range = layerToRange (getObjectForLayer (layer)); + if (range[0] == range[1]) + return new Component[0]; + else + { + Component[] comps = getComponents (); + int sz = range[1] - range[0]; + Component[] nc = new Component[sz]; + for (int i = 0; i < sz; ++i) + nc[i] = comps[range[0] + i]; + return nc; + } + } + + /** + * Return the number of components within a layer of this + * container. + * + * @param layer the layer count components in. + * @return the number of components in the layer. + */ + public int getComponentCountInLayer(int layer) + { + int[] range = layerToRange (getObjectForLayer (layer)); + if (range[0] == range[1]) + return 0; + else + return (range[1] - range[0]); + } + + /** + * Return a hashtable mapping child components of this container to + * Integer objects representing the component's layer assignments. + */ + protected Hashtable getComponentToLayer() + { + return componentToLayer; + } + + /** + * Return the index of a component within the underlying (contiguous) + * array of children. This is a "raw" number which does not represent the + * child's position in a layer, but rather its position in the logical + * drawing order of all children of the container. + * + * @param c the component to look up. + * @return the external index of the component. + * @throws IllegalArgumentException if the component is not a child of + * this container. + */ + public int getIndexOf(Component c) + { + int layer = getLayer (c); + int[] range = layerToRange(new Integer(layer)); + Component[] comps = getComponents(); + for (int i = range[0]; i < range[1]; ++i) + { + if (comps[i] == c) + return i; + } + // should have found the component during iteration + throw new IllegalArgumentException (); + } + + /** + * Return an Integer object which holds the same int value as the + * parameter. This is strictly an optimization to minimize the number of + * identical Integer objects which we allocate. + * + * @param layer the layer number as an int. + * @return the layer number as an Integer, possibly shared. + */ + protected Integer getObjectForLayer(int layer) + { + switch (layer) + { + case -30000: + return FRAME_CONTENT_LAYER; + + case 0: + return DEFAULT_LAYER; + + case 100: + return PALETTE_LAYER; + + case 200: + return MODAL_LAYER; + + case 300: + return POPUP_LAYER; + + case 400: + return DRAG_LAYER; + + default: + break; + } + + return new Integer(layer); + } + + /** + * Computes an index at which to request the superclass {@link + * java.awt.Container} inserts a component, given an abstract layer and + * position number. + * + * @param layer the layer in which to insert a component. + * @param position the position in the layer at which to insert a component. + * @return the index at which to insert the component. + */ + protected int insertIndexForLayer(int layer, int position) + { + + Integer lobj = getObjectForLayer (layer); + if (! layers.containsKey(lobj)) + layers.put (lobj, new Integer (0)); + int[] range = layerToRange (lobj); + if (range[0] == range[1]) + return range[0]; + + int top = range[0]; + int bot = range[1]; + + if (position == -1 || position > (bot - top)) + return bot; + else + return top + position; + } + + /** + * Removes a child from this container. The child is specified by + * index. After removal, the child no longer occupies a layer. + * + * @param index the index of the child component to remove. + */ + public void remove (int index) + { + Component c = getComponent (index); + int layer = getLayer (c); + decrLayer (new Integer(layer)); + componentToLayer.remove (c); + super.remove (index); + 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)); + } + + /** + *

Set the layer property for a component, within this container. The + * component will be implicitly mapped to the bottom-most position in the + * layer, but only if added after calling this method.

+ * + *

Read that carefully: this method should be called before the + * component is added to the container.

+ * + * @param c the component to set the layer property for. + * @param layer the layer number to assign to the component. + */ + public void setLayer(Component c, int layer) + { + componentToLayer.put (c, getObjectForLayer (layer)); + } + + /** + * Set the layer and position of a component, within this container. + * + * @param c the child component to set the layer property for. + * @param layer the layer number to assign to the component. + * @param position the position number to assign to the component. + */ + public void setLayer(Component c, + int layer, + int position) + { + remove(c); + add(c, getObjectForLayer (layer)); + setPosition(c, position); + revalidate(); + repaint(); + } + + /** + * Overrides the default implementation from {@link java.awt.Container} + * such that layerConstraint is interpreted as an {@link + * Integer}, specifying the layer to which the component will be added + * (at the bottom position). + * + * @param comp the component to add. + * @param layerConstraint an integer specifying the layer to add the component to. + * @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; + else if (componentToLayer.containsKey (comp)) + layer = (Integer) componentToLayer.remove (comp); + else + layer = DEFAULT_LAYER; + + int newIdx = insertIndexForLayer(layer.intValue (), index); + + componentToLayer.put (comp, layer); + incrLayer (layer); + + super.addImpl(comp, null, newIdx); + revalidate(); + repaint(); + } + + /** + * Sets the layer property for a JComponent. + * + * @param component the component for which to set the layer + * @param layer the layer property to set + */ + public static void putLayer(JComponent component, int layer) + { + getLayeredPaneAbove(component).setLayer(component, layer); + } +} diff --git a/libjava/classpath/javax/swing/JList.java b/libjava/classpath/javax/swing/JList.java new file mode 100644 index 0000000..fb8d18b --- /dev/null +++ b/libjava/classpath/javax/swing/JList.java @@ -0,0 +1,1416 @@ +/* JList.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.plaf.ListUI; +import javax.swing.text.Position; + +/** + *

This class is a facade over three separate objects: {@link + * javax.swing.ListModel}, {@link javax.swing.ListSelectionModel} and + * {@link javax.swing.plaf.ListUI}. The facade represents a unified "list" + * concept, with independently replacable (possibly client-provided) models + * for its contents and its current selection. In addition, each element in + * the list is rendered via a strategy class {@link + * javax.swing.ListCellRenderer}.

+ * + *

Lists have many properties, some of which are stored in this class + * while others are delegated to the list's model or selection. The + * following properties are available:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Property Stored inBound?
accessibleContext list no
anchorSelectionIndex selectionno
cellRenderer list yes
dragEnabled list no
firstVisibleIndex list no
fixedCellHeight list yes
fixedCellWidth list yes
lastVisibleIndex list no
layoutOrientation list yes
leadSelectionIndex selectionno
maxSelectionIndex selectionno
minSelectionIndex selectionno
model list yes
opaque list no
preferredScrollableViewportSizelist no
prototypeCellValue list yes
scrollableTracksViewportHeight list no
scrollableTracksViewportWidth list no
selectedIndex selectionno
selectedIndices selectionno
selectedValue model no
selectedValues model no
selectionBackground list yes
selectionEmpty selectionno
selectionForeground list yes
selectionMode selectionno
selectionModel list yes
UI list yes
UIClassID list no
valueIsAdjusting list no
visibleRowCount list no
+ * + * @author Graydon Hoare (graydon@redhat.com) + */ + +public class JList extends JComponent implements Accessible, Scrollable +{ + private static final long serialVersionUID = 4406629526391098046L; + + /** + * Constant value used in "layoutOrientation" property. This value means + * that cells are laid out in a single vertical column. This is the default. + */ + public static final int VERTICAL = 0; + + /** + * Constant value used in "layoutOrientation" property. This value means + * that cells are laid out in multiple columns "newspaper style", filling + * vertically first, then horizontally. + */ + public static final int VERTICAL_WRAP = 1; + + /** + * Constant value used in "layoutOrientation" property. This value means + * that cells are laid out in multiple columns "newspaper style", + * filling horizontally first, then vertically. + */ + public static final int HORIZONTAL_WRAP = 2; + + /** + * This property indicates whether "drag and drop" functions are enabled + * on the list. + */ + boolean dragEnabled; + + /** This property provides a strategy for rendering cells in the list. */ + ListCellRenderer cellRenderer; + + /** + * This property indicates an fixed width to assign to all cells in the + * list. If its value is -1, no width has been + * assigned. This value can be set explicitly, or implicitly by setting + * the {@link #prototypeCellValue} property. + */ + int fixedCellWidth; + + /** + * This property indicates an fixed height to assign to all cells in the + * list. If its value is -1, no height has been + * assigned. This value can be set explicitly, or implicitly by setting + * the {@link #prototypeCellValue} property. + */ + int fixedCellHeight; + + /** + * This property holds the current layout orientation of the list, which + * is one of the integer constants {@link #VERTICAL}, {@link + * #VERTICAL_WRAP}, or {@link #HORIZONTAL_WRAP}. + */ + int layoutOrientation; + + /** This property holds the data elements displayed by the list. */ + ListModel model; + + /** + *

This property holds a reference to a "prototype" data value -- + * typically a String -- which is used to calculate the {@link + * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the + * {@link #cellRenderer} property to acquire a component to render the + * prototype.

+ * + *

It is important that you not set this value to a + * component. It has to be a data value such as the objects you + * would find in the list's model. Setting it to a component will have + * undefined (and undesirable) affects.

+ */ + Object prototypeCellValue; + + /** + * This property specifies a foreground color for the selected cells in + * the list. When {@link ListCellRenderer.getListCellRendererComponent} + * is called with a selected cell object, the component returned will + * have its "foreground" set to this color. + */ + Color selectionBackground; + + /** + * This property specifies a background color for the selected cells in + * 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. + */ + Color selectionForeground; + + /** + * This property holds a description of which data elements in the {@link + * #model} property should be considered "selected", when displaying and + * interacting with the list. + */ + ListSelectionModel selectionModel; + + + /** + * This property indicates that the list's selection is currently + * "adjusting" -- perhaps due to a user actively dragging the mouse over + * multiple list elements -- and is therefore likely to change again in + * the near future. A {@link ListSelectionListener} might choose to delay + * updating its view of the list's selection until this property is + * false, meaning that the adjustment has completed. + */ + boolean valueIsAdjusting; + + /** + * This property indicates a preference for the number of rows + * displayed in the list, and will scale the + * {@link #preferredScrollableViewportSize} 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. + */ + int visibleRowCount; + + /** + * Fire a {@link ListSelectionEvent} to all the registered ListSelectionListeners. + */ + protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) + { + ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, lastIndex, isAdjusting); + ListSelectionListener listeners[] = getListSelectionListeners(); + for (int i = 0; i < listeners.length; ++i) + { + listeners[i].valueChanged(evt); + } + } + + /** + * This private listener propagates {@link ListSelectionEvent} events + * from the list's "selectionModel" property to the list's {@link + * ListSelectionListener} listeners. It also listens to {@link + * ListDataEvent} events from the list's {@link #model} property. If this + * class receives either type of event, it triggers repainting of the + * list. + */ + private class ListListener + implements ListSelectionListener, ListDataListener + { + // ListDataListener events + public void contentsChanged(ListDataEvent event) + { + JList.this.revalidate(); + JList.this.repaint(); + } + public void intervalAdded(ListDataEvent event) + { + JList.this.revalidate(); + JList.this.repaint(); + } + public void intervalRemoved(ListDataEvent event) + { + JList.this.revalidate(); + JList.this.repaint(); + } + // ListSelectionListener events + public void valueChanged(ListSelectionEvent event) + { + JList.this.fireSelectionValueChanged(event.getFirstIndex(), + event.getLastIndex(), + event.getValueIsAdjusting()); + JList.this.repaint(); + } + }; + + /** + * Shared ListListener instance, subscribed to both the current {@link + * #model} and {@link #selectionModel} properties of the list. + */ + ListListener listListener; + + + /** + * Creates a new JList object. + */ + public JList() + { + init(); + } + + /** + * Creates a new JList object. + * + * @param listData Initial data to populate the list with + */ + public JList(Object[] listData) + { + init(); + setListData(listData); + } + + /** + * Creates a new JList object. + * + * @param listData Initial data to populate the list with + */ + public JList(Vector listData) + { + init(); + setListData(listData); + } + + /** + * Creates a new JList object. + * + * @param listData Initial data to populate the list with + */ + public JList(ListModel listData) + { + init(); + setModel(listData); + } + + void init() + { + dragEnabled = false; + fixedCellHeight = -1; + fixedCellWidth = -1; + layoutOrientation = VERTICAL; + opaque = true; + valueIsAdjusting = false; + visibleRowCount = 8; + + cellRenderer = new DefaultListCellRenderer(); + listListener = new ListListener(); + + setModel(new DefaultListModel()); + setSelectionModel(createSelectionModel()); + + updateUI(); + } + + /** + * Creates the default ListSelectionModel. + * + * @return the ListSelectionModel + */ + protected ListSelectionModel createSelectionModel() + { + return new DefaultListSelectionModel(); + } + + /** + * Gets the value of the {@link #fixedCellHeight} property. This property + * may be -1 to indicate that no cell height has been + * set. This property is also set implicitly when the + * {@link #prototypeCellValue} property is set. + * + * @return The current value of the property + * + * @see #fixedCellHeight + * @see #setFixedCellHeight + * @see #setPrototypeCellValue + */ + public int getFixedCellHeight() + { + return fixedCellHeight; + } + + /** + * Sets the value of the {@link #fixedCellHeight} property. This property + * may be -1 to indicate that no cell height has been + * set. This property is also set implicitly when the {@link + * #prototypeCellValue} property is set, but setting it explicitly + * overrides the height computed from {@link #prototypeCellValue}. + * + * @see #getFixedCellHeight + * @see #getPrototypeCellValue + */ + public void setFixedCellHeight(int h) + { + if (fixedCellHeight == h) + return; + + int old = fixedCellHeight; + fixedCellHeight = h; + firePropertyChange("fixedCellWidth", old, h); + } + + + /** + * Gets the value of the {@link #fixedCellWidth} property. This property + * may be -1 to indicate that no cell width has been + * set. This property is also set implicitly when the {@link + * #prototypeCellValue} property is set. + * + * @return The current value of the property + * + * @see #setFixedCellWidth + * @see #setPrototypeCellValue + */ + public int getFixedCellWidth() + { + return fixedCellWidth; + } + + /** + * Sets the value of the {@link #fixedCellWidth} property. This property + * may be -1 to indicate that no cell width has been + * set. This property is also set implicitly when the {@link + * #prototypeCellValue} property is set, but setting it explicitly + * overrides the width computed from {@link #prototypeCellValue}. + * + * @see #getFixedCellHeight + * @see #getPrototypeCellValue + */ + public void setFixedCellWidth(int w) + { + if (fixedCellWidth == w) + return; + + int old = fixedCellWidth; + fixedCellWidth = w; + firePropertyChange("fixedCellWidth", old, w); + } + + /** + * Gets the value of the {@link #visibleRowCount} property. + * + * @return the current value of the property. + */ + + public int getVisibleRowCount() + { + return visibleRowCount; + } + + /** + * Sets the value of the {@link #visibleRowCount} property. + * + * @param visibleRowCount The new property value + */ + public void setVisibleRowCount(int vc) + { + visibleRowCount = vc; + revalidate(); + repaint(); + } + + /** + * Adds a {@link ListSelectionListener} to the listener list for this + * list. The listener will be called back with a {@link + * ListSelectionEvent} any time the list's {@link #selectionModel} + * property changes. The source of such events will be the JList, + * not the selection model. + * + * @param listener The new listener to add + */ + public void addListSelectionListener(ListSelectionListener listener) + { + listenerList.add (ListSelectionListener.class, listener); + } + + /** + * Removes a {@link ListSelectionListener} from the listener list for + * this list. The listener will no longer be called when the list's + * {@link #selectionModel} changes. + * + * @param listener The listener to remove + */ + public void removeListSelectionListener(ListSelectionListener listener) + { + listenerList.remove(ListSelectionListener.class, listener); + } + + /** + * Returns an array of all ListSelectionListeners subscribed to this + * list. + * + * @return The current subscribed listeners + * + * @since 1.4 + */ + public ListSelectionListener[] getListSelectionListeners() + { + return (ListSelectionListener[]) getListeners(ListSelectionListener.class); + } + + public int getSelectionMode() + { + return selectionModel.getSelectionMode(); + } + + /** + * Sets the list's "selectionMode" property, which simply mirrors the + * same property on the list's {@link #selectionModel} property. This + * property should be one of the integer constants + * SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, + * or MULTIPLE_INTERVAL_SELECTION from the {@link + * ListSelectionModel} interface. + * + * @param a The new selection mode + */ + public void setSelectionMode(int a) + { + selectionModel.setSelectionMode(a); + } + + /** + * Adds the interval [a,a] to the set of selections managed + * by this list's {@link #selectionModel} property. Depending on the + * selection mode, this may cause existing selections to become invalid, + * or may simply expand the set of selections. + * + * @param a A number in the half-open range [0, x) where + * x = getModel.getSize(), indicating the index of an + * element in the list to select. + * + * @see #setSelectionMode + * @see #selectionModel + */ + public void setSelectedIndex(int a) + { + selectionModel.setSelectionInterval(a, a); + } + + /** + * For each element a[i] of the provided array + * a, calls {@link #setSelectedIndex} on a[i]. + * + * @see #setSelectionMode + * @see #selectionModel + */ + public void setSelectedIndices(int [] a) + { + for (int i = 0; i < a.length; ++i) + setSelectedIndex(a[i]); + } + + /** + * Returns the minimum index of an element in the list which is currently + * selected. + * + * @return A number in the half-open range [0, x) where + * x = getModel.getSize(), indicating the minimum index of + * an element in the list for which the element is selected, or + * -1 if no elements are selected + */ + public int getSelectedIndex() + { + return selectionModel.getMinSelectionIndex(); + } + + /** + * Returns true if the model's selection is empty, otherwise + * false. + * + * @return The return value of {@link ListSelectionModel#isSelectionEmpty} + */ + public boolean isSelectionEmpty() + { + return selectionModel.isSelectionEmpty(); + } + + /** + * Returns the list index of the upper left or upper right corner of the + * {@link #visibleRect} property, depending on the {@link + * #componentOrientation} property. + * + * @return The index of the first visible list cell, or -1 + * if none is visible. + */ + public int getFirstVisibleIndex() + { + ComponentOrientation or = getComponentOrientation(); + Rectangle r = getVisibleRect(); + if (or == ComponentOrientation.RIGHT_TO_LEFT) + r.translate((int) r.getWidth(), 0); + return getUI().locationToIndex(this, r.getLocation()); + } + + + /** + * Returns index of the cell to which specified location is closest to + * @param location for which to look for in the list + * + * @return index of the cell to which specified location is closest to. + */ + public int locationToIndex(Point location) { + return getUI().locationToIndex(this, location); + } + + /** + * Returns location of the cell located at the specified index in the list. + * @param index of the cell for which location will be determined + * + * @return location of the cell located at the specified index in the list. + */ + public Point indexToLocation(int index){ + //FIXME: Need to implement. + return null; + } + + /** + * Returns the list index of the lower right or lower left corner of the + * {@link #visibleRect} property, depending on the {@link + * #componentOrientation} property. + * + * @return The index of the first visible list cell, or -1 + * if none is visible. + */ + public int getLastVisibleIndex() + { + ComponentOrientation or = getComponentOrientation(); + Rectangle r = getVisibleRect(); + r.translate(0, (int) r.getHeight()); + if (or == ComponentOrientation.LEFT_TO_RIGHT) + r.translate((int) r.getWidth(), 0); + return getUI().locationToIndex(this, r.getLocation()); + } + + /** + * Returns the indices of values in the {@link #model} property which are + * selected. + * + * @return An array of model indices, each of which is selected according + * to the {@link #selection} property + */ + public int[] getSelectedIndices() + { + int lo, hi, n, i, j; + if (selectionModel.isSelectionEmpty()) + return new int[0]; + lo = selectionModel.getMinSelectionIndex(); + hi = selectionModel.getMaxSelectionIndex(); + n = 0; + for (i = lo; i <= hi; ++i) + if (selectionModel.isSelectedIndex(i)) + n++; + int [] v = new int[n]; + j = 0; + for (i = lo; i < hi; ++i) + if (selectionModel.isSelectedIndex(i)) + v[j++] = i; + return v; + } + + /** + * Indicates whether the list element at a given index value is + * currently selected. + * + * @param a The index to check + * @return true if a is the index of a selected + * list element + */ + public boolean isSelectedIndex(int a) + { + return selectionModel.isSelectedIndex(a); + } + + /** + * Returns the first value in the list's {@link #model} property which is + * selected, according to the list's {@link #selectionModel} property. + * This is equivalent to calling + * getModel()getElementAt(getSelectedIndex()), with a check + * for the special index value of -1 which returns null + * null. + * + * @return The first selected element, or null if no element + * is selected. + * + * @see getSelectedValues + */ + public Object getSelectedValue() + { + int index = getSelectedIndex(); + if (index == -1) + return null; + return getModel().getElementAt(index); + } + + /** + * Returns all the values in the list's {@link #model} property which + * are selected, according to the list's {@link #selectionModel} property. + * + * @return An array containing all the selected values + * + * @see getSelectedValue + */ + public Object[] getSelectedValues() + { + int [] idx = getSelectedIndices(); + Object [] v = new Object[idx.length]; + for (int i = 0; i < idx.length; ++i) + v[i] = getModel().getElementAt(i); + return v; + } + + /** + * Gets the value of the {@link #selectionBackground} property. + * + * @return The current value of the property + */ + public Color getSelectionBackground() + { + return selectionBackground; + } + + /** + * Sets the value of the {@link #selectionBackground} property. + * + * @param c The new value of the property + */ + public void setSelectionBackground(Color c) + { + if (selectionBackground == c) + return; + + Color old = selectionBackground; + selectionBackground = c; + firePropertyChange("selectionBackground", old, c); + repaint(); + } + + /** + * Gets the value of the {@link #selectionForeground} property. + * + * @return The current value of the property + */ + public Color getSelectionForeground() + { + return selectionForeground; + } + + /** + * Sets the value of the {@link #selectionForeground} property. + * + * @param c The new value of the property + */ + public void setSelectionForeground(Color c) + { + if (selectionForeground == c) + return; + + Color old = selectionForeground; + selectionForeground = c; + firePropertyChange("selectionForeground", old, c); + } + + /** + * Sets the selection to cover only the specified value, if it + * exists in the model. + * + * @param obj The object to select + * @param scroll Whether to scroll the list to make the newly selected + * value visible + * + * @see #ensureIndexIsVisible + */ + + public void setSelectedValue(Object obj, boolean scroll) + { + for (int i = 0; i < model.getSize(); ++i) + { + if (model.getElementAt(i).equals(obj)) + { + setSelectedIndex(i); + if (scroll) + ensureIndexIsVisible(i); + break; + } + } + } + + /** + * Scrolls this list to make the specified cell visible. This + * only works if the list is contained within a viewport. + * + * @param i The list index to make visible + * + * @see JComponent#scrollRectToVisible + */ + public void ensureIndexIsVisible(int i) + { + scrollRectToVisible(getUI().getCellBounds(this, i, i)); + } + + /** + * Sets the {@link #model} property of the list to a new anonymous + * {@link AbstractListModel} subclass which accesses the provided Object + * array directly. + * + * @param listData The object array to build a new list model on + * @see #setModel + */ + public void setListData(final Object[] listData) + { + setModel(new AbstractListModel() + { + public int getSize() + { + return listData.length; + } + + public Object getElementAt(int i) + { + return listData[i]; + } + }); + } + + /** + * Sets the {@link #model} property of the list to a new anonymous {@link + * AbstractListModel} subclass which accesses the provided vector + * directly. + * + * @param listData The object array to build a new list model on + * @see #setModel + */ + public void setListData(final Vector listData) + { + setModel(new AbstractListModel() + { + public int getSize() + { + return listData.size(); + } + + public Object getElementAt(int i) + { + return listData.elementAt(i); + } + }); + } + + /** + * Gets the value of the {@link #cellRenderer} property. + * + * @return The current value of the property + */ + public ListCellRenderer getCellRenderer() + { + return cellRenderer; + } + + /** + * Sets the value of the {@link #celLRenderer} property. + * + * @param renderer The new property value + */ + public void setCellRenderer(ListCellRenderer renderer) + { + if (cellRenderer == renderer) + return; + + ListCellRenderer old = cellRenderer; + cellRenderer = renderer; + firePropertyChange("cellRenderer", old, renderer); + revalidate(); + repaint(); + } + + /** + * Gets the value of the {@link #model} property. + * + * @return The current value of the property + */ + public ListModel getModel() + { + return model; + } + + /** + * Sets the value of the {@link #model} property. The list's {@link + * #listListener} is unsubscribed from the existing model, if it exists, + * and re-subscribed to the new model. + * + * @param model The new property value + */ + public void setModel(ListModel model) + { + if (this.model == model) + return; + + if (this.model != null) + this.model.removeListDataListener(listListener); + + ListModel old = this.model; + this.model = model; + + if (this.model != null) + this.model.addListDataListener(listListener); + + firePropertyChange("model", old, model); + revalidate(); + repaint(); + } + + + public ListSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * Sets the value of the {@link #selectionModel} property. The list's + * {@link #listListener} is unsubscribed from the existing selection + * model, if it exists, and re-subscribed to the new selection model. + * + * @param model The new property value + */ + public void setSelectionModel(ListSelectionModel model) + { + if (selectionModel == model) + return; + + if (selectionModel != null) + selectionModel.removeListSelectionListener(listListener); + + ListSelectionModel old = selectionModel; + selectionModel = model; + + if (selectionModel != null) + selectionModel.addListSelectionListener(listListener); + + firePropertyChange("selectionModel", old, model); + revalidate(); + repaint(); + } + + /** + * Gets the value of the UI property. + * + * @return The current property value + */ + public ListUI getUI() + { + return (ListUI) ui; + } + + /** + * Sets the value of the UI property. + * + * @param ui The new property value + */ + public void setUI(ListUI ui) + { + super.setUI(ui); + } + + /** + * Calls {@link #setUI} with the {@link ListUI} subclass + * returned from calling {@link UIManager#getUI}. + */ + public void updateUI() + { + setUI((ListUI) UIManager.getUI(this)); + } + + /** + * Return the class identifier for the list's UI property. This should + * be the constant string "ListUI", and map to an + * appropriate UI class in the {@link UIManager}. + * + * @return The class identifier + */ + public String getUIClassID() + { + return "ListUI"; + } + + + /** + * Returns the current value of the {@link #prototypeCellValue} + * property. This property holds a reference to a "prototype" data value + * -- typically a String -- which is used to calculate the {@link + * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the + * {@link #cellRenderer} property to acquire a component to render the + * prototype. + * + * @return The current prototype cell value + * @see #setPrototypeCellValue + */ + public Object getPrototypeCellValue() + { + return prototypeCellValue; + } + + /** + *

Set the {@link #prototypeCellValue} property. This property holds a + * reference to a "prototype" data value -- typically a String -- which + * is used to calculate the {@link #fixedCellWidth} and {@link + * #fixedCellHeight} properties, using the {@link #cellRenderer} property + * to acquire a component to render the prototype.

+ * + *

It is important that you not set this value to a + * component. It has to be a data value such as the objects you + * would find in the list's model. Setting it to a component will have + * undefined (and undesirable) affects.

+ * + * @param obj The new prototype cell value + * @see #getPrototypeCellValue + */ + public void setPrototypeCellValue(Object obj) + { + if (prototypeCellValue == obj) + return; + + Object old = prototypeCellValue; + Component comp = getCellRenderer() + .getListCellRendererComponent(this, obj, 0, false, false); + Dimension d = comp.getPreferredSize(); + fixedCellWidth = d.width; + fixedCellHeight = d.height; + prototypeCellValue = obj; + firePropertyChange("prototypeCellValue", old, obj); + } + + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * 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. + * + * @return The preferred size + */ + public Dimension getPreferredScrollableViewportSize() + { + + Dimension retVal = getPreferredSize(); + if (getLayoutOrientation() == VERTICAL) + { + if (fixedCellHeight != -1) + { + if (fixedCellWidth != -1) + { + int size = getModel().getSize(); + retVal = new Dimension(fixedCellWidth, size * fixedCellHeight); + } // TODO: add else clause (preferredSize is ok for now) + } // TODO: add else clause (preferredSize is ok for now) + } + return retVal; + } + + /** + *

Return the number of pixels the list must scroll in order to move a + * "unit" of the list into the provided visible rectangle. When the + * provided direction is positive, the call describes a "downwards" + * scroll, which will be exposing a cell at a greater index in + * the list than those elements currently showing. Then the provided + * direction is negative, the call describes an "upwards" scroll, which + * will be exposing a cell at a lesser index in the list than + * those elements currently showing.

+ * + *

If the provided orientation is HORIZONTAL, the above + * comments refer to "rightwards" for positive direction, and "leftwards" + * for negative.

+ * + * + * @param visibleRect The rectangle to scroll an element into + * @param orientation One of the numeric consants VERTICAL + * or HORIZONTAL + * @param direction An integer indicating the scroll direction: positive means + * forwards (down, right), negative means backwards (up, left) + * + * @return The scrollable unit increment, in pixels + */ + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, int direction) + { + ListUI lui = this.getUI(); + if (orientation == SwingConstants.VERTICAL) + { + if (direction > 0) + { + // Scrolling down + Point bottomLeft = new Point(visibleRect.x, + visibleRect.y + visibleRect.height); + int curIdx = lui.locationToIndex(this, bottomLeft); + Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx); + if (curBounds.y + curBounds.height == bottomLeft.y) + { + // we are at the exact bottom of the current cell, so we + // are being asked to scroll to the end of the next one + if (curIdx + 1 < model.getSize()) + { + // there *is* a next item in the list + Rectangle nxtBounds = lui.getCellBounds(this, curIdx + 1, curIdx + 1); + return nxtBounds.height; + } + else + { + // no next item, no advance possible + return 0; + } + } + else + { + // we are part way through an existing cell, so we are being + // asked to scroll to the bottom of it + return (curBounds.y + curBounds.height) - bottomLeft.y; + } + } + else + { + // scrolling up + Point topLeft = new Point(visibleRect.x, visibleRect.y); + int curIdx = lui.locationToIndex(this, topLeft); + Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx); + if (curBounds.y == topLeft.y) + { + // we are at the exact top of the current cell, so we + // are being asked to scroll to the top of the previous one + if (curIdx > 0) + { + // there *is* a previous item in the list + Rectangle nxtBounds = lui.getCellBounds(this, curIdx - 1, curIdx - 1); + return -nxtBounds.height; + } + else + { + // no previous item, no advance possible + return 0; + } + } + else + { + // we are part way through an existing cell, so we are being + // asked to scroll to the top of it + return curBounds.y - topLeft.y; + } + } + } + + // FIXME: handle horizontal scrolling (also wrapping?) + return 1; + } + + /** + *

Return the number of pixels the list must scroll in order to move a + * "block" of the list into the provided visible rectangle. When the + * provided direction is positive, the call describes a "downwards" + * scroll, which will be exposing a cell at a greater index in + * the list than those elements currently showing. Then the provided + * direction is negative, the call describes an "upwards" scroll, which + * will be exposing a cell at a lesser index in the list than + * those elements currently showing.

+ * + *

If the provided orientation is HORIZONTAL, the above + * comments refer to "rightwards" for positive direction, and "leftwards" + * for negative.

+ * + * + * @param visibleRect The rectangle to scroll an element into + * @param orientation One of the numeric consants VERTICAL + * or HORIZONTAL + * @param direction An integer indicating the scroll direction: positive means + * forwards (down, right), negative means backwards (up, left) + * + * @return The scrollable unit increment, in pixels + */ + public int getScrollableBlockIncrement(Rectangle visibleRect, + int orientation, int direction) + { + if (orientation == VERTICAL) + return visibleRect.height * direction; + else + return visibleRect.width * direction; + } + + /** + * Gets the value of the {@link #scrollableTracksViewportWidth} property. + * + * @return true if the viewport is larger (horizontally) + * than the list and the list should be expanded to fit the viewport; + * false if the viewport is smaller than the list and the + * list should scroll (horizontally) within the viewport + */ + public boolean getScrollableTracksViewportWidth() + { + Component parent = getParent(); + boolean retVal = false; + if (parent instanceof JViewport) + { + JViewport viewport = (JViewport) parent; + Dimension pref = getPreferredSize(); + if (viewport.getSize().width > pref.width) + retVal = true; + if ((getLayoutOrientation() == HORIZONTAL_WRAP) + && (getVisibleRowCount() <= 0)) + retVal = true; + } + return retVal; + } + + /** + * Gets the value of the {@link #scrollableTracksViewportWidth} property. + * + * @return true if the viewport is larger (vertically) + * than the list and the list should be expanded to fit the viewport; + * false if the viewport is smaller than the list and the + * list should scroll (vertically) within the viewport + */ + public boolean getScrollableTracksViewportHeight() + { + Component parent = getParent(); + boolean retVal = false; + if (parent instanceof JViewport) + { + JViewport viewport = (JViewport) parent; + Dimension pref = getPreferredSize(); + if (viewport.getSize().height > pref.height) + retVal = true; + if ((getLayoutOrientation() == VERTICAL_WRAP) + && (getVisibleRowCount() <= 0)) + retVal = true; + } + return retVal; + } + + public int getAnchorSelectionIndex() + { + return selectionModel.getAnchorSelectionIndex(); + } + + public int getLeadSelectionIndex() + { + return selectionModel.getLeadSelectionIndex(); + } + + public int getMinSelectionIndex() + { + return selectionModel.getMaxSelectionIndex(); + } + + public int getMaxSelectionIndex() + { + return selectionModel.getMaxSelectionIndex(); + } + + public void clearSelection() + { + selectionModel.clearSelection(); + } + + public void setSelectionInterval(int anchor, int lead) + { + selectionModel.setSelectionInterval(anchor, lead); + } + + public void addSelectionInterval(int anchor, int lead) + { + selectionModel.addSelectionInterval(anchor, lead); + } + + public void removeSelectionInterval(int index0, int index1) + { + selectionModel.removeSelectionInterval(index0, index1); + } + + /** + * Returns the value of the valueIsAdjusting property. + * + * @return the value + */ + public boolean getValueIsAdjusting() + { + return valueIsAdjusting; + } + + /** + * Sets the valueIsAdjusting property. + * + * @param isAdjusting the new value + */ + public void setValueIsAdjusting(boolean isAdjusting) + { + valueIsAdjusting = isAdjusting; + } + + /** + * Return the value of the dragEnabled property. + * + * @return the value + * + * @since 1.4 + */ + public boolean getDragEnabled() + { + return dragEnabled; + } + + /** + * Set the dragEnabled property. + * + * @param enabled new value + * + * @since 1.4 + */ + public void setDragEnabled(boolean enabled) + { + dragEnabled = enabled; + } + + /** + * Returns the layout orientation. + * + * @return the orientation, one of JList.VERTICAL, + * JList.VERTICAL_WRAP and JList.HORIZONTAL_WRAP + * + * @since 1.4 + */ + public int getLayoutOrientation() + { + return layoutOrientation; + } + + /** + * Sets the layout orientation. + * + * @param orientation the orientation to set, one of JList.VERTICAL, + * JList.VERTICAL_WRAP and JList.HORIZONTAL_WRAP + * + * @since 1.4 + */ + public void setLayoutOrientation(int orientation) + { + if (layoutOrientation == orientation) + return; + + int old = layoutOrientation; + layoutOrientation = orientation; + firePropertyChange("layoutOrientation", old, orientation); + } + + /** + * Returns the bounds of the rectangle that encloses both list cells + * with index0 and index1. + * + * @param index0 the index of the first cell + * @param index1 the index of the second cell + * + * @return the bounds of the rectangle that encloses both list cells + * with index0 and index1, null if one of the indices is + * not valid + */ + public Rectangle getCellBounds(int index0, int index1) + { + return ((ListUI) ui).getCellBounds(this, index0, index1); + } + + /** + * Returns the next list element (beginning from startIndex + * that starts with prefix. Searching is done in the direction + * specified by bias. + * + * @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} + * + * @return the index of the found element or -1 if no such element has + * been found + * + * @throws IllegalArgumentException if prefix is null or + * startIndex is not valid + * + * @since 1.4 + */ + public int getNextMatch(String prefix, int startIndex, Position.Bias bias) + { + if (prefix == null) + throw new IllegalArgumentException("The argument 'prefix' must not be" + + " null."); + if (startIndex < 0) + throw new IllegalArgumentException("The argument 'startIndex' must not" + + " be less than zero."); + + int size = model.getSize(); + if (startIndex > model.getSize()) + throw new IllegalArgumentException("The argument 'startIndex' must not" + + " be greater than the number of" + + " elements in the ListModel."); + + int index = -1; + if (bias == Position.Bias.Forward) + { + for (int i = startIndex; i < size; i++) + { + String item = model.getElementAt(i).toString(); + if (item.startsWith(prefix)) + { + index = i; + break; + } + } + } + else + { + for (int i = startIndex; i >= 0; i--) + { + String item = model.getElementAt(i).toString(); + if (item.startsWith(prefix)) + { + index = i; + break; + } + } + } + return index; + } +} diff --git a/libjava/classpath/javax/swing/JMenu.java b/libjava/classpath/javax/swing/JMenu.java new file mode 100644 index 0000000..8dcad8b --- /dev/null +++ b/libjava/classpath/javax/swing/JMenu.java @@ -0,0 +1,915 @@ +/* JMenu.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Point; +import java.awt.event.KeyEvent; +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; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import javax.swing.plaf.MenuItemUI; + +/** + * This class represents a menu that can be added to a menu bar or + * can be a submenu in some other menu. When JMenu is selected it + * displays JPopupMenu containing its menu items. + * + *

+ * JMenu's fires MenuEvents when this menu's selection changes. If this menu + * is selected, then fireMenuSelectedEvent() is invoked. In case when menu is + * deselected or cancelled, then fireMenuDeselectedEvent() or + * fireMenuCancelledEvent() is invoked, respectivelly. + *

+ */ +public class JMenu extends JMenuItem implements Accessible, MenuElement +{ + private static final long serialVersionUID = 4227225638931828014L; + + /** A Popup menu associated with this menu, which pops up when menu is selected */ + private JPopupMenu popupMenu = new JPopupMenu(); + + /** Whenever menu is selected or deselected the MenuEvent is fired to + menu's registered listeners. */ + private MenuEvent menuEvent = new MenuEvent(this); + + /*Amount of time, in milliseconds, that should pass before popupMenu + associated with this menu appears or disappers */ + private int delay; + + /* PopupListener */ + protected WinListener popupListener; + + /** Location at which popup menu associated with this menu will be + displayed */ + private Point menuLocation; + + /** + * Creates a new JMenu object. + */ + public JMenu() + { + super(); + } + + /** + * Creates a new JMenu with the specified label. + * + * @param text label for this menu + */ + public JMenu(String text) + { + super(text); + popupMenu.setInvoker(this); + } + + /** + * Creates a new JMenu object. + * + * @param action Action that is used to create menu item tha will be + * added to the menu. + */ + public JMenu(Action action) + { + super(action); + createActionChangeListener(this); + popupMenu.setInvoker(this); + } + + /** + * Creates a new JMenu with specified label and an option + * for this menu to be tear-off menu. + * + * @param text label for this menu + * @param tearoff true if this menu should be tear-off and false otherwise + */ + public JMenu(String text, boolean tearoff) + { + // FIXME: tearoff not implemented + this(text); + } + + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * Adds specified menu item to this menu + * + * @param item Menu item to add to this menu + * + * @return Menu item that was added + */ + public JMenuItem add(JMenuItem item) + { + return popupMenu.add(item); + } + + /** + * Adds specified component to this menu. + * + * @param component Component to add to this menu + * + * @return Component that was added + */ + public Component add(Component component) + { + popupMenu.insert(component, -1); + return component; + } + + /** + * Adds specified component to this menu at the given index + * + * @param component Component to add + * @param index Position of this menu item in the menu + * + * @return Component that was added + */ + public Component add(Component component, int index) + { + return popupMenu.add(component, index); + } + + /** + * Adds JMenuItem constructed with the specified label to this menu + * + * @param text label for the menu item that will be added + * + * @return Menu Item that was added to this menu + */ + public JMenuItem add(String text) + { + return popupMenu.add(text); + } + + /** + * Adds JMenuItem constructed using properties from specified action. + * + * @param action action to construct the menu item with + * + * @return Menu Item that was added to this menu + */ + public JMenuItem add(Action action) + { + return popupMenu.add(action); + } + + /** + * Removes given menu item from this menu. Nothing happens if + * this menu doesn't contain specified menu item. + * + * @param item Menu Item which needs to be removed + */ + public void remove(JMenuItem item) + { + popupMenu.remove(item); + } + + /** + * Removes component at the specified index from this menu + * + * @param index Position of the component that needs to be removed in the menu + */ + public void remove(int index) + { + popupMenu.remove(index); + } + + /** + * Removes given component from this menu. + * + * @param component Component to remove + */ + public void remove(Component component) + { + int index = popupMenu.getComponentIndex(component); + popupMenu.remove(index); + } + + /** + * Removes all menu items from the menu + */ + public void removeAll() + { + popupMenu.removeAll(); + } + + /** + * Creates JMenuItem with the specified text and inserts it in the + * at the specified index + * + * @param text label for the new menu item + * @param index index at which to insert newly created menu item. + */ + public void insert(String text, int index) + { + this.insert(new JMenuItem(text), index); + } + + /** + * Creates JMenuItem with the specified text and inserts it in the + * at the specified index. IllegalArgumentException is thrown + * if index is less than 0 + * + * @param item menu item to insert + * @param index index at which to insert menu item. + * @return Menu item that was added to the menu + */ + public JMenuItem insert(JMenuItem item, int index) + { + if (index < 0) + throw new IllegalArgumentException("index less than zero"); + + popupMenu.insert(item, index); + return item; + } + + /** + * Creates JMenuItem with the associated action and inserts it to the menu + * at the specified index. IllegalArgumentException is thrown + * if index is less than 0 + * + * @param action Action for the new menu item + * @param index index at which to insert newly created menu item. + * @return Menu item that was added to the menu + */ + public JMenuItem insert(Action action, int index) + { + JMenuItem item = new JMenuItem(action); + this.insert(item, index); + + return item; + } + + /** + * This method sets this menuItem's UI to the UIManager's default for the + * current look and feel. + */ + public void updateUI() + { + super.setUI((MenuItemUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for the menu. + * + * @return The Look and Feel classID. "MenuUI" + */ + public String getUIClassID() + { + return "MenuUI"; + } + + /** + * Sets model for this menu. + * + * @param model model to set + */ + public void setModel(ButtonModel model) + { + super.setModel(model); + } + + /** + * Returns true if the menu is selected and false otherwise + * + * @return true if the menu is selected and false otherwise + */ + public boolean isSelected() + { + return super.isSelected(); + } + + /** + * A helper method to handle setSelected calls from both mouse events and + * direct calls to setSelected. Direct calls shouldn't expand the popup + * menu and should select the JMenu even if it is disabled. Mouse events + * only select the JMenu if it is enabled and should expand the popup menu + * associated with this JMenu. + * @param selected whether or not the JMenu was selected + * @param menuEnabled whether or not selecting the menu is "enabled". This + * is always true for direct calls, and is set to isEnabled() for mouse + * based calls. + * @param showMenu whether or not to show the popup menu + */ + private void setSelectedHelper(boolean selected, boolean menuEnabled, boolean showMenu) + { + // If menu is selected and enabled, activates the menu and + // displays associated popup. + if (selected && menuEnabled) + { + super.setArmed(true); + super.setSelected(true); + + // FIXME: The popup menu should be shown on the screen after certain + // number of seconds pass. The 'delay' property of this menu indicates + // this amount of seconds. 'delay' property is 0 by default. + if (isShowing()) + { + fireMenuSelected(); + + int x = 0; + int y = 0; + if (showMenu) + if (menuLocation == null) + { + // Calculate correct position of the popup. Note that location of the popup + // passed to show() should be relative to the popup's invoker + if (isTopLevelMenu()) + y = this.getHeight(); + else + x = this.getWidth(); + getPopupMenu().show(this, x, y); + } + else + { + getPopupMenu().show(this, menuLocation.x, menuLocation.y); + } + } + } + + else + { + super.setSelected(false); + super.setArmed(false); + fireMenuDeselected(); + popupMenu.setVisible(false); + } + } + + /** + * Changes this menu selected state if selected is true and false otherwise + * This method fires menuEvents to menu's registered listeners. + * + * @param selected true if the menu should be selected and false otherwise + */ + public void setSelected(boolean selected) + { + setSelectedHelper(selected, true, false); + } + + /** + * Checks if PopupMenu associated with this menu is visible + * + * @return true if the popup associated with this menu is currently visible + * on the screen and false otherwise. + */ + public boolean isPopupMenuVisible() + { + return popupMenu.isVisible(); + } + + /** + * Sets popup menu visibility + * + * @param popup true if popup should be visible and false otherwise + */ + public void setPopupMenuVisible(boolean popup) + { + if (getModel().isEnabled()) + popupMenu.setVisible(popup); + } + + /** + * Returns origin point of the popup menu + * + * @return Point containing + */ + protected Point getPopupMenuOrigin() + { + // if menu in the menu bar + if (isTopLevelMenu()) + return new Point(0, this.getHeight()); + + // if submenu + return new Point(this.getWidth(), 0); + } + + /** + * Returns delay property. + * + * @return delay property, indicating number of milliseconds before + * popup menu associated with the menu appears or disappears after + * menu was selected or deselected respectively + */ + public int getDelay() + { + return delay; + } + + /** + * Sets delay property for this menu. If given time for the delay + * property is negative, then IllegalArgumentException is thrown + * + * @param delay number of milliseconds before + * popup menu associated with the menu appears or disappears after + * menu was selected or deselected respectively + */ + public void setDelay(int delay) + { + if (delay < 0) + throw new IllegalArgumentException("delay less than 0"); + this.delay = delay; + } + + /** + * Sets location at which popup menu should be displayed + * The location given is relative to this menu item + * + * @param x x-coordinate of the menu location + * @param y y-coordinate of the menu location + */ + public void setMenuLocation(int x, int y) + { + menuLocation = new Point(x, y); + } + + /** + * Creates and returns JMenuItem associated with the given action + * + * @param action Action to use for creation of JMenuItem + * + * @return JMenuItem that was creted with given action + */ + protected JMenuItem createActionComponent(Action action) + { + return new JMenuItem(action); + } + + /** + * Creates ActionChangeListener to listen for PropertyChangeEvents occuring + * in the action that is associated with this menu + * + * @param item menu that contains action to listen to + * + * @return The PropertyChangeListener + */ + protected PropertyChangeListener createActionChangeListener(JMenuItem item) + { + return new ActionChangedListener(item); + } + + /** + * Adds separator to the end of the menu items in the menu. + */ + public void addSeparator() + { + getPopupMenu().addSeparator(); + } + + /** + * Inserts separator in the menu at the specified index. + * + * @param index Index at which separator should be inserted + */ + public void insertSeparator(int index) + { + if (index < 0) + throw new IllegalArgumentException("index less than 0"); + + getPopupMenu().insert(new JPopupMenu.Separator(), index); + } + + /** + * Returns menu item located at the specified index in the menu + * + * @param index Index at which to look for the menu item + * + * @return menu item located at the specified index in the menu + */ + public JMenuItem getItem(int index) + { + if (index < 0) + throw new IllegalArgumentException("index less than 0"); + + Component c = popupMenu.getComponentAtIndex(index); + + if (c instanceof JMenuItem) + return (JMenuItem) c; + else + return null; + } + + /** + * Returns number of items in the menu including separators. + * + * @return number of items in the menu + * + * @see #getMenuComponentCount() + */ + public int getItemCount() + { + return getMenuComponentCount(); + } + + /** + * Checks if this menu is a tear-off menu. + * + * @return true if this menu is a tear-off menu and false otherwise + */ + public boolean isTearOff() + { + // NOT YET IMPLEMENTED + return false; + } + + /** + * Returns number of menu components in this menu + * + * @return number of menu components in this menu + */ + public int getMenuComponentCount() + { + return popupMenu.getComponentCount(); + } + + /** + * Returns menu component located at the givent index + * in the menu + * + * @param index index at which to get the menu component in the menu + * + * @return Menu Component located in the menu at the specified index + */ + public Component getMenuComponent(int index) + { + return (Component) popupMenu.getComponentAtIndex(index); + } + + /** + * Return components belonging to this menu + * + * @return components belonging to this menu + */ + public Component[] getMenuComponents() + { + return popupMenu.getComponents(); + } + + /** + * Checks if this menu is a top level menu. The menu is top + * level menu if it is inside the menu bar. While if the menu + * inside some other menu, it is considered to be a pull-right menu. + * + * @return true if this menu is top level menu, and false otherwise + */ + public boolean isTopLevelMenu() + { + return getParent() instanceof JMenuBar; + } + + /** + * Checks if given component exists in this menu. The submenus of + * this menu are checked as well + * + * @param component Component to look for + * + * @return true if the given component exists in this menu, and false otherwise + */ + public boolean isMenuComponent(Component component) + { + return false; + } + + /** + * Returns popup menu associated with the menu. + * + * @return popup menu associated with the menu. + */ + public JPopupMenu getPopupMenu() + { + return popupMenu; + } + + /** + * Adds MenuListener to the menu + * + * @param listener MenuListener to add + */ + public void addMenuListener(MenuListener listener) + { + listenerList.add(MenuListener.class, listener); + } + + /** + * Removes MenuListener from the menu + * + * @param listener MenuListener to remove + */ + public void removeMenuListener(MenuListener listener) + { + listenerList.remove(MenuListener.class, listener); + } + + /** + * Returns all registered MenuListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public MenuListener[] getMenuListeners() + { + return (MenuListener[]) listenerList.getListeners(MenuListener.class); + } + + /** + * This method fires MenuEvents to all menu's MenuListeners. In this case + * menuSelected() method of MenuListeners is called to indicated that the menu + * was selected. + */ + protected void fireMenuSelected() + { + MenuListener[] listeners = getMenuListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].menuSelected(menuEvent); + } + + /** + * This method fires MenuEvents to all menu's MenuListeners. In this case + * menuDeselected() method of MenuListeners is called to indicated that the menu + * was deselected. + */ + protected void fireMenuDeselected() + { + EventListener[] ll = listenerList.getListeners(MenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuListener) ll[i]).menuDeselected(menuEvent); + } + + /** + * This method fires MenuEvents to all menu's MenuListeners. In this case + * menuSelected() method of MenuListeners is called to indicated that the menu + * was cancelled. The menu is cancelled when it's popup menu is close without selection. + */ + protected void fireMenuCanceled() + { + EventListener[] ll = listenerList.getListeners(MenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuListener) ll[i]).menuCanceled(menuEvent); + } + + /** + * Creates WinListener that listens to the menu;s popup menu. + * + * @param popup JPopupMenu to listen to + * + * @return The WinListener + */ + protected WinListener createWinListener(JPopupMenu popup) + { + return new WinListener(popup); + } + + /** + * Method of the MenuElementInterface. It reacts to the selection + * changes in the menu. If this menu was selected, then it + * displayes popup menu associated with it and if this menu was + * deselected it hides the popup menu. + * + * @param changed true if the menu was selected and false otherwise + */ + public void menuSelectionChanged(boolean changed) + { + // if this menu selection is true, then activate this menu and + // display popup associated with this menu + setSelectedHelper(changed, isEnabled(), true); + } + + /** + * Method of MenuElement interface. Returns sub components of + * this menu. + * + * @return array containing popupMenu that is associated with this menu + */ + public MenuElement[] getSubElements() + { + return new MenuElement[] { popupMenu }; + } + + /** + * @return Returns reference to itself + */ + public Component getComponent() + { + return this; + } + + /** + * This method is overriden with empty implementation, s.t the + * accelerator couldn't be set for the menu. The mnemonic should + * be used for the menu instead. + * + * @param keystroke accelerator for this menu + */ + public void setAccelerator(KeyStroke keystroke) + { + throw new Error("setAccelerator() is not defined for JMenu. Use setMnemonic() instead."); + } + + /** + * This method process KeyEvent occuring when the menu is visible + * + * @param event The KeyEvent + */ + protected void processKeyEvent(KeyEvent event) + { + } + + /** + * Programatically performs click + * + * @param time Number of milliseconds for which this menu stays pressed + */ + public void doClick(int time) + { + getModel().setArmed(true); + getModel().setPressed(true); + try + { + java.lang.Thread.sleep(time); + } + catch (java.lang.InterruptedException e) + { + // probably harmless + } + + getModel().setPressed(false); + getModel().setArmed(false); + popupMenu.show(this, this.getWidth(), 0); + } + + /** + * A string that describes this JMenu. Normally only used + * for debugging. + * + * @return A string describing this JMenu + */ + protected String paramString() + { + return super.paramString(); + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJMenu(); + + return accessibleContext; + } + + protected class AccessibleJMenu extends AccessibleJMenuItem + implements AccessibleSelection + { + private static final long serialVersionUID = -8131864021059524309L; + + protected AccessibleJMenu() + { + } + + public int getAccessibleChildrenCount() + { + return 0; + } + + public Accessible getAccessibleChild(int value0) + { + return null; + } + + public AccessibleSelection getAccessibleSelection() + { + return null; + } + + public Accessible getAccessibleSelection(int value0) + { + return null; + } + + public boolean isAccessibleChildSelected(int value0) + { + return false; + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU; + } + + public int getAccessibleSelectionCount() + { + return 0; + } + + public void addAccessibleSelection(int value0) + { + } + + public void removeAccessibleSelection(int value0) + { + } + + public void clearAccessibleSelection() + { + } + + public void selectAllAccessibleSelection() + { + } + } + + protected class WinListener extends WindowAdapter implements Serializable + { + JPopupMenu popupMenu; + private static final long serialVersionUID = -6415815570638474823L; + + public WinListener(JPopupMenu popup) + { + } + + public void windowClosing(WindowEvent event) + { + } + } + + /** + * This class listens to PropertyChangeEvents occuring in menu's action + */ + protected class ActionChangedListener implements PropertyChangeListener + { + /** menu item associated with the action */ + private JMenuItem menuItem; + + /** Creates new ActionChangedListener and adds it to menuItem's action */ + public ActionChangedListener(JMenuItem menuItem) + { + this.menuItem = menuItem; + + Action a = menuItem.getAction(); + if (a != null) + a.addPropertyChangeListener(this); + } + + /**This method is invoked when some change occures in menuItem's action*/ + public void propertyChange(PropertyChangeEvent evt) + { + // FIXME: Need to implement + } + } + +} diff --git a/libjava/classpath/javax/swing/JMenuBar.java b/libjava/classpath/javax/swing/JMenuBar.java new file mode 100644 index 0000000..a464fff --- /dev/null +++ b/libjava/classpath/javax/swing/JMenuBar.java @@ -0,0 +1,459 @@ +/* JMenuBar.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.plaf.MenuBarUI; + +/** + * JMenuBar is a container for menu's. For a menu bar to be seen on the + * screen, at least one menu should be added to it. Just like adding + * components to container, one can use add() to add menu's to the menu bar. + * Menu's will be displayed in the menu bar in the order they were added. + * The JMenuBar uses selectionModel to keep track of selected menu index. + * JMenuBar's selectionModel will fire ChangeEvents to its registered + * listeners when the selected index changes. + */ +public class JMenuBar extends JComponent implements Accessible, MenuElement +{ + private static final long serialVersionUID = -8191026883931977036L; + + /** JMenuBar's model. It keeps track of selected menu's index */ + private transient SingleSelectionModel selectionModel; + + /* borderPainted property indicating if the menuBar's border will be painted*/ + private boolean borderPainted; + + /* margin between menu bar's border and its menues*/ + private Insets margin; + + /** + * Creates a new JMenuBar object. + */ + public JMenuBar() + { + selectionModel = new DefaultSingleSelectionModel(); + borderPainted = true; + updateUI(); + } + + /** + * Adds menu to the menu bar + * + * @param c menu to add + * + * @return reference to the added menu + */ + public JMenu add(JMenu c) + { + c.setAlignmentX(Component.LEFT_ALIGNMENT); + super.add(c); + return c; + } + + /** + * This method overrides addNotify() in the Container to register + * this menu bar with the current keyboard manager. + */ + public void addNotify() + { + // FIXME: Should register this menu bar with the keyboard manager + super.addNotify(); + } + + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * Returns reference to this menu bar + * + * @return reference to this menu bar + */ + public Component getComponent() + { + return this; + } + + /** + * Returns component at the specified index. + * + * @param i index of the component to get + * + * @return component at the specified index. Null is returned if + * component at the specified index doesn't exist. + * @deprecated Replaced by getComponent(int) + */ + public Component getComponentAtIndex(int i) + { + return getComponent(i); + } + + /** + * Returns index of the specified component + * + * @param c Component to search for + * + * @return index of the specified component. -1 is returned if + * specified component doesnt' exist in the menu bar. + */ + public int getComponentIndex(Component c) + { + Component[] comps = getComponents(); + + int index = -1; + + for (int i = 0; i < comps.length; i++) + { + if (comps[i].equals(c)) + { + index = i; + break; + } + } + + return index; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenu getHelpMenu() + { + return null; + } + + /** + * Returns margin betweeen menu bar's border and its menues + * + * @return margin between menu bar's border and its menues + */ + public Insets getMargin() + { + if (margin == null) + return new Insets(0, 0, 0, 0); + else + return margin; + } + + /** + * Return menu at the specified index. If component at the + * specified index is not a menu, then null is returned. + * + * @param index index to look for the menu + * + * @return menu at specified index, or null if menu doesn't exist + * at the specified index. + */ + public JMenu getMenu(int index) + { + if (getComponentAtIndex(index) instanceof JMenu) + return (JMenu) getComponentAtIndex(index); + else + return null; + } + + /** + * Returns number of menu's in this menu bar + * + * @return number of menu's in this menu bar + */ + public int getMenuCount() + { + return getComponentCount(); + } + + /** + * Returns selection model for this menu bar. SelectionModel + * keeps track of the selected menu in the menu bar. Whenever + * selected property of selectionModel changes, the ChangeEvent + * will be fired its ChangeListeners. + * + * @return selection model for this menu bar. + */ + public SingleSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * Method of MenuElement interface. It returns subcomponents + * of the menu bar, which are all the menues that it contains. + * + * @return MenuElement[] array containing menues in this menu bar + */ + public MenuElement[] getSubElements() + { + MenuElement[] subElements = new MenuElement[getComponentCount()]; + + for (int i = 0; i < getComponentCount(); i++) + subElements[i] = (MenuElement) getMenu(i); + + return subElements; + } + + /** + * Set the "UI" property of the menu bar, which is a look and feel class + * responsible for handling the menuBar's input events and painting it. + * + * @return The current "UI" property + */ + public MenuBarUI getUI() + { + return (MenuBarUI) ui; + } + + /** + * 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" + */ + public String getUIClassID() + { + return "MenuBarUI"; + } + + /** + * Returns true if menu bar paints its border and false otherwise + * + * @return true if menu bar paints its border and false otherwise + */ + public boolean isBorderPainted() + { + return borderPainted; + } + + /** + * Returns true if some menu in menu bar is selected. + * + * @return true if some menu in menu bar is selected and false otherwise + */ + public boolean isSelected() + { + return selectionModel.isSelected(); + } + + /** + * This method does nothing by default. This method is need for the + * MenuElement interface to be implemented. + * + * @param isIncluded true if menuBar is included in the selection + * and false otherwise + */ + public void menuSelectionChanged(boolean isIncluded) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * Paints border of the menu bar, if its borderPainted property is set to + * true. + * + * @param g The graphics context with which to paint the border + */ + protected void paintBorder(Graphics g) + { + if (borderPainted) + getBorder().paintBorder(this, g, 0, 0, getSize(null).width, + getSize(null).height); + } + + /** + * A string that describes this JMenuBar. Normally only used + * for debugging. + * + * @return A string describing this JMenuBar + */ + protected String paramString() + { + StringBuffer sb = new StringBuffer(); + sb.append(super.paramString()); + sb.append(",margin="); + if (getMargin() != null) + sb.append(getMargin()); + sb.append(",paintBorder=").append(isBorderPainted()); + return sb.toString(); + } + + /** + * Process key events forwarded from MenuSelectionManager. This method + * doesn't do anything. It is here to conform to the MenuElement interface. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + * + */ + public void processKeyEvent(KeyEvent e, MenuElement[] path, + MenuSelectionManager manager) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * Process mouse events forwarded from MenuSelectionManager. This method + * doesn't do anything. It is here to conform to the MenuElement interface. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + * + */ + public void processMouseEvent(MouseEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * This method overrides removeNotify() in the Container to + * unregister this menu bar from the current keyboard manager. + */ + public void removeNotify() + { + // Must unregister this menu bar with the current keyboard manager. + super.removeNotify(); + } + + /** + * Sets painting status of the border. If 'b' is true then menu bar's + * border will be painted, and it will not be painted otherwise. + * + * @param b indicates if menu bar's border should be painted. + */ + public void setBorderPainted(boolean b) + { + if (b != borderPainted) + { + boolean old = borderPainted; + borderPainted = b; + firePropertyChange("borderPainted", old, b); + revalidate(); + repaint(); + } + } + + /** + * Sets help menu for this menu bar + * + * @param menu help menu + */ + public void setHelpMenu(JMenu menu) + { + } + + /** + * Sets the menu bar's "margin" bound property, which represents + * distance between the menubar's border and its menus. + * icon. When marging property is modified, PropertyChangeEvent will + * be fired to menuBar's PropertyChangeListener's. + * + * @param m distance between the menubar's border and its menus. + * + */ + public void setMargin(Insets m) + { + if (m != margin) + { + Insets oldMargin = margin; + margin = m; + firePropertyChange("margin", oldMargin, margin); + } + } + + /** + * Changes menu bar's selection to the specified menu. + * This method updates selected index of menu bar's selection model, + * which results in a model firing change event. + * + * @param sel menu to select + */ + public void setSelected(Component sel) + { + int index = getComponentIndex(sel); + selectionModel.setSelectedIndex(index); + } + + /** + * Sets menuBar's selection model to the one specified + * + * @param model SingleSelectionModel that needs to be set for this menu bar + */ + public void setSelectionModel(SingleSelectionModel model) + { + if (selectionModel != model) + { + SingleSelectionModel oldModel = selectionModel; + selectionModel = model; + firePropertyChange("model", oldModel, selectionModel); + } + } + + /** + * Set the "UI" property of the menu bar, which is a look and feel class + * responsible for handling menuBar's input events and painting it. + * + * @param ui The new "UI" property + */ + public void setUI(MenuBarUI ui) + { + super.setUI(ui); + } + + /** + * Set the "UI" property to a class constructed, via the {@link + * UIManager}, from the current look and feel. + */ + public void updateUI() + { + setUI((MenuBarUI) UIManager.getUI(this)); + invalidate(); + } +} diff --git a/libjava/classpath/javax/swing/JMenuItem.java b/libjava/classpath/javax/swing/JMenuItem.java new file mode 100644 index 0000000..069b7bc --- /dev/null +++ b/libjava/classpath/javax/swing/JMenuItem.java @@ -0,0 +1,677 @@ +/* JMenuItem.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.plaf.MenuItemUI; + +/** + * JMenuItem represents element in the menu. It inherits most of + * its functionality from AbstractButton, however its behavior somewhat + * varies from it. JMenuItem fire different kinds of events. + * PropertyChangeEvents are fired when menuItems properties are modified; + * ChangeEvents are fired when menuItem's state changes and actionEvents are + * fired when menu item is selected. In addition to this events menuItem also + * fire MenuDragMouseEvent and MenuKeyEvents when mouse is dragged over + * the menu item or associated key with menu item is invoked respectively. + */ +public class JMenuItem extends AbstractButton implements Accessible, + MenuElement +{ + private static final long serialVersionUID = -1681004643499461044L; + + /** Combination of keyboard keys that can be used to activate this menu item */ + private KeyStroke accelerator; + + /** + * Creates a new JMenuItem object. + */ + public JMenuItem() + { + super(); + } + + /** + * Creates a new JMenuItem with the given icon. + * + * @param icon Icon that will be displayed on the menu item + */ + public JMenuItem(Icon icon) + { + // FIXME: The requestedFocusEnabled property should + // be set to false, when only icon is set for menu item. + super(); + init(null, icon); + } + + /** + * Creates a new JMenuItem with the given label. + * + * @param text label for the menu item + */ + public JMenuItem(String text) + { + this(text, null); + } + + /** + * Creates a new JMenuItem associated with the specified action. + * + * @param action action for this menu item + */ + public JMenuItem(Action action) + { + super(); + super.setAction(action); + } + + /** + * Creates a new JMenuItem with specified text and icon. + * Text is displayed to the left of icon by default. + * + * @param text label for this menu item + * @param icon icon that will be displayed on this menu item + */ + public JMenuItem(String text, Icon icon) + { + super(); + init(text, icon); + } + + /** + * Creates a new JMenuItem object. + * + * @param text label for this menu item + * @param mnemonic - Single key that can be used with a + * look-and-feel meta key to activate this menu item. However + * menu item should be visible on the screen when mnemonic is used. + */ + public JMenuItem(String text, int mnemonic) + { + this(text, null); + setMnemonic(mnemonic); + } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + } + + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * Initializes this menu item + * + * @param text label for this menu item + * @param icon icon to be displayed for this menu item + */ + protected void init(String text, Icon icon) + { + super.init(text, icon); + setModel(new DefaultButtonModel()); + + // Initializes properties for this menu item, that are different + // from Abstract button properties. + /* NOTE: According to java specifications paint_border should be set to false, + since menu item should not have a border. However running few java programs + it seems that menu items and menues can have a border. Commenting + out statement below for now. */ + //borderPainted = false; + focusPainted = false; + horizontalAlignment = JButton.LEFT; + horizontalTextPosition = JButton.LEFT; + } + + /** + * Set the "UI" property of the menu item, which is a look and feel class + * responsible for handling menuItem's input events and painting it. + * + * @param ui The new "UI" property + */ + public void setUI(MenuItemUI ui) + { + super.setUI(ui); + } + + /** + * This method sets this menuItem's UI to the UIManager's default for the + * current look and feel. + */ + public void updateUI() + { + MenuItemUI mi = ((MenuItemUI) UIManager.getUI(this)); + setUI(mi); + invalidate(); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for the menuItem. + * + * @return The Look and Feel classID. "MenuItemUI" + */ + public String getUIClassID() + { + return "MenuItemUI"; + } + + /** + * Returns true if button's model is armed and false otherwise. The + * button model is armed if menu item has focus or it is selected. + * + * @return $boolean$ true if button's model is armed and false otherwise + */ + public boolean isArmed() + { + return getModel().isArmed(); + } + + /** + * Sets menuItem's "ARMED" property + * + * @param armed DOCUMENT ME! + */ + public void setArmed(boolean armed) + { + getModel().setArmed(armed); + } + + /** + * Enable or disable menu item. When menu item is disabled, + * its text and icon are grayed out if they exist. + * + * @param enabled if true enable menu item, and disable otherwise. + */ + public void setEnabled(boolean enabled) + { + super.setEnabled(enabled); + } + + /** + * Return accelerator for this menu item. + * + * @return $KeyStroke$ accelerator for this menu item. + */ + public KeyStroke getAccelerator() + { + return accelerator; + } + + /** + * Sets accelerator for this menu item. + * + * @param keystroke accelerator for this menu item. + */ + public void setAccelerator(KeyStroke keystroke) + { + this.accelerator = keystroke; + } + + /** + * Configures menu items' properties from properties of the specified action. + * This method overrides configurePropertiesFromAction from AbstractButton + * to also set accelerator property. + * + * @param action action to configure properties from + */ + protected void configurePropertiesFromAction(Action action) + { + super.configurePropertiesFromAction(action); + + if (! (this instanceof JMenu) && action != null) + setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY))); + } + + /** + * Creates PropertyChangeListener to listen for the changes in action + * properties. + * + * @param action action to listen to for property changes + * + * @return $PropertyChangeListener$ Listener that listens to changes in + * action properties. + */ + protected PropertyChangeListener createActionPropertyChangeListener(Action action) + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + Action act = (Action) (e.getSource()); + configurePropertiesFromAction(act); + } + }; + } + + /** + * Process mouse events forwarded from MenuSelectionManager. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + */ + public void processMouseEvent(MouseEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Fire MenuDragMouseEvents if mouse is being dragged. + boolean dragged + = (event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0; + if (dragged) + processMenuDragMouseEvent(createMenuDragMouseEvent(event, path, manager)); + + switch (event.getID()) + { + case MouseEvent.MOUSE_CLICKED: + break; + case MouseEvent.MOUSE_ENTERED: + if (isRolloverEnabled()) + model.setRollover(true); + break; + case MouseEvent.MOUSE_EXITED: + if (isRolloverEnabled()) + model.setRollover(false); + + // for JMenu last element on the path is its popupMenu. + // JMenu shouldn't me disarmed. + if (! (path[path.length - 1] instanceof JPopupMenu) && ! dragged) + setArmed(false); + break; + case MouseEvent.MOUSE_PRESSED: + if ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0) + { + model.setArmed(true); + model.setPressed(true); + } + break; + case MouseEvent.MOUSE_RELEASED: + break; + case MouseEvent.MOUSE_MOVED: + break; + case MouseEvent.MOUSE_DRAGGED: + break; + } + } + + /** + * Creates MenuDragMouseEvent. + * + * @param event MouseEvent that occured while mouse was pressed. + * @param path Path the the menu element where the dragging event was + * originated + * @param manager MenuSelectionManager for the current menu hierarchy. + * + * @return new MenuDragMouseEvent + */ + private MenuDragMouseEvent createMenuDragMouseEvent(MouseEvent event, + MenuElement[] path, + MenuSelectionManager manager) + { + return new MenuDragMouseEvent((Component) event.getSource(), + event.getID(), event.getWhen(), + event.getModifiers(), event.getX(), + event.getY(), event.getClickCount(), + event.isPopupTrigger(), path, manager); + } + + /** + * Process key events forwarded from MenuSelectionManager. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + */ + public void processKeyEvent(KeyEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Need to implement. + } + + /** + * This method fires MenuDragMouseEvents to registered listeners. + * Different types of MenuDragMouseEvents are fired depending + * on the observed mouse event. + * + * @param event Mouse + */ + public void processMenuDragMouseEvent(MenuDragMouseEvent event) + { + switch (event.getID()) + { + case MouseEvent.MOUSE_ENTERED: + fireMenuDragMouseEntered(event); + break; + case MouseEvent.MOUSE_EXITED: + fireMenuDragMouseExited(event); + break; + case MouseEvent.MOUSE_DRAGGED: + fireMenuDragMouseDragged(event); + break; + case MouseEvent.MOUSE_RELEASED: + fireMenuDragMouseReleased(event); + break; + } + } + + /** + * This method fires MenuKeyEvent to registered listeners. + * Different types of MenuKeyEvents are fired depending + * on the observed key event. + * + * @param event DOCUMENT ME! + */ + public void processMenuKeyEvent(MenuKeyEvent event) + { + // Need to implement. + } + + /** + * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. + * + * @param event The event signifying that mouse entered menuItem while it was dragged + */ + protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event); + } + + /** + * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. + * + * @param event The event signifying that mouse has exited menu item, while it was dragged + */ + protected void fireMenuDragMouseExited(MenuDragMouseEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event); + } + + /** + * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. + * + * @param event The event signifying that mouse is being dragged over the menuItem + */ + protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event); + } + + /** + * This method fires a MenuDragMouseEvent to all the MenuItem's MouseInputListeners. + * + * @param event The event signifying that mouse was released while it was dragged over the menuItem + */ + protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event); + } + + /** + * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. + * + * @param event The event signifying that key associated with this menu was pressed + */ + protected void fireMenuKeyPressed(MenuKeyEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuKeyListener) ll[i]).menuKeyPressed(event); + } + + /** + * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. + * + * @param event The event signifying that key associated with this menu was released + */ + protected void fireMenuKeyReleased(MenuKeyEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuKeyListener) ll[i]).menuKeyTyped(event); + } + + /** + * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. + * + * @param event The event signifying that key associated with this menu was typed. + * The key is typed when it was pressed and then released + */ + protected void fireMenuKeyTyped(MenuKeyEvent event) + { + EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuKeyListener) ll[i]).menuKeyTyped(event); + } + + /** + * Method of the MenuElement interface. + * This method is invoked by MenuSelectionManager when selection of + * this menu item has changed. If this menu item was selected then + * arm it's model, and disarm the model otherwise. The menu item + * is considered to be selected, and thus highlighted when its model + * is armed. + * + * @param changed indicates selection status of this menu item. If changed is + * true then menu item is selected and deselected otherwise. + */ + public void menuSelectionChanged(boolean changed) + { + Component parent = this.getParent(); + if (changed) + { + model.setArmed(true); + + if (parent != null && parent instanceof JPopupMenu) + ((JPopupMenu) parent).setSelected(this); + } + else + { + model.setArmed(false); + + if (parent != null && parent instanceof JPopupMenu) + ((JPopupMenu) parent).getSelectionModel().clearSelection(); + } + } + + /** + * Method of the MenuElement interface. + * + * @return $MenuElement[]$ Returns array of sub-components for this menu + * item. By default menuItem doesn't have any subcomponents and so + * empty array is returned instead. + */ + public MenuElement[] getSubElements() + { + return new MenuElement[0]; + } + + /** + * Returns reference to the component that will paint this menu item. + * + * @return $Component$ Component that will paint this menu item. + * Simply returns reference to this menu item. + */ + public Component getComponent() + { + return this; + } + + /** + * Adds a MenuDragMouseListener to this menu item. When mouse + * is dragged over the menu item the MenuDragMouseEvents will be + * fired, and these listeners will be called. + * + * @param listener The new listener to add + */ + public void addMenuDragMouseListener(MenuDragMouseListener listener) + { + listenerList.add(MenuDragMouseListener.class, listener); + } + + /** + * Removes a MenuDragMouseListener from the menuItem's listener list. + * + * @param listener The listener to remove + */ + public void removeMenuDragMouseListener(MenuDragMouseListener listener) + { + listenerList.remove(MenuDragMouseListener.class, listener); + } + + /** + * Returns all added MenuDragMouseListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public MenuDragMouseListener[] getMenuDragMouseListeners() + { + return (MenuDragMouseListener[]) listenerList.getListeners(MenuDragMouseListener.class); + } + + /** + * Adds an MenuKeyListener to this menu item. This listener will be + * invoked when MenuKeyEvents will be fired by this menu item. + * + * @param listener The new listener to add + */ + public void addMenuKeyListener(MenuKeyListener listener) + { + listenerList.add(MenuKeyListener.class, listener); + } + + /** + * Removes an MenuKeyListener from the menuItem's listener list. + * + * @param listener The listener to remove + */ + public void removeMenuKeyListener(MenuKeyListener listener) + { + listenerList.remove(MenuKeyListener.class, listener); + } + + /** + * Returns all added MenuKeyListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public MenuKeyListener[] getMenuKeyListeners() + { + return (MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class); + } + + /** + * A string that describes this JMenuItem. Normally only used + * for debugging. + * + * @return A string describing this JMenuItem + */ + protected String paramString() + { + return super.paramString(); + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJMenuItem(); + + return accessibleContext; + } + + protected class AccessibleJMenuItem extends AccessibleAbstractButton + implements ChangeListener + { + private static final long serialVersionUID = 6748924232082076534L; + + /** + * Creates a new AccessibleJMenuItem object. + */ + AccessibleJMenuItem() + { + //super(component); + } + + public void stateChanged(ChangeEvent event) + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU_ITEM; + } + } +} diff --git a/libjava/classpath/javax/swing/JOptionPane.java b/libjava/classpath/javax/swing/JOptionPane.java new file mode 100644 index 0000000..88fa993 --- /dev/null +++ b/libjava/classpath/javax/swing/JOptionPane.java @@ -0,0 +1,1547 @@ +/* JOptionPane.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; +import javax.swing.plaf.OptionPaneUI; + +/** + * This class creates different types of JDialogs and JInternalFrames that can + * ask users for input or pass on information. JOptionPane can be used by + * calling one of the show static methods or by creating an instance of + * JOptionPane and calling createDialog or createInternalFrame. + */ +public class JOptionPane extends JComponent implements Accessible +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJOptionPane extends JComponent.AccessibleJComponent + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = 686071432213084821L; + + /** + * Creates a new AccessibleJOptionPane object. + */ + protected AccessibleJOptionPane() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + } + + /** DOCUMENT ME! */ + private static final long serialVersionUID = 5231143276678566796L; + + /** The value returned when cancel option is selected. */ + public static final int CANCEL_OPTION = 2; + + /** The value returned when the dialog is closed without a selection. */ + public static final int CLOSED_OPTION = -1; + + /** An option used in confirmation dialog methods. */ + public static final int DEFAULT_OPTION = -1; + + /** The value returned when the no option is selected. */ + public static final int NO_OPTION = 1; + + /** An option used in confirmation dialog methods. */ + public static final int OK_CANCEL_OPTION = 2; + + /** The value returned when the ok option is selected. */ + public static final int OK_OPTION = 0; + + /** An option used in confirmation dialog methods. */ + public static final int YES_NO_CANCEL_OPTION = 1; + + /** An option used in confirmation dialog methods. */ + public static final int YES_NO_OPTION = 0; + + /** The value returned when the yes option is selected. */ + public static final int YES_OPTION = 0; + + /** Identifier for the error message type. */ + public static final int ERROR_MESSAGE = 0; + + /** Identifier for the information message type. */ + public static final int INFORMATION_MESSAGE = 1; + + /** Identifier for the plain message type. */ + public static final int PLAIN_MESSAGE = -1; + + /** Identifier for the question message type. */ + public static final int QUESTION_MESSAGE = 3; + + /** Identifier for the warning message type. */ + public static final int WARNING_MESSAGE = 2; + + /** + * The identifier for the propertyChangeEvent when the icon property + * changes. + */ + public static final String ICON_PROPERTY = "icon"; + + /** + * The identifier for the propertyChangeEvent when the initialSelectionValue + * property changes. + */ + public static final String INITIAL_SELECTION_VALUE_PROPERTY = "initialSelectionValue"; + + /** + * The identifier for the propertyChangeEvent when the initialValue property + * changes. + */ + public static final String INITIAL_VALUE_PROPERTY = "initialValue"; + + /** + * The identifier for the propertyChangeEvent when the inputValue property + * changes. + */ + public static final String INPUT_VALUE_PROPERTY = "inputValue"; + + /** + * The identifier for the propertyChangeEvent when the message property + * changes. + */ + public static final String MESSAGE_PROPERTY = "message"; + + /** + * The identifier for the propertyChangeEvent when the messageType property + * changes. + */ + public static final String MESSAGE_TYPE_PROPERTY = "messageType"; + + /** + * The identifier for the propertyChangeEvent when the optionType property + * changes. + */ + public static final String OPTION_TYPE_PROPERTY = "optionType"; + + /** + * The identifier for the propertyChangeEvent when the options property + * changes. + */ + public static final String OPTIONS_PROPERTY = "options"; + + /** + * The identifier for the propertyChangeEvent when the selectionValues + * property changes. + */ + public static final String SELECTION_VALUES_PROPERTY = "selectionValues"; + + /** + * The identifier for the propertyChangeEvent when the value property + * changes. + */ + public static final String VALUE_PROPERTY = "value"; + + /** + * The identifier for the propertyChangeEvent when the wantsInput property + * changes. + */ + public static final String WANTS_INPUT_PROPERTY = "wantsInput"; + + /** The value returned when the inputValue is uninitialized. */ + public static Object UNINITIALIZED_VALUE = "uninitializedValue"; + + /** The icon displayed in the dialog/internal frame. */ + protected Icon icon; + + /** The initial selected value in the input component. */ + protected Object initialSelectionValue; + + /** The object that is initially selected for options. */ + protected Object initialValue; + + /** The value the user inputs. */ + protected Object inputValue = UNINITIALIZED_VALUE; + + /** The message displayed in the dialog/internal frame. */ + protected Object message; + + /** The type of message displayed. */ + protected int messageType = PLAIN_MESSAGE; + + /** + * The options (usually buttons) aligned at the bottom for the user to + * select. + */ + protected Object[] options; + + /** The type of options to display. */ + protected int optionType = DEFAULT_OPTION; + + /** The input values the user can select. */ + protected Object[] selectionValues; + + /** The value returned by selecting an option. */ + protected Object value = UNINITIALIZED_VALUE; + + /** Whether the Dialog/InternalFrame needs input. */ + protected boolean wantsInput; + + /** The common frame used when no parent is provided. */ + private static Frame privFrame = SwingUtilities.getOwnerFrame(); + + /** + * Creates a new JOptionPane object using a message of "JOptionPane + * message", using the PLAIN_MESSAGE type and DEFAULT_OPTION. + */ + public JOptionPane() + { + this("JOptionPane message", PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); + } + + /** + * Creates a new JOptionPane object using the given message using the + * PLAIN_MESSAGE type and DEFAULT_OPTION. + * + * @param message The message to display. + */ + public JOptionPane(Object message) + { + this(message, PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); + } + + /** + * Creates a new JOptionPane object using the given message and messageType + * and DEFAULT_OPTION. + * + * @param message The message to display. + * @param messageType The type of message. + */ + public JOptionPane(Object message, int messageType) + { + this(message, messageType, DEFAULT_OPTION, null, null, null); + } + + /** + * Creates a new JOptionPane object using the given message, messageType and + * optionType. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + */ + public JOptionPane(Object message, int messageType, int optionType) + { + this(message, messageType, optionType, null, null, null); + } + + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType and icon. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + */ + public JOptionPane(Object message, int messageType, int optionType, Icon icon) + { + this(message, messageType, optionType, icon, null, null); + } + + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType, icon and options. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + * @param options The options given. + */ + public JOptionPane(Object message, int messageType, int optionType, + Icon icon, Object[] options) + { + this(message, messageType, optionType, icon, options, null); + } + + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType, icon, options and initialValue. The initialValue will be + * focused initially. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + * @param options The options given. + * @param initialValue The component to focus on initially. + * + * @throws IllegalArgumentException If the messageType or optionType are not + * legal values. + */ + public JOptionPane(Object message, int messageType, int optionType, + Icon icon, Object[] options, Object initialValue) + { + this.message = message; + if (! validMessageType(messageType)) + throw new IllegalArgumentException("Message Type not legal value."); + this.messageType = messageType; + if (! validOptionType(optionType)) + throw new IllegalArgumentException("Option Type not legal value."); + this.optionType = optionType; + this.icon = icon; + this.options = options; + this.initialValue = initialValue; + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + updateUI(); + invalidate(); + repaint(); + } + + /** + * This method creates a new JDialog that is either centered around the + * parent's frame or centered on the screen (if the parent is null). The + * JDialog will not be resizable and will be modal. Once the JDialog is + * disposed, the inputValue and value properties will be set by the + * optionPane. + * + * @param parentComponent The parent of the Dialog. + * @param title The title in the bar of the JDialog. + * + * @return A new JDialog based on the JOptionPane configuration. + */ + public JDialog createDialog(Component parentComponent, String title) + { + Frame toUse = getFrameForComponent(parentComponent); + if (toUse == null) + toUse = getRootFrame(); + + JDialog dialog = new JDialog(toUse, title); + inputValue = UNINITIALIZED_VALUE; + value = UNINITIALIZED_VALUE; + + // FIXME: This dialog should be centered on the parent + // or at the center of the screen (if the parent is null) + // Need getGraphicsConfiguration to return non-null in + // order for that to work so we know how large the + // screen is. + dialog.getContentPane().add(this); + dialog.setModal(true); + dialog.setResizable(false); + dialog.invalidate(); + dialog.repaint(); + + return dialog; + } + + /** + * This method creates a new JInternalFrame that is in the JDesktopPane + * which contains the parentComponent given. If no suitable JDesktopPane + * can be found from the parentComponent given, a RuntimeException will be + * thrown. + * + * @param parentComponent The parent to find a JDesktopPane from. + * @param title The title of the JInternalFrame. + * + * @return A new JInternalFrame based on the JOptionPane configuration. + * + * @throws RuntimeException If no suitable JDesktopPane is found. + */ + public JInternalFrame createInternalFrame(Component parentComponent, + String title) + throws RuntimeException + { + JDesktopPane toUse = getDesktopPaneForComponent(parentComponent); + if (toUse == null) + throw new RuntimeException("parentComponent does not have a valid parent"); + + JInternalFrame frame = new JInternalFrame(title); + + inputValue = UNINITIALIZED_VALUE; + value = UNINITIALIZED_VALUE; + + frame.setClosable(true); + toUse.add(frame); + + // FIXME: JLayeredPane broken? See bug # 16576 + // frame.setLayer(JLayeredPane.MODAL_LAYER); + return frame; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJOptionPane(); + return accessibleContext; + } + + /** + * This method returns the JDesktopPane for the given parentComponent or + * null if none can be found. + * + * @param parentComponent The component to look in. + * + * @return The JDesktopPane for the given component or null if none can be + * found. + */ + public static JDesktopPane getDesktopPaneForComponent(Component parentComponent) + { + return (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class, + parentComponent); + } + + /** + * This method returns the Frame for the given parentComponent or null if + * none can be found. + * + * @param parentComponent The component to look in. + * + * @return The Frame for the given component or null if none can be found. + */ + public static Frame getFrameForComponent(Component parentComponent) + { + return (Frame) SwingUtilities.getAncestorOfClass(Frame.class, + parentComponent); + } + + /** + * This method returns the icon displayed. + * + * @return The icon displayed. + */ + public Icon getIcon() + { + return icon; + } + + /** + * This method returns the value initially selected from the list of values + * the user can input. + * + * @return The initial selection value. + */ + public Object getInitialSelectionValue() + { + return initialSelectionValue; + } + + /** + * This method returns the value that is focused from the list of options. + * + * @return The initial value from options. + */ + public Object getInitialValue() + { + return initialValue; + } + + /** + * This method returns the value that the user input. + * + * @return The user's input value. + */ + public Object getInputValue() + { + return inputValue; + } + + /** + * This method returns the maximum characters per line. By default, this is + * Integer.MAX_VALUE. + * + * @return The maximum characters per line. + */ + public int getMaxCharactersPerLineCount() + { + return Integer.MAX_VALUE; + } + + /** + * This method returns the message displayed. + * + * @return The message displayed. + */ + public Object getMessage() + { + return message; + } + + /** + * This method returns the message type. + * + * @return The message type. + */ + public int getMessageType() + { + return messageType; + } + + /** + * This method returns the options. + * + * @return The options. + */ + public Object[] getOptions() + { + return options; + } + + /** + * This method returns the option type. + * + * @return The option type. + */ + public int getOptionType() + { + return optionType; + } + + /** + * This method returns the Frame used by JOptionPane dialog's that have no + * parent. + * + * @return The Frame used by dialogs that have no parent. + */ + public static Frame getRootFrame() + { + return privFrame; + } + + /** + * This method returns the selection values. + * + * @return The selection values. + */ + public Object[] getSelectionValues() + { + return selectionValues; + } + + /** + * This method returns the UI used by the JOptionPane. + * + * @return The UI used by the JOptionPane. + */ + public OptionPaneUI getUI() + { + return (OptionPaneUI) ui; + } + + /** + * This method returns an identifier to determine which UI class will act as + * the UI. + * + * @return The UI identifier. + */ + public String getUIClassID() + { + return "OptionPaneUI"; + } + + /** + * This method returns the value that the user selected out of options. + * + * @return The value that the user selected out of options. + */ + public Object getValue() + { + return value; + } + + /** + * This method returns whether this JOptionPane wants input. + * + * @return Whether this JOptionPane wants input. + */ + public boolean getWantsInput() + { + return wantsInput; + } + + /** + * This method returns a String that describes this JOptionPane. + * + * @return A String that describes this JOptionPane. + */ + protected String paramString() + { + return "JOptionPane"; + } + + /** + * This method requests focus for the initial value. + */ + public void selectInitialValue() + { + if (ui != null) + ((OptionPaneUI) ui).selectInitialValue(this); + } + + /** + * This method changes the icon property. + * + * @param newIcon The new icon to use. + */ + public void setIcon(Icon newIcon) + { + if (icon != newIcon) + { + Icon old = icon; + icon = newIcon; + firePropertyChange(ICON_PROPERTY, old, icon); + } + } + + /** + * This method changes the initial selection property. + * + * @param newValue The new initial selection. + */ + public void setInitialSelectionValue(Object newValue) + { + if (initialSelectionValue != newValue) + { + Object old = initialSelectionValue; + initialSelectionValue = newValue; + firePropertyChange(INITIAL_SELECTION_VALUE_PROPERTY, old, + initialSelectionValue); + } + } + + /** + * This method changes the initial value property. + * + * @param newValue The new initial value. + */ + public void setInitialValue(Object newValue) + { + if (initialValue != newValue) + { + Object old = initialValue; + initialValue = newValue; + firePropertyChange(INITIAL_VALUE_PROPERTY, old, initialValue); + } + } + + /** + * This method changes the inputValue property. + * + * @param newValue The new inputValue. + */ + public void setInputValue(Object newValue) + { + if (inputValue != newValue) + { + Object old = inputValue; + inputValue = newValue; + firePropertyChange(INPUT_VALUE_PROPERTY, old, inputValue); + } + } + + /** + * This method changes the message property. + * + * @param newMessage The new message. + */ + public void setMessage(Object newMessage) + { + if (message != newMessage) + { + Object old = message; + message = newMessage; + firePropertyChange(MESSAGE_PROPERTY, old, message); + } + } + + /** + * This method changes the messageType property. + * + * @param newType The new messageType. + * + * @throws IllegalArgumentException If the messageType is not valid. + */ + public void setMessageType(int newType) + { + if (! validMessageType(newType)) + throw new IllegalArgumentException("Message Type not legal value."); + if (newType != messageType) + { + int old = messageType; + messageType = newType; + firePropertyChange(MESSAGE_TYPE_PROPERTY, old, messageType); + } + } + + /** + * This method changes the options property. + * + * @param newOptions The new options. + */ + public void setOptions(Object[] newOptions) + { + if (options != newOptions) + { + Object[] old = options; + options = newOptions; + firePropertyChange(OPTIONS_PROPERTY, old, options); + } + } + + /** + * This method changes the optionType property. + * + * @param newType The new optionType. + * + * @throws IllegalArgumentException If the optionType is not valid. + */ + public void setOptionType(int newType) + { + if (! validOptionType(newType)) + throw new IllegalArgumentException("Option Type not legal value."); + if (newType != optionType) + { + int old = optionType; + optionType = newType; + firePropertyChange(OPTION_TYPE_PROPERTY, old, optionType); + } + } + + /** + * This method changes the Frame used for JOptionPane dialogs that have no + * parent. + * + * @param newRootFrame The Frame to use for dialogs that have no parent. + */ + public static void setRootFrame(Frame newRootFrame) + { + privFrame = newRootFrame; + } + + /** + * This method changes the selectionValues property. + * + * @param newValues The new selectionValues. + */ + public void setSelectionValues(Object[] newValues) + { + if (newValues != selectionValues) + { + if (newValues != null) + wantsInput = true; + Object[] old = selectionValues; + selectionValues = newValues; + firePropertyChange(SELECTION_VALUES_PROPERTY, old, selectionValues); + } + } + + /** + * This method sets the UI used with the JOptionPane. + * + * @param ui The UI used with the JOptionPane. + */ + public void setUI(OptionPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method sets the value has been selected out of options. + * + * @param newValue The value that has been selected out of options. + */ + public void setValue(Object newValue) + { + if (value != newValue) + { + Object old = value; + value = newValue; + firePropertyChange(VALUE_PROPERTY, old, value); + } + } + + /** + * This method changes the wantsInput property. + * + * @param newValue Whether this JOptionPane requires input. + */ + public void setWantsInput(boolean newValue) + { + if (wantsInput != newValue) + { + boolean old = wantsInput; + wantsInput = newValue; + firePropertyChange(WANTS_INPUT_PROPERTY, old, wantsInput); + } + } + + /** + * This method shows a confirmation dialog with the title "Select an Option" + * and displays the given message. The parent frame will be the same as the + * parent frame of the given parentComponent. This method returns the + * option chosen by the user. + * + * @param parentComponent The parentComponent to find a frame in. + * @param message The message to display. + * + * @return The option that was selected. + */ + public static int showConfirmDialog(Component parentComponent, Object message) + { + JOptionPane pane = new JOptionPane(message); + JDialog dialog = pane.createDialog(parentComponent, "Select an Option"); + + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, + * optionType and title. The frame that owns the dialog will be the same + * frame that holds the given parentComponent. This method returns the + * option that was chosen. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * + * @return The option that was chosen. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType) + { + JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, title, + * messageType and optionType. The frame owner will be the same frame as + * the one that holds the given parentComponent. This method returns the + * option selected by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messageType. + * + * @return The selected option. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, title, + * optionType, messageType and icon. The frame owner will be the same as + * the one that holds the given parentComponent. This method returns the + * option selected by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messsageType. + * @param icon The icon displayed. + * + * @return The selected option. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method will show a QUESTION_MESSAGE input dialog with the given + * message. No selectionValues is set so the Look and Feel will usually + * give the user a TextField to fill out. The frame owner will be the same + * frame that holds the given parentComponent. This method will return the + * value entered by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * + * @return The value entered by the user. + */ + public static String showInputDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method will show a QUESTION_MESSAGE type input dialog with the given + * message and initialSelectionValue. Since there is no selectionValues + * set, the Look and Feel will usually give a TextField to fill out. The + * frame owner will be the same as the one that holds the given + * parentComponent. This method will return the value entered by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message to display. + * @param initialSelectionValue The initially selected value. + * + * @return The value the user input. + */ + public static String showInputDialog(Component parentComponent, + Object message, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setInitialSelectionValue(initialSelectionValue); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method displays a new input dialog with the given message, title and + * messageType. Since no selectionValues value is given, the Look and Feel + * will usually give the user a TextField to input data to. This method + * returns the value the user inputs. + * + * @param parentComponent The component to find a frame in. + * @param message The message to display. + * @param title The title of the dialog. + * @param messageType The messageType. + * + * @return The value the user input. + */ + public static String showInputDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an input dialog with the given message, title, + * messageType, icon, selectionValues, and initialSelectionValue. This + * method returns the value that the user selects. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + * @param icon The icon displayed. + * @param selectionValues The list of values to select from. + * @param initialSelectionValue The initially selected value. + * + * @return The user selected value. + */ + public static Object showInputDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon, + Object[] selectionValues, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + pane.setIcon(icon); + pane.setSelectionValues(selectionValues); + pane.setInitialSelectionValue(initialSelectionValue); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows a QUESTION_MESSAGE type input dialog. Since no + * selectionValues is set, the Look and Feel will usually give the user a + * TextField to input data to. This method returns the value the user + * inputs. + * + * @param message The message to display. + * + * @return The user selected value. + */ + public static String showInputDialog(Object message) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(null, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows a QUESTION_MESSAGE type input dialog. Since no + * selectionValues is set, the Look and Feel will usually give the user a + * TextField to input data to. The input component will be initialized with + * the initialSelectionValue. This method returns the value the user + * inputs. + * + * @param message The message to display. + * @param initialSelectionValue The initialSelectionValue. + * + * @return The user selected value. + */ + public static String showInputDialog(Object message, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + pane.setInitialSelectionValue(initialSelectionValue); + JDialog dialog = pane.createDialog(null, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an internal confirmation dialog with the given message. + * The internal frame dialog will be placed in the first JDesktopPane + * ancestor of the given parentComponent. This method will return the value + * selected. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message to display. + * + * @return The value selected. + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message); + JInternalFrame frame = pane.createInternalFrame(parentComponent, null); + + startModal(frame, pane); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows an internal confirmation dialog with the given message, + * optionType and title. The internal frame dialog will be placed in the + * first JDesktopPane ancestor of the given parentComponent. This method + * will return the selected value. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param optionType The option type. + * + * @return The selected value. + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType) + { + JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows an internal confirmation dialog with the given message, + * title, optionTypes and icon for the given message type. The internal + * confirmation dialog will be placed in the first instance of + * JDesktopPane ancestor of the given parentComponent. + * + * @param parentComponent The component to find a JDesktopPane in. + * @param message The message to display. + * @param title The title of the dialog. + * @param optionType The option type. + * @param messageType The message type. + * + * @return The selected value. + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows an internal confirmation dialog with the given message, + * title, option type, message type, and icon. The internal frame dialog + * will be placed in the first JDesktopPane ancestor that is found in the + * given parentComponent. This method returns the selected value. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param optionType The option type. + * @param messageType The message type. + * @param icon The icon to display. + * + * @return The selected value. + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows an internal input dialog with the given message. The + * internal frame dialog will be placed in the first JDesktopPane ancestor + * of the given parent component. This method returns the value input by + * the user. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message to display. + * + * @return The user selected value. + */ + public static String showInternalInputDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message); + pane.setWantsInput(true); + JInternalFrame frame = pane.createInternalFrame(parentComponent, null); + + startModal(frame, pane); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an internal input dialog with the given message, title + * and message type. The internal input dialog will be placed in the first + * JDesktopPane ancestor found in the given parent component. This method + * will return the input value given by the user. + * + * @param parentComponent The component to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param messageType The message type. + * + * @return The user input value. + */ + public static String showInternalInputDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an internal input dialog with the given message, title + * message type, icon, selection value list and initial selection value. + * The internal frame dialog will be placed in the first JDesktopPane + * ancestor found in the given parent component. This method returns the + * input value from the user. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param messageType The message type. + * @param icon The icon to display. + * @param selectionValues The selection value list. + * @param initialSelectionValue The initial selection value. + * + * @return The user input value. + */ + public static Object showInternalInputDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon, + Object[] selectionValues, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + pane.setIcon(icon); + pane.setSelectionValues(selectionValues); + pane.setInitialSelectionValue(initialSelectionValue); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an internal message dialog with the given message. The + * internal frame dialog will be placed in the first JDesktopPane ancestor + * found in the given parent component. + * + * @param parentComponent The component to find a JDesktopPane in. + * @param message The message to display. + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message); + JInternalFrame frame = pane.createInternalFrame(parentComponent, null); + + startModal(frame, pane); + } + + /** + * This method shows an internal message dialog with the given message, + * title and message type. The internal message dialog is placed in the + * first JDesktopPane ancestor found in the given parent component. + * + * @param parentComponent The parent component to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param messageType The message type. + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + } + + /** + * This method shows an internal message dialog with the given message, + * title, message type and icon. The internal message dialog is placed in + * the first JDesktopPane ancestor found in the given parent component. + * + * @param parentComponent The component to find a JDesktopPane in. + * @param message The message to display. + * @param title The title to display. + * @param messageType The message type. + * @param icon The icon to display. + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setIcon(icon); + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + } + + /** + * This method displays an internal option dialog with the given message, + * title, option type, message type, icon, option list, and initial option + * value. The internal option dialog is placed in the first JDesktopPane + * ancestor found in the parent component. This method returns the option + * selected. + * + * @param parentComponent The parent to find a JDesktopPane in. + * @param message The message displayed. + * @param title The title displayed. + * @param optionType The option type. + * @param messageType The message type. + * @param icon The icon to display. + * @param options The array of options. + * @param initialValue The initial value selected. + * + * @return The option that was selected. + */ + public static int showInternalOptionDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon, Object[] options, + Object initialValue) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, + options, initialValue); + + JInternalFrame frame = pane.createInternalFrame(parentComponent, title); + + startModal(frame, pane); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows an INFORMATION_MESSAGE type message dialog. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + */ + public static void showMessageDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows a message dialog with the given message, title and + * messageType. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + */ + public static void showMessageDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows a message dialog with the given message, title, + * messageType and icon. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + * @param icon The icon displayed. + */ + public static void showMessageDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setIcon(icon); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows an option dialog with the given message, title, + * optionType, messageType, icon, options and initialValue. This method + * returns the option that was selected. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messageType. + * @param icon The icon displayed. + * @param options The options to choose from. + * @param initialValue The initial value. + * + * @return The selected option. + */ + public static int showOptionDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon, Object[] options, + Object initialValue) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, + options, initialValue); + + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method resets the UI to the Look and Feel default. + */ + public void updateUI() + { + setUI((OptionPaneUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns true if the key is a valid messageType. + * + * @param key The key to check. + * + * @return True if key is valid. + */ + private boolean validMessageType(int key) + { + switch (key) + { + case ERROR_MESSAGE: + case INFORMATION_MESSAGE: + case PLAIN_MESSAGE: + case QUESTION_MESSAGE: + case WARNING_MESSAGE: + return true; + } + return false; + } + + /** + * This method returns true if the key is a valid optionType. + * + * @param key The key to check. + * + * @return True if key is valid. + */ + private boolean validOptionType(int key) + { + switch (key) + { + case DEFAULT_OPTION: + case OK_CANCEL_OPTION: + case YES_NO_CANCEL_OPTION: + case YES_NO_OPTION: + return true; + } + return false; + } + + /** + * This helper method makes the JInternalFrame wait until it is notified by + * an InternalFrameClosing event. This method also adds the given + * JOptionPane to the JInternalFrame and sizes it according to the + * 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, JOptionPane pane) + { + f.getContentPane().add(pane); + f.pack(); + f.show(); + + Dimension pref = f.getPreferredSize(); + f.setBounds(0, 0, pref.width, pref.height); + + 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) + { + } + } + } +} diff --git a/libjava/classpath/javax/swing/JPanel.java b/libjava/classpath/javax/swing/JPanel.java new file mode 100644 index 0000000..c7f7c44 --- /dev/null +++ b/libjava/classpath/javax/swing/JPanel.java @@ -0,0 +1,114 @@ +/* JPanel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.FlowLayout; +import java.awt.LayoutManager; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.plaf.PanelUI; + +/** + * An instance of JPanel can be added to a panel, frame etc + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JPanel extends JComponent implements Accessible +{ + 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) + { + 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() + { + return null; + } + + protected String paramString() + { + return "JPanel"; + } +} diff --git a/libjava/classpath/javax/swing/JPasswordField.java b/libjava/classpath/javax/swing/JPasswordField.java new file mode 100644 index 0000000..f9df102 --- /dev/null +++ b/libjava/classpath/javax/swing/JPasswordField.java @@ -0,0 +1,270 @@ +/* JPasswordField.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; + +/** + * class JPasswordField + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class JPasswordField extends JTextField +{ + /** + * AccessibleJPasswordField + */ + protected class AccessibleJPasswordField extends AccessibleJTextField + { + private static final long serialVersionUID = -8477039424200681086L; + + /** + * Constructor AccessibleJPasswordField + */ + protected AccessibleJPasswordField() + { + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PASSWORD_TEXT; + } + } + + /** + * echoChar. Default is 0. + */ + private char echoChar = 0; + + /** + * Creates a JPasswordField object. + */ + public JPasswordField() + { + this(null, null, 0); + } + + /** + * Creates a JPasswordField object. + * + * @param text the initial text + */ + public JPasswordField(String text) + { + this(null, text, 0); + } + + /** + * Creates a JPasswordField object. + * + * @param columns the number of columns + */ + public JPasswordField(int columns) + { + this(null, null, columns); + } + + /** + * Creates a JPasswordField object. + * + * @param text the initial text + * @param columns the number of columns + */ + public JPasswordField(String text, int columns) + { + this(null, text, columns); + } + + /** + * Creates a JPasswordField object. + * + * @param document the document to use + * @param text the initial text + * @param columns the number of columns + */ + public JPasswordField(Document document, String text, int columns) + { + super(document, text, columns); + } + + /** + * writeObject + * + * @param stream the stream to write to + * + * @exception IOException if an error occurs + */ + private void writeObject(ObjectOutputStream stream) throws IOException + { + // TODO: Implement me. + } + + /** + * Returns the UIClassID + * + * @return the string "PasswordFieldUI" + */ + public String getUIClassID() + { + return "PasswordFieldUI"; + } + + /** + * getEchoChar + * + * @return the echo char + */ + public char getEchoChar() + { + return echoChar; + } + + /** + * setEchoChar + * + * @param echo the echo char + */ + public void setEchoChar(char echo) + { + this.echoChar = echo; + } + + /** + * echoCharIsSet + * + * @return true if the echo char is set, + * false otherwise. + */ + public boolean echoCharIsSet() + { + return echoChar == 0; + } + + /** + * Copies the selected text into the clipboard. This operation is not + * allowed in a password input field. + */ + public void copy() + { + UIManager.getLookAndFeel().provideErrorFeedback(this); + } + + /** + * Cuts the selected text and puts it into the clipboard. This operation + * is not allowed in a password input field. + */ + public void cut() + { + UIManager.getLookAndFeel().provideErrorFeedback(this); + } + + /** + * getText + * + * @return String + * + * @deprecated + */ + public String getText() + { + return null; // TODO + } + + /** + * getText + * + * @param offset TODO + * @param length TODO + * + * @return String + * + * @exception BadLocationException TODO + * + * @deprecated + */ + public String getText(int offset, int length) throws BadLocationException + { + return null; // TODO + } + + /** + * getPassword + * + * @return char[] + */ + public char[] getPassword() + { + return new char[0]; // TODO + } + + /** + * paramString + * + * @return String + */ + protected String paramString() + { + return null; // TODO + } + + /** + * getAccessibleContext + * + * @return the AccessibleContext object + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJPasswordField(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JPopupMenu.java b/libjava/classpath/javax/swing/JPopupMenu.java new file mode 100644 index 0000000..a0a7359 --- /dev/null +++ b/libjava/classpath/javax/swing/JPopupMenu.java @@ -0,0 +1,1071 @@ +/* JPopupMenu.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.PopupMenuUI; + +/** + * JPopupMenu is a container that is used to display popup menu's menu + * items. By default JPopupMenu is a lightweight container, however if it + * is the case that JPopupMenu's bounds are outside of main window, then + * heawyweight container will be used to display menu items. It is also + * possible to change JPopupMenu's default behavior and set JPopupMenu + * to always use heavyweight container. + * + * JPopupMenu can be displayed anywhere; it is a floating free popup menu. + * However before JPopupMenu is diplayed, its invoker property should be set. + * JPopupMenu's invoker is a component relative to which popup menu is + * displayed. + * + * JPopupMenu fires PopupMenuEvents to its registered listeners. Whenever + * JPopupMenu becomes visible on the screen then PopupMenuEvent indicating + * that popup menu became visible will be fired. In the case when + * JPopupMenu becomes invisible or cancelled without selection, then + * popupMenuBecomeInvisible() or popupMenuCancelled() methods of + * PopupMenuListeners will be invoked. + * + * JPopupMenu also fires PropertyChangeEvents when its bound properties + * change.In addittion to inheritted bound properties, JPopupMenu has + * 'visible' bound property. When JPopupMenu becomes visible/invisible on + * the screen it fires PropertyChangeEvents to its registered + * PropertyChangeListeners. + */ +public class JPopupMenu extends JComponent implements Accessible, MenuElement +{ + private static final long serialVersionUID = -8336996630009646009L; + + /* indicates if popup's menu border should be painted*/ + private boolean borderPainted = true; + + /** Flag indicating whether lightweight, mediumweight or heavyweight popup + is used to display menu items. + + These are the possible cases: + + 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. + + 2. if DefaultLightWeightPopupEnabled false + (i) if popup fits, use awt.Panel (mediumWeight) + (ii) if popup doesn't fit, use JWindow (heavyWeight) + */ + private static boolean DefaultLightWeightPopupEnabled = true; + + /* Component that invokes popup menu. */ + transient Component invoker; + + /* Label for this popup menu. It is not used in most of the look and feel themes. */ + private String label; + + /*Amount of space between menuItem's in JPopupMenu and JPopupMenu's border */ + private Insets margin; + + /** Indicates whether ligthWeight container can be used to display popup + menu. This flag is the same as DefaultLightWeightPopupEnabled, but setting + this flag can change popup menu after creation of the object */ + private boolean lightWeightPopupEnabled; + + /** SelectionModel that keeps track of menu selection. */ + private SingleSelectionModel selectionModel; + + /* Popup that is used to display JPopupMenu */ + private transient Popup popup; + + /* Location of the popup */ + private Point popupLocation; + + /* Field indicating if popup menu is visible or not */ + private boolean visible = false; + + /** + * Creates a new JPopupMenu object. + */ + public JPopupMenu() + { + this(null); + } + + /** + * Creates a new JPopupMenu with specified label + * + * @param label Label for popup menu. + */ + public JPopupMenu(String label) + { + lightWeightPopupEnabled = getDefaultLightWeightPopupEnabled(); + setLabel(label); + setSelectionModel(new DefaultSingleSelectionModel()); + super.setVisible(false); + updateUI(); + } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + } + + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * Adds given menu item to the popup menu + * + * @param item menu item to add to the popup menu + * + * @return menu item that was added to the popup menu + */ + public JMenuItem add(JMenuItem item) + { + this.insert(item, -1); + return item; + } + + /** + * Constructs menu item with a specified label and adds it to + * popup menu + * + * @param text label for the menu item to be added + * + * @return constructed menu item that was added to the popup menu + */ + public JMenuItem add(String text) + { + JMenuItem item = new JMenuItem(text); + return add(item); + } + + /** + * Constructs menu item associated with the specified action + * and adds it to the popup menu + * + * @param action Action for the new menu item + * + * @return menu item that was added to the menu + */ + public JMenuItem add(Action action) + { + JMenuItem item = createActionComponent(action); + + if (action != null) + action.addPropertyChangeListener(createActionChangeListener(item)); + + return add(item); + } + + /** + * Revomes component at the given index from the menu. + * + * @param index index of the component that will be removed in the menu + */ + 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); + } + } + + /** + * Create menu item associated with the given action + * and inserts it into the popup menu at the specified index + * + * @param action Action for the new menu item + * @param index index in the popup menu at which to insert new menu item. + */ + public void insert(Action action, int index) + { + JMenuItem item = new JMenuItem(action); + this.insert(item, index); + } + + /** + * Insert given component to the popup menu at the + * specified index + * + * @param component Component to insert + * @param index Index at which to insert given component + */ + 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); + } + } + } + + /** + * Returns flag indicating if newly created JPopupMenu will use + * heavyweight or lightweight container to display its menu items + * + * @return true if JPopupMenu will use lightweight container to display + * menu items by default, and false otherwise. + */ + public static boolean getDefaultLightWeightPopupEnabled() + { + return DefaultLightWeightPopupEnabled; + } + + /** + * Sets whether JPopupMenu should use ligthWeight container to + * display it menu items by default + * + * @param enabled true if JPopupMenu should use lightweight container + * for displaying its menu items, and false otherwise. + */ + public static void setDefaultLightWeightPopupEnabled(boolean enabled) + { + DefaultLightWeightPopupEnabled = enabled; + } + + /** + * This method returns the UI used to display the JPopupMenu. + * + * @return The UI used to display the JPopupMenu. + */ + public PopupMenuUI getUI() + { + return (PopupMenuUI) ui; + } + + /** + * Set the "UI" property of the menu item, which is a look and feel class + * responsible for handling popupMenu's input events and painting it. + * + * @param ui The new "UI" property + */ + public void setUI(PopupMenuUI ui) + { + super.setUI(ui); + } + + /** + * This method sets this menuItem's UI to the UIManager's default for the + * current look and feel. + */ + public void updateUI() + { + setUI((PopupMenuUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for the menuItem. + * + * @return The Look and Feel classID. "PopupMenuUI" + */ + public String getUIClassID() + { + return "PopupMenuUI"; + } + + /** + * Returns selectionModel used by this popup menu to keep + * track of the selection. + * + * @return popup menu's selection model + */ + public SingleSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * Sets selection model for this popup menu + * + * @param model new selection model of this popup menu + */ + public void setSelectionModel(SingleSelectionModel model) + { + selectionModel = model; + } + + /** + * Creates new menu item associated with a given action. + * + * @param action Action used to create new menu item + * + * @return new created menu item associated with a given action. + */ + protected JMenuItem createActionComponent(Action action) + { + return new JMenuItem(action); + } + + /** + * Creates PropertyChangeListener that listens to PropertyChangeEvents + * occuring in the Action associated with given menu item in this popup menu. + * + * @param item MenuItem + * + * @return The PropertyChangeListener + */ + protected PropertyChangeListener createActionChangeListener(JMenuItem item) + { + return new ActionChangeListener(); + } + + /** + * Returns true if this popup menu will display its menu item in + * a lightweight container and false otherwise. + * + * @return true if this popup menu will display its menu items + * in a lightweight container and false otherwise. + */ + public boolean isLightWeightPopupEnabled() + { + return lightWeightPopupEnabled; + } + + /** + * DOCUMENT ME! + * + * @param enabled DOCUMENT ME! + */ + public void setLightWeightPopupEnabled(boolean enabled) + { + lightWeightPopupEnabled = enabled; + } + + /** + * Returns label for this popup menu + * + * @return label for this popup menu + */ + public String getLabel() + { + return label; + } + + /** + * Sets label for this popup menu. This method fires PropertyChangeEvent + * when the label property is changed. Please note that most + * of the Look & Feel will ignore this property. + * + * @param label label for this popup menu + */ + public void setLabel(String label) + { + if (label != this.label) + { + String oldLabel = this.label; + this.label = label; + firePropertyChange("label", oldLabel, label); + } + } + + /** + * Adds separator to this popup menu + */ + public void addSeparator() + { + // insert separator at the end of the list of menu items + this.insert(new Separator(), -1); + } + + /** + * Adds popupMenuListener to listen for PopupMenuEvents fired + * by the JPopupMenu + * + * @param listener PopupMenuListener to add to JPopupMenu + */ + public void addPopupMenuListener(PopupMenuListener listener) + { + listenerList.add(PopupMenuListener.class, listener); + } + + /** + * Removes PopupMenuListener from JPopupMenu's list of listeners + * + * @param listener PopupMenuListener which needs to be removed + */ + public void removePopupMenuListener(PopupMenuListener listener) + { + listenerList.remove(PopupMenuListener.class, listener); + } + + /** + * Returns array of PopupMenuListeners that are listening to JPopupMenu + * + * @return Array of PopupMenuListeners that are listening to JPopupMenu + */ + public PopupMenuListener[] getPopupMenuListeners() + { + return ((PopupMenuListener[]) listenerList.getListeners(PopupMenuListener.class)); + } + + /** + * This method calls popupMenuWillBecomeVisible() of popup menu's + * PopupMenuListeners. This method is invoked just before popup menu + * will appear on the screen. + */ + protected void firePopupMenuWillBecomeVisible() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuWillBecomeVisible(new PopupMenuEvent(this)); + } + + /** + * This method calls popupMenuWillBecomeInvisible() of popup + * menu's PopupMenuListeners. This method is invoked just before popup + * menu will disappear from the screen + */ + protected void firePopupMenuWillBecomeInvisible() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this)); + } + + /** + * This method calls popupMenuCanceled() of popup menu's PopupMenuListeners. + * This method is invoked just before popup menu is cancelled. This happens + * when popup menu is closed without selecting any of its menu items. This + * usually happens when the top-level window is resized or moved. + */ + protected void firePopupMenuCanceled() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuCanceled(new PopupMenuEvent(this)); + } + + /** + * This methods sets popup menu's size to its' preferred size. If the + * popup menu's size is previously set it will be ignored. + */ + public void pack() + { + super.setSize(null); + } + + /** + * Return visibility of the popup menu + * + * @return true if popup menu is visible on the screen and false otherwise. + */ + public boolean isVisible() + { + return visible; + } + + /** + * Sets visibility property of this popup menu. If the property is + * set to true then popup menu will be dispayed and popup menu will + * hide itself if visible property is set to false. + * + * @param visible true if popup menu will become visible and false otherwise. + */ + public void setVisible(boolean visible) + { + if (visible == isVisible()) + return; + + boolean old = isVisible(); + 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(); + } + } + } + + /** + * Sets location of the popup menu. + * + * @param x X coordinate of the popup menu's location + * @param y Y coordinate of the popup menu's location + */ + public void setLocation(int x, int y) + { + if (popupLocation == null) + popupLocation = new Point(); + + popupLocation.x = x; + popupLocation.y = y; + } + + /** + * Returns popup menu's invoker. + * + * @return popup menu's invoker + */ + public Component getInvoker() + { + return invoker; + } + + /** + * Sets popup menu's invoker. + * + * @param component The new invoker of this popup menu + */ + public void setInvoker(Component component) + { + invoker = component; + } + + /** + * This method displays JPopupMenu on the screen at the specified + * location. Note that x and y coordinates given to this method + * should be expressed in terms of the popup menus' invoker. + * + * @param component Invoker for this popup menu + * @param x x-coordinate of the popup menu relative to the specified invoker + * @param y y-coordiate of the popup menu relative to the specified invoker + */ + 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); + } + + /** + * Returns component located at the specified index in the popup menu + * + * @param index index of the component to return + * + * @return component located at the specified index in the popup menu + * + * @deprecated Replaced by getComponent(int) + */ + public Component getComponentAtIndex(int index) + { + return getComponent(index); + } + + /** + * Returns index of the specified component in the popup menu + * + * @param component Component to look for + * + * @return index of the specified component in the popup menu + */ + public int getComponentIndex(Component component) + { + Component[] items = getComponents(); + + for (int i = 0; i < items.length; i++) + { + if (items[i].equals(component)) + return i; + } + + return -1; + } + + /** + * Sets size of the popup + * + * @param size Dimensions representing new size of the popup menu + */ + public void setPopupSize(Dimension size) + { + super.setSize(size); + } + + /** + * Sets size of the popup menu + * + * @param width width for the new size + * @param height height for the new size + */ + public void setPopupSize(int width, int height) + { + super.setSize(width, height); + } + + /** + * Selects specified component in this popup menu. + * + * @param selected component to select + */ + public void setSelected(Component selected) + { + int index = getComponentIndex(selected); + selectionModel.setSelectedIndex(index); + } + + /** + * Checks if this popup menu paints its border. + * + * @return true if this popup menu paints its border and false otherwise. + */ + public boolean isBorderPainted() + { + return borderPainted; + } + + /** + * Sets if the border of the popup menu should be + * painter or not. + * + * @param painted true if the border should be painted and false otherwise + */ + public void setBorderPainted(boolean painted) + { + borderPainted = painted; + } + + /** + * Returns margin for this popup menu. + * + * @return margin for this popup menu. + */ + public Insets getMargin() + { + return margin; + } + + /** + * A string that describes this JPopupMenu. Normally only used + * for debugging. + * + * @return A string describing this JMenuItem + */ + protected String paramString() + { + StringBuffer sb = new StringBuffer(); + sb.append(super.paramString()); + sb.append(",label="); + if (getLabel() != null) + sb.append(getLabel()); + sb.append(",lightWeightPopupEnabled=").append(isLightWeightPopupEnabled()); + sb.append(",margin="); + if (getMargin() != null) + sb.append(margin); + sb.append(",paintBorder=").append(isBorderPainted()); + return sb.toString(); + } + + /** + * Process mouse events forwarded from MenuSelectionManager. This method + * doesn't do anything. It is here to conform to the MenuElement interface. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + */ + public void processMouseEvent(MouseEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Empty Implementation. This method is needed for the implementation + // of MenuElement interface + } + + /** + * Process key events forwarded from MenuSelectionManager. This method + * doesn't do anything. It is here to conform to the MenuElement interface. + * + * @param event event forwarded from MenuSelectionManager + * @param path path to the menu element from which event was generated + * @param manager MenuSelectionManager for the current menu hierarchy + * + */ + public void processKeyEvent(KeyEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Empty Implementation. This method is needed for the implementation + // of MenuElement interface + } + + /** + * Method of MenuElement Interface. It is invoked when + * popupMenu's selection has changed + * + * @param changed true if this popupMenu is part of current menu + * hierarchy and false otherwise. + */ + public void menuSelectionChanged(boolean changed) + { + if (! changed) + setVisible(false); + } + + /** + * Return subcomonents of this popup menu. This method returns only + * components that implement the MenuElement interface. + * + * @return array of menu items belonging to this popup menu + */ + public MenuElement[] getSubElements() + { + Component[] items = getComponents(); + ArrayList subElements = new ArrayList(); + + for (int i = 0; i < items.length; i++) + if (items[i] instanceof MenuElement) + subElements.add(items[i]); + + return (MenuElement[]) + subElements.toArray(new MenuElement[subElements.size()]); + } + + /** + * Method of the MenuElement interface. Returns reference to itself. + * + * @return Returns reference to itself + */ + public Component getComponent() + { + return this; + } + + /** + * Checks if observing mouse event should trigger popup + * menu to show on the screen. + * + * @param event MouseEvent to check + * + * @return true if the observing mouse event is popup trigger and false otherwise + */ + public boolean isPopupTrigger(MouseEvent event) + { + return ((PopupMenuUI) getUI()).isPopupTrigger(event); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJPopupMenu(); + + return accessibleContext; + } + + /** + * 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 + { + /** + * Creates a new LightWeightPopup menu + * + * @param c Container containing menu items + */ + private Component c; + + 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() + { + } + + public String getUIClassID() + { + return "PopupMenuSeparatorUI"; + } + } + + protected class AccessibleJPopupMenu extends AccessibleJComponent + { + private static final long serialVersionUID = 7423261328879849768L; + + protected AccessibleJPopupMenu() + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.POPUP_MENU; + } + } + + /* This class resizes popup menu and repaints popup menu appropriately if one + of item's action has changed */ + protected class ActionChangeListener implements PropertyChangeListener + { + public void propertyChange(PropertyChangeEvent evt) + { + JPopupMenu.this.revalidate(); + JPopupMenu.this.repaint(); + } + } +} diff --git a/libjava/classpath/javax/swing/JProgressBar.java b/libjava/classpath/javax/swing/JProgressBar.java new file mode 100644 index 0000000..1b8fcea --- /dev/null +++ b/libjava/classpath/javax/swing/JProgressBar.java @@ -0,0 +1,661 @@ +/* JProgressBar.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Graphics; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ProgressBarUI; + +/** + * The ProgressBar is a widget that displays in two modes. In + * determinate mode, it displays fills a percentage of its bar + * based on its current value. In indeterminate mode, it creates + * box and bounces it between its bounds. + * + *

+ * JProgressBars have the following properties: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Property Stored in Bound?
borderPainted progressBar yes
changeListeners progressBar no
indeterminate progressBar yes
maximum model no
minimum model no
model progressBar no
orientation progressBar yes
percentComplete progressBar no
string progressBar yes
stringPainted progressBar yes
value model no
+ */ +public class JProgressBar extends JComponent implements SwingConstants, + Accessible +{ + /** + * AccessibleJProgressBar + */ + protected class AccessibleJProgressBar extends AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = -2938130009392721813L; + + /** + * Constructor AccessibleJProgressBar + */ + protected AccessibleJProgressBar() + { + } + + /** + * getAccessibleStateSet + * + * @return AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PROGRESS_BAR; + } + + /** + * getAccessibleValue + * + * @return AccessibleValue + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * getCurrentAccessibleValue + * + * @return Number + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * setCurrentAccessibleValue + * + * @param value0 TODO + * + * @return boolean + */ + public boolean setCurrentAccessibleValue(Number value0) + { + return false; + } + + /** + * getMinimumAccessibleValue + * + * @return Number + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * getMaximumAccessibleValue + * + * @return Number + */ + public Number getMaximumAccessibleValue() + { + return null; + } + } + + private static final long serialVersionUID = 1980046021813598781L; + + /** Whether the ProgressBar is determinate. */ + private transient boolean indeterminate = false; + + /** The orientation of the ProgressBar */ + protected int orientation = HORIZONTAL; + + /** Whether borders should be painted. */ + protected boolean paintBorder = true; + + /** The model describing this ProgressBar. */ + protected BoundedRangeModel model; + + /** The string that is displayed by the ProgressBar. */ + protected String progressString; + + /** Whether the string should be painted. */ + protected boolean paintString = false; + + /** The static changeEvent passed to all ChangeListeners. */ + protected transient ChangeEvent changeEvent; + + /** The ChangeListener that listens to the model. */ + protected ChangeListener changeListener; + + /** + * Creates a new horizontally oriented JProgressBar object + * with a minimum of 0 and a maximum of 100. + */ + public JProgressBar() + { + this(HORIZONTAL, 0, 100); + } + + /** + * Creates a new JProgressBar object with a minimum of 0, + * a maximum of 100, and the given orientation. + * + * @param orientation The orientation of the JProgressBar. + * + * @throws IllegalArgumentException if orientation is not either + * {@link #HORIZONTAL} or {@link #VERTICAL}. + */ + public JProgressBar(int orientation) + { + this(orientation, 0, 100); + } + + /** + * Creates a new horizontally oriented JProgressBar object + * with the given minimum and maximum. + * + * @param minimum The minimum of the JProgressBar. + * @param maximum The maximum of the JProgressBar. + */ + public JProgressBar(int minimum, int maximum) + { + this(HORIZONTAL, minimum, maximum); + } + + /** + * Creates a new JProgressBar object with the given minimum, + * maximum, and orientation. + * + * @param minimum The minimum of the JProgressBar. + * @param maximum The maximum of the JProgressBar. + * @param orientation The orientation of the JProgressBar. + * + * @throws IllegalArgumentException if orientation is not either + * {@link #HORIZONTAL} or {@link #VERTICAL}. + */ + public JProgressBar(int orientation, int minimum, int maximum) + { + model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum); + if (orientation != HORIZONTAL && orientation != VERTICAL) + throw new IllegalArgumentException(orientation + " is not a legal orientation"); + this.orientation = orientation; + changeListener = createChangeListener(); + model.addChangeListener(changeListener); + updateUI(); + } + + /** + * Creates a new horizontally oriented JProgressBar object + * with the given model. + * + * @param model The model to be used with the JProgressBar. + */ + public JProgressBar(BoundedRangeModel model) + { + this.model = model; + changeListener = createChangeListener(); + model.addChangeListener(changeListener); + updateUI(); + } + + /** + * This method returns the current value of the JProgressBar. + * + * @return The current value of the JProgressBar. + */ + public int getValue() + { + return model.getValue(); + } + + /** + * This method sets the value of the JProgressBar. + * + * @param value The value of the JProgressBar. + */ + public void setValue(int value) + { + model.setValue(value); + } + + /** + * This method paints the border of the JProgressBar + * + * @param graphics The graphics object to paint with. + */ + protected void paintBorder(Graphics graphics) + { + Border border = getBorder(); + if (paintBorder && border != null) + border.paintBorder(this, graphics, 0, 0, + getWidth(), + getHeight()); + } + + /** + * This method returns the orientation of the JProgressBar. + * + * @return The orientation of the JProgressBar. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method changes the orientation property. The orientation of the + * JProgressBar can be either horizontal or vertical. + * + * @param orientation The orientation of the JProgressBar. + */ + public void setOrientation(int orientation) + { + if (orientation != VERTICAL && orientation != HORIZONTAL) + throw new IllegalArgumentException("orientation must be one of VERTICAL or HORIZONTAL"); + if (this.orientation != orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange("orientation", oldOrientation, + this.orientation); + } + } + + /** + * This method returns whether the progressString will be painted. + * + * @return Whether the string is painted. + */ + public boolean isStringPainted() + { + return paintString; + } + + /** + * This method changes the stringPainted property. + * + * @param painted Whether the string is painted. + */ + public void setStringPainted(boolean painted) + { + if (paintString != painted) + { + boolean oldPainted = paintString; + paintString = painted; + firePropertyChange("stringPainted", oldPainted, + paintString); + } + } + + /** + * This method returns the string that is painted if the + * stringPainted property is set to true. If there is no + * string set, it will return a string containing the + * JProgressBar's value as a percent. + * + * @return The string that is painted. + */ + public String getString() + { + if (progressString != null) + return progressString; + else + return (int) (getPercentComplete() * 100) + "%"; + } + + /** + * This method changes the string property. The string + * given will be the one painted. If you want to + * revert to the default string given, set the + * string to null. + * + * @param string The string to be painted. + */ + public void setString(String string) + { + if (((string == null || progressString == null) && + string != progressString) || (string != null && + ! string.equals(progressString))) + { + String oldString = progressString; + progressString = string; + firePropertyChange("string", oldString, progressString); + } + } + + /** + * This method returns the percent of the bar + * that is "complete". (This is the amount value / (max - min)). + * + * @return DOCUMENT ME! + */ + public double getPercentComplete() + { + if (getMaximum() == getMinimum()) + return 1.0; + else + return (double) (model.getValue() - model.getMinimum()) / (model + .getMaximum() + - model.getMinimum()); + } + + /** + * This method returns whether the border is painted. + * + * @return Whether the border is painted. + */ + public boolean isBorderPainted() + { + return paintBorder; + } + + /** + * This method changes the borderPainted property. + * + * @param painted Whether the border is painted. + */ + public void setBorderPainted(boolean painted) + { + if (painted != paintBorder) + { + boolean oldPainted = paintBorder; + paintBorder = painted; + firePropertyChange("borderPainted", oldPainted, + paintBorder); + } + } + + /** + * This method returns the JProgressBar's UI delegate. + * + * @return This JProgressBar's UI delegate. + */ + public ProgressBarUI getUI() + { + return (ProgressBarUI) ui; + } + + /** + * This method changes the UI property for this JProgressBar. + * + * @param ui The new UI delegate. + */ + public void setUI(ProgressBarUI ui) + { + super.setUI(ui); + } + + /** + * This method reverts the UI delegate for this JProgressBar + * to the default for this Look and Feel. + */ + public void updateUI() + { + setUI((ProgressBarUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns the identifier to allow the UIManager + * to pick the correct class to act as the UI for + * this JProgressBar. + * + * @return The UIClassID: "ProgressBarUI". + */ + public String getUIClassID() + { + return "ProgressBarUI"; + } + + /** + * This method returns a ChangeListener that gets registered + * model. By default, the ChangeListener, propagates the + * ChangeEvents to the ChangeListeners of the JProgressBar. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener() + { + return new ChangeListener() + { + public void stateChanged(ChangeEvent ce) + { + fireStateChanged(); + } + }; + } + + /** + * This method adds a ChangeListener to this JProgressBar. + * + * @param listener The ChangeListener to add to this JProgressBar. + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * This method removes a ChangeListener from this JProgressBar. + * + * @param listener The ChangeListener to remove from this JProgressBar. + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * This method returns an array of all ChangeListeners listening to this + * progress bar. + * + * @return An array of ChangeListeners listening to this progress bar. + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * This method is called when the JProgressBar receives a ChangeEvent + * from its model. This simply propagates the event (changing the source + * to the JProgressBar) to the JProgressBar's listeners. + */ + protected void fireStateChanged() + { + Object[] changeListeners = listenerList.getListenerList(); + if (changeEvent == null) + changeEvent = new ChangeEvent(this); + for (int i = changeListeners.length - 2; i >= 0; i -= 2) + { + if (changeListeners[i] == ChangeListener.class) + ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent); + } + } + + /** + * This method returns the model used with this JProgressBar. + * + * @return The model used with this JProgressBar. + */ + public BoundedRangeModel getModel() + { + return model; + } + + /** + * This method changes the model property for this JProgressBar. + * + * @param model The model to use with this JProgressBar. + */ + public void setModel(BoundedRangeModel model) + { + if (model != this.model) + { + this.model.removeChangeListener(changeListener); + this.model = model; + this.model.addChangeListener(changeListener); + fireStateChanged(); + } + } + + /** + * This method returns the minimum value of this JProgressBar. + * + * @return The minimum value of this JProgressBar. + */ + public int getMinimum() + { + return model.getMinimum(); + } + + /** + * This method sets the minimum value of this JProgressBar. + * + * @param minimum The minimum value of this JProgressBar. + */ + public void setMinimum(int minimum) + { + model.setMinimum(minimum); + } + + /** + * This method returns the maximum value of this JProgressBar. + * + * @return The maximum value of this JProgressBar. + */ + public int getMaximum() + { + return model.getMaximum(); + } + + /** + * This method sets the maximum value of this JProgressBar. + * + * @param maximum The maximum value of this JProgressBar. + */ + public void setMaximum(int maximum) + { + model.setMaximum(maximum); + } + + /** + * This method returns a string that can be used to + * describe this JProgressBar. This method is usually + * only used for debugging purposes. + * + * @return A string that describes this JProgressBar. + */ + protected String paramString() + { + return "JProgressBar"; + } + + /** + * This method changes the indeterminate property. If the + * JProgressBar is determinate, it paints a percentage + * of the bar described by its value. If it is indeterminate, + * it simply bounces a box between the ends of the bar; the + * value of the JProgressBar is ignored. + * + * @param newValue Whether the JProgressBar is indeterminate. + */ + public void setIndeterminate(boolean newValue) + { + if (indeterminate != newValue) + { + boolean olddeter = indeterminate; + indeterminate = newValue; + firePropertyChange("indeterminate", olddeter, + indeterminate); + } + } + + /** + * This method returns whether the JProgressBar is indeterminate. + * + * @return Whether this JProgressBar is indeterminate. + */ + public boolean isIndeterminate() + { + return indeterminate; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJProgressBar(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JRadioButton.java b/libjava/classpath/javax/swing/JRadioButton.java new file mode 100644 index 0000000..66f5902 --- /dev/null +++ b/libjava/classpath/javax/swing/JRadioButton.java @@ -0,0 +1,259 @@ +/* JRadioButton.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.plaf.ButtonUI; + +/** + * The JRadioButton component provides a visually selectable + * button with mutually exclusive behaviour within a ButtonGroup. + * A series of radio buttons can be used to provide options to the user, + * where the user can only select one of the available options. The state + * of the button is provided by the superclass, JToggleButton. + * JRadioButton adds the additional behaviour, that if two + * or more radio buttons are grouped together, the selection of one implies + * the deselection of the other buttons within the group. + *

+ * + * Buttons are grouped by adding each instance to a ButtonGroup. + * The existence of such a grouping is not reflected visually, so other means + * should be used to denote this. For instance, the grouped buttons can be placed + * within the same panel, possibly with an appropriate border to denote + * the connection between the components. + * + * @author Michael Koch (konqueror@gmx.de) + * @author Graydon Hoare (graydon@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see JToggleButton + * @see ButtonGroup + * @since 1.2 + */ +public class JRadioButton extends JToggleButton +{ + /** + * Compatible with Sun's JDK. + */ + private static final long serialVersionUID = 7751949583255506856L; + + /** + * This class provides accessibility support for the toggle button. + */ + protected class AccessibleJRadioButton + extends AccessibleJToggleButton + { + private static final long serialVersionUID = 4850967637026120674L; + + /** + * Constructor for the accessible toggle button. + */ + protected AccessibleJRadioButton() + { + /* Call the superclass to register for events */ + super(); + } + + /** + * Returns the accessible role for the toggle button. + * + * @return An instance of AccessibleRole, describing + * the role of the toggle button. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.RADIO_BUTTON; + } + + } + + /** + * Constructs an unselected radio button with no text or icon. + */ + public JRadioButton() + { + this(null, null, false); + } + + /** + * Constructs a radio button using the labelling, state + * and icon specified by the supplied action. + * + * @param a the action to use to define the properties of the button. + */ + public JRadioButton(Action a) + { + this(); + setAction(a); + } + + /** + * Constructs an unselected radio button with the supplied icon + * and no text. + * + * @param icon the icon to use. + */ + public JRadioButton(Icon icon) + { + this(null, icon, false); + } + + /** + * Constructs a radio button with the supplied icon and state. + * + * @param icon the icon to use. + * @param selected if true, the radio button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JRadioButton(Icon icon, boolean selected) + { + this(null, icon, selected); + } + + /** + * Constructs an unselected radio button using the supplied text + * and no icon. + * + * @param text the text to use. + */ + public JRadioButton(String text) + { + this(text, null, false); + } + + /** + * Constructs a radio button with the supplied text and state. + * + * @param text the text to use. + * @param selected if true, the radio button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JRadioButton(String text, boolean selected) + { + this(text, null, selected); + } + + /** + * Constructs an unselected radio button with the supplied text + * and icon. + * + * @param text the text to use. + * @param icon the icon to use. + */ + public JRadioButton(String text, Icon icon) + { + this(text, icon, false); + } + + /** + * Constructs a radio button with the supplied text, icon and state. + * + * @param text the text to use. + * @param icon the icon to use. + * @param selected if true, the radio button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JRadioButton(String text, Icon icon, boolean selected) + { + super(text, icon, selected); + borderPainted = false; + contentAreaFilled = false; + } + + /** + * Returns the accessible context for this JRadioButton, + * in the form of an instance of AccessibleJRadioButton. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + { + /* Create the context */ + accessibleContext = new AccessibleJRadioButton(); + } + return accessibleContext; + } + + /** + * Returns a string specifying the name of the Look and Feel UI class + * that renders this component. + * + * @return the Look and Feel UI class for JRadioButtons + * as a String. + */ + public String getUIClassID() + { + return "RadioButtonUI"; + } + + /** + * Returns a string representation of this component for debugging use. + * Users should not depend on anything as regards the content or formatting + * of this string, except for the fact that the returned string may never be + * null (only empty). + * + * @return the component in String form for debugging. + */ + protected String paramString() + { + return super.paramString(); + } + + /** + * This method resets the radio button's UI delegate to the default UI for + * the current look and feel. + */ + public void updateUI() + { + /* + I can't see any difference between this and the superclass one, + but Sun reimplements it... there is no RadioButtonUI class for it + to be cast to. + */ + setUI((ButtonUI) UIManager.getUI(this)); + } + +} + + + diff --git a/libjava/classpath/javax/swing/JRadioButtonMenuItem.java b/libjava/classpath/javax/swing/JRadioButtonMenuItem.java new file mode 100644 index 0000000..76a8fef --- /dev/null +++ b/libjava/classpath/javax/swing/JRadioButtonMenuItem.java @@ -0,0 +1,212 @@ +/* JRadioButtonMenuItem.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class represents JRadioButtonMenuItem. Its behaviour is very similar + * to JRadioButton. Just like JRadioButton, user can check and uncheck this + * menu item by clicking on it. JRadioButtonMenuItem uses ToggleButtonModel + * to keep track of its selection. If the JRadioButtonMenuItem is included in + * the button group, then only one JRadioButtonMenuItem can be selected at + * one time. + */ +public class JRadioButtonMenuItem extends JMenuItem implements Accessible +{ + private static final long serialVersionUID = 8482658191548521743L; + + /** name for the UI delegate for this radio button menu item. */ + private static final String uiClassID = "RadioButtonMenuItemUI"; + + /** + * Creates a new JRadioButtonMenuItem object. + */ + public JRadioButtonMenuItem() + { + this(null, null); + } + + /** + * Creates a new JRadioButtonMenuItem with specified icon + * + * @param icon Icon to be used for this menu item + */ + public JRadioButtonMenuItem(Icon icon) + { + this(null, icon); + } + + /** + * Creates a new JRadioButtonMenuItem with specified label + * + * @param text Label for this menu item + */ + public JRadioButtonMenuItem(String text) + { + this(text, null); + } + + /** + * Creates a new JRadioButtonMenuItem using specified action + * + * @param action Action for this menu item + */ + public JRadioButtonMenuItem(Action action) + { + this(); + setAction(action); + } + + /** + * Creates a new JRadioButtonMenuItem with specified label and icon + * + * @param text Label for this menu item + * @param icon Icon for this menu item + */ + public JRadioButtonMenuItem(String text, Icon icon) + { + this(text, icon, false); + } + + /** + * Creates a new JRadioButtonMenuItem with specified label + * and marked selected if 'selected' is true. + * + * @param text Text for this menu item + * @param selected Selected state of this menu item + */ + public JRadioButtonMenuItem(String text, boolean selected) + { + this(text, null, selected); + } + + /** + * Creates a new JRadioButtonMenuItem with specified icon + * and given selected state + * + * @param icon Icon for this menu item + * @param selected Selected state for this menu item + */ + public JRadioButtonMenuItem(Icon icon, boolean selected) + { + this(null, icon, selected); + } + + /** + * Creates a new JRadioButtonMenuItem with specified label, + * icon and selected state. + * + * @param text Label for this menu item + * @param icon Icon to be use for this menu item + * @param selected selected state of this menu item + */ + public JRadioButtonMenuItem(String text, Icon icon, boolean selected) + { + super(text, icon); + setModel(new JToggleButton.ToggleButtonModel()); + 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. + * + * @return The Look and Feel classID. "JRadioButtonMenuItemUI" + */ + public String getUIClassID() + { + return uiClassID; + } + + /** + * This method overrides JComponent.requestFocus with an empty + * implementation, since JRadioButtonMenuItems should not + * receve focus in general. + */ + public void requestFocus() + { + // Should do nothing here + } + + /** + * A string that describes this JRadioButtonMenuItem. Normally only used + * for debugging. + * + * @return A string describing this JRadioButtonMenuItem + */ + protected String paramString() + { + return "JRadioButtonMenuItem"; + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJRadioButtonMenuItem(); + + return accessibleContext; + } + + protected class AccessibleJRadioButtonMenuItem extends AccessibleJMenuItem + { + private static final long serialVersionUID = 4381471510145292179L; + + /** + * Creates a new AccessibleJRadioButtonMenuItem object. + */ + protected AccessibleJRadioButtonMenuItem() + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.RADIO_BUTTON; + } + } +} diff --git a/libjava/classpath/javax/swing/JRootPane.java b/libjava/classpath/javax/swing/JRootPane.java new file mode 100644 index 0000000..cb0bafd --- /dev/null +++ b/libjava/classpath/javax/swing/JRootPane.java @@ -0,0 +1,625 @@ +/* JRootPane.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.LayoutManager2; +import java.io.Serializable; + +import javax.accessibility.AccessibleRole; +import javax.swing.plaf.RootPaneUI; + +/** + * This class is where JComponents are added to. Unlike awt where you could + * just say frame.add(), with swing you need to say frame.getRootPane() + * (which delivers an instance of this class) and add your components to + * that. It is implemented by several 'layers' (pane() should be read as + * plane()) each on top of the others where you can add components to. + * (getContentPane(), getGlassPane(), getLayeredPane()) + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JRootPane extends JComponent +{ + // The class used to obtain the accessible role for this object. + protected static class AccessibleJRootPane + { + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 1082432482784468088L; + + /** + * Creates a new AccessibleJRootPane object. + */ + protected AccessibleJRootPane() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.ROOT_PANE; + } + } + + // Custom Layout Manager for JRootPane. It positions contentPane and + // menuBar withing its layeredPane. + protected class RootLayout implements LayoutManager2, Serializable + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = -4100116998559815027L; + + /** + * Creates a new RootLayout object. + */ + protected RootLayout() + { + } + + /** + * DOCUMENT ME! + * + * @param comp DOCUMENT ME! + * @param constraints DOCUMENT ME! + */ + public void addLayoutComponent(Component comp, Object constraints) + { + } + + /** + * DOCUMENT ME! + * + * @param name DOCUMENT ME! + * @param comp DOCUMENT ME! + */ + public void addLayoutComponent(String name, Component comp) + { + } + + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public float getLayoutAlignmentX(Container target) + { + return target.getAlignmentX(); + } + + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public float getLayoutAlignmentY(Container target) + { + return target.getAlignmentY(); + } + + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + */ + public void invalidateLayout(Container target) + { + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void layoutContainer(Container c) + { + Dimension menuBarSize; + Dimension containerSize = c.getSize(null); + Dimension contentPaneSize = contentPane.getPreferredSize(); + + /* + if size of top-level window wasn't set then just set + contentPane and menuBar to its preferred sizes. + Otherwise, if the size of top-level window was specified then + set menuBar to its preferred size and make content pane + to fit into the remaining space + + + +-------------------------------+ + | JLayeredPane | + | +--------------------------+ | + | | menuBar | | + | +--------------------------+ | + | +--------------------------+ | + | |contentPane | | + | | | | + | | | | + | | | | + | +--------------------------+ | + +-------------------------------+ + + */ + if (containerSize.width == 0 && containerSize.height == 0) + { + if (menuBar != null) + { + int maxWidth; + menuBarSize = menuBar.getPreferredSize(); + maxWidth = Math.max(menuBarSize.width, contentPaneSize.width); + menuBar.setBounds(0, 0, maxWidth, menuBarSize.height); + glassPane.setBounds(0, menuBarSize.height, maxWidth, + contentPaneSize.height); + contentPane.setBounds(0, menuBarSize.height, maxWidth, + contentPaneSize.height); + layeredPane.setSize(maxWidth, + menuBarSize.height + contentPaneSize.height); + } + else + { + glassPane.setBounds(0, 0, contentPaneSize.width, + contentPaneSize.height); + contentPane.setBounds(0, 0, contentPaneSize.width, + contentPaneSize.height); + layeredPane.setSize(contentPaneSize.width, contentPaneSize.height); + } + } + else + { + if (menuBar != null) + { + menuBarSize = menuBar.getPreferredSize(); + if (menuBarSize.height > containerSize.height) + menuBarSize.height = containerSize.height; + menuBar.setBounds(0, 0, containerSize.width, menuBarSize.height); + int remainingHeight = containerSize.height - menuBarSize.height; + 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); + } + } + + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension maximumLayoutSize(Container target) + { + return preferredLayoutSize(target); + } + + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension minimumLayoutSize(Container target) + { + return preferredLayoutSize(target); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension preferredLayoutSize(Container c) + { + Dimension menuBarSize; + Dimension prefSize; + + Dimension containerSize = c.getSize(); + Dimension contentPaneSize = contentPane.getPreferredSize(); + + if (containerSize.width == 0 && containerSize.height == 0) + { + if (menuBar != null) + { + int maxWidth; + menuBarSize = menuBar.getPreferredSize(); + maxWidth = Math.max(menuBarSize.width, contentPaneSize.width); + prefSize = new Dimension(maxWidth, + contentPaneSize.height + + menuBarSize.height); + } + else + prefSize = contentPaneSize; + } + else + prefSize = c.getSize(); + + return prefSize; + } + + /** + * DOCUMENT ME! + * + * @param comp DOCUMENT ME! + */ + public void removeLayoutComponent(Component comp) + { + } + } + + /** DOCUMENT ME! */ + private static final long serialVersionUID = 8690748000348575668L; + + public static final int NONE = 0; + public static final int FRAME = 1; + public static final int PLAIN_DIALOG = 2; + public static final int INFORMATION_DIALOG = 3; + public static final int ERROR_DIALOG = 4; + public static final int COLOR_CHOOSER_DIALOG = 5; + public static final int FILE_CHOOSER_DIALOG = 6; + public static final int QUESTION_DIALOG = 7; + public static final int WARNING_DIALOG = 8; + + /** DOCUMENT ME! */ + protected Component glassPane; + + /** DOCUMENT ME! */ + protected JLayeredPane layeredPane; + + /** DOCUMENT ME! */ + protected JMenuBar menuBar; + + /** DOCUMENT ME! */ + protected Container contentPane; + + protected JButton defaultButton; + + /** + * @since 1.4 + */ + private int windowDecorationStyle = NONE; + + /** + * DOCUMENT ME! + * + * @param m DOCUMENT ME! + */ + public void setJMenuBar(JMenuBar m) + { + JLayeredPane jlPane = getLayeredPane(); + if (menuBar != null) + jlPane.remove(menuBar); + menuBar = m; + if (menuBar != null) + jlPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER); + } + + /** + * @deprecated Replaced by setJMenuBar() + */ + public void setMenuBar(JMenuBar m) + { + setJMenuBar(m); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuBar getJMenuBar() + { + return menuBar; + } + + /** + * @deprecated Replaced by getJMenuBar() + */ + public JMenuBar getMenuBar() + { + return getJMenuBar(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isValidateRoot() + { + return true; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Container getContentPane() + { + if (contentPane == null) + setContentPane(createContentPane()); + return contentPane; + } + + /** + * DOCUMENT ME! + * + * @param p DOCUMENT ME! + */ + public void setContentPane(Container p) + { + contentPane = p; + getLayeredPane().add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER); + } + + /** + * DOCUMENT ME! + * + * @param comp DOCUMENT ME! + * @param constraints DOCUMENT ME! + * @param index DOCUMENT ME! + */ + protected void addImpl(Component comp, Object constraints, int index) + { + super.addImpl(comp, constraints, index); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getGlassPane() + { + if (glassPane == null) + setGlassPane(createGlassPane()); + return glassPane; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + */ + public void setGlassPane(Component f) + { + if (glassPane != null) + remove(glassPane); + + glassPane = f; + + glassPane.setVisible(false); + add(glassPane, 0); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JLayeredPane getLayeredPane() + { + if (layeredPane == null) + setLayeredPane(createLayeredPane()); + return layeredPane; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + */ + public void setLayeredPane(JLayeredPane f) + { + if (layeredPane != null) + remove(layeredPane); + + layeredPane = f; + add(f, -1); + } + + /** + * Creates a new JRootPane object. + */ + public JRootPane() + { + setLayout(createRootLayout()); + getGlassPane(); + getLayeredPane(); + getContentPane(); + setDoubleBuffered(true); + updateUI(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected LayoutManager createRootLayout() + { + return new RootLayout(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Container createContentPane() + { + JPanel p = new JPanel(); + p.setName(this.getName() + ".contentPane"); + p.setLayout(new BorderLayout()); + return p; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Component createGlassPane() + { + JPanel p = new JPanel(); + p.setName(this.getName() + ".glassPane"); + p.setLayout(new BorderLayout()); + p.setVisible(false); + p.setOpaque(false); + return p; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected JLayeredPane createLayeredPane() + { + JLayeredPane l = new JLayeredPane(); + l.setLayout(null); + return l; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public RootPaneUI getUI() + { + return (RootPaneUI) ui; + } + + /** + * DOCUMENT ME! + * + * @param ui DOCUMENT ME! + */ + public void setUI(RootPaneUI ui) + { + super.setUI(ui); + } + + /** + * DOCUMENT ME! + */ + public void updateUI() + { + setUI((RootPaneUI) UIManager.getUI(this)); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return "RootPaneUI"; + } + + public JButton getDefaultButton() + { + return defaultButton; + } + + public void setDefaultButton(JButton newButton) + { + if (defaultButton == newButton) + return; + + JButton oldButton = defaultButton; + defaultButton = newButton; + firePropertyChange("defaultButton", oldButton, newButton); + } + + /** + * @since 1.4 + */ + public int getWindowDecorationStyle() + { + return windowDecorationStyle; + } + + /** + * @since 1.4 + */ + public void setWindowDecorationStyle(int style) + { + if (style != NONE + && style != FRAME + && style != INFORMATION_DIALOG + && style != ERROR_DIALOG + && style != COLOR_CHOOSER_DIALOG + && style != FILE_CHOOSER_DIALOG + && style != QUESTION_DIALOG + && style != WARNING_DIALOG) + throw new IllegalArgumentException("invalid style"); + + int oldStyle = windowDecorationStyle; + windowDecorationStyle = style; + firePropertyChange("windowDecorationStyle", oldStyle, style); + } +} diff --git a/libjava/classpath/javax/swing/JScrollBar.java b/libjava/classpath/javax/swing/JScrollBar.java new file mode 100644 index 0000000..caed92c --- /dev/null +++ b/libjava/classpath/javax/swing/JScrollBar.java @@ -0,0 +1,647 @@ +/* JScrollBar.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Adjustable; +import java.awt.Dimension; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.plaf.ScrollBarUI; + +/** + * The JScrollBar. Two buttons control how the values that the + * scroll bar can take. You can also drag the thumb or click the track + * to move the scroll bar. Typically, the JScrollBar is used with + * other components to translate the value of the bar to the viewable + * contents of the other components. + */ +public class JScrollBar extends JComponent implements Adjustable, Accessible +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJScrollBar extends JComponent.AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = -7758162392045586663L; + + /** + * Creates a new AccessibleJSlider object. + * + * @param value0 DOCUMENT ME! + */ + protected AccessibleJScrollBar() + { + super(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * setCurrentAccessibleValue + * + * @param value0 TODO + * + * @return boolean + */ + public boolean setCurrentAccessibleValue(Number value0) + { + return false; + } + + /** + * getMinimumAccessibleValue + * + * @return Number + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * getMaximumAccessibleValue + * + * @return Number + */ + public Number getMaximumAccessibleValue() + { + return null; + } + } + + private static final long serialVersionUID = -8195169869225066566L; + + /** How much the thumb moves when moving in a block. */ + protected int blockIncrement = 10; + + /** The model that holds the scroll bar's data. */ + protected BoundedRangeModel model; + + /** The orientation of the scroll bar. */ + protected int orientation = SwingConstants.VERTICAL; + + /** How much the thumb moves when moving in a unit. */ + protected int unitIncrement = 1; + + /** + * Creates a new horizontal JScrollBar object with a minimum + * of 0, a maxmium of 100, a value of 0 and an extent of 10. + */ + public JScrollBar() + { + this(SwingConstants.VERTICAL, 0, 10, 0, 100); + } + + /** + * Creates a new JScrollBar object with a minimum of 0, a + * maximum of 100, a value of 0, an extent of 10 and the given + * orientation. + * + * @param orientation The orientation of the JScrollBar. + */ + public JScrollBar(int orientation) + { + this(orientation, 0, 10, 0, 100); + } + + /** + * Creates a new JScrollBar object with the given orientation, + * value, min, max, and extent. + * + * @param orientation The orientation to use. + * @param value The value to use. + * @param extent The extent to use. + * @param min The minimum value of the scrollbar. + * @param max The maximum value of the scrollbar. + */ + public JScrollBar(int orientation, int value, int extent, int min, int max) + { + model = new DefaultBoundedRangeModel(value, extent, min, max); + if (orientation != SwingConstants.HORIZONTAL + && orientation != SwingConstants.VERTICAL) + throw new IllegalArgumentException(orientation + + " is not a legal orientation"); + this.orientation = orientation; + updateUI(); + } + + /** + * This method sets the UI of this scrollbar to + * the given UI. + * + * @param ui The UI to use with this scrollbar. + */ + public void setUI(ScrollBarUI ui) + { + super.setUI(ui); + } + + /** + * This method returns the UI that is being used + * with this scrollbar. + * + * @return The scrollbar's current UI. + */ + public ScrollBarUI getUI() + { + return (ScrollBarUI) ui; + } + + /** + * This method changes the UI to be the + * default for the current look and feel. + */ + public void updateUI() + { + setUI((ScrollBarUI) UIManager.getUI(this)); + invalidate(); + repaint(); + } + + /** + * This method returns an identifier to + * choose the correct UI delegate for the + * scrollbar. + * + * @return The identifer to choose the UI delegate; "ScrollBarUI" + */ + public String getUIClassID() + { + return "ScrollBarUI"; + } + + /** + * This method returns the orientation of the scrollbar. + * + * @return The orientation of the scrollbar. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method sets the orientation of the scrollbar. + * + * @param orientation The orientation of the scrollbar. + */ + public void setOrientation(int orientation) + { + if (orientation != SwingConstants.HORIZONTAL + && orientation != SwingConstants.VERTICAL) + throw new IllegalArgumentException("orientation must be one of HORIZONTAL or VERTICAL"); + if (orientation != this.orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange("orientation", oldOrientation, + this.orientation); + } + } + + /** + * This method returns the model being used with + * the scrollbar. + * + * @return The scrollbar's model. + */ + public BoundedRangeModel getModel() + { + return model; + } + + /** + * This method sets the model to use with + * the scrollbar. + * + * @param newModel The new model to use with the scrollbar. + */ + public void setModel(BoundedRangeModel newModel) + { + if (model != newModel) + { + BoundedRangeModel oldModel = model; + model = newModel; + firePropertyChange("model", oldModel, model); + } + } + + /** + * This method returns how much the scrollbar's value + * should change for a unit increment depending on the + * given direction. + * + * @param direction The direction to scroll in. + * + * @return The amount the scrollbar's value will change given the direction. + */ + public int getUnitIncrement(int direction) + { + return direction * unitIncrement; + } + + /** + * This method sets the unitIncrement property. + * + * @param unitIncrement The new unitIncrement. + */ + public void setUnitIncrement(int unitIncrement) + { + if (unitIncrement != this.unitIncrement) + { + int oldInc = this.unitIncrement; + this.unitIncrement = unitIncrement; + firePropertyChange("unitIncrement", oldInc, + this.unitIncrement); + } + } + + /** + * The method returns how much the scrollbar's value + * should change for a block increment depending on + * the given direction. + * + * @param direction The direction to scroll in. + * + * @return The amount the scrollbar's value will change given the direction. + */ + public int getBlockIncrement(int direction) + { + return direction * blockIncrement; + } + + /** + * This method sets the blockIncrement property. + * + * @param blockIncrement The new blockIncrement. + */ + public void setBlockIncrement(int blockIncrement) + { + if (blockIncrement != this.blockIncrement) + { + int oldInc = this.blockIncrement; + this.blockIncrement = blockIncrement; + firePropertyChange("blockIncrement", oldInc, + this.blockIncrement); + } + } + + /** + * This method returns the unitIncrement. + * + * @return The unitIncrement. + */ + public int getUnitIncrement() + { + return unitIncrement; + } + + /** + * This method returns the blockIncrement. + * + * @return The blockIncrement. + */ + public int getBlockIncrement() + { + return blockIncrement; + } + + /** + * This method returns the value of the scrollbar. + * + * @return The value of the scrollbar. + */ + public int getValue() + { + return model.getValue(); + } + + /** + * This method changes the value of the scrollbar. + * + * @param value The new value of the scrollbar. + */ + public void setValue(int value) + { + if (isEnabled() && value != getValue()) + { + model.setValue(value); + fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, value); + } + } + + /** + * This method returns the visible amount (AKA extent). + * The visible amount can be used by UI delegates to + * determine the size of the thumb. + * + * @return The visible amount (AKA extent). + */ + public int getVisibleAmount() + { + return model.getExtent(); + } + + /** + * This method sets the visible amount (AKA extent). + * + * @param extent The visible amount (AKA extent). + */ + public void setVisibleAmount(int extent) + { + if (extent != getVisibleAmount()) + { + model.setExtent(extent); + fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, extent); + } + } + + /** + * This method returns the minimum value of the scrollbar. + * + * @return The minimum value of the scrollbar. + */ + public int getMinimum() + { + return model.getMinimum(); + } + + /** + * This method sets the minimum value of the scrollbar. + * + * @param minimum The minimum value of the scrollbar. + */ + public void setMinimum(int minimum) + { + if (minimum != getMinimum()) + { + model.setMinimum(minimum); + fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, minimum); + } + } + + /** + * This method returns the maximum value of the scrollbar. + * + * @return The maximum value of the scrollbar. + */ + public int getMaximum() + { + return model.getMaximum(); + } + + /** + * This method sets the maximum value of the scrollbar. + * + * @param maximum The maximum value of the scrollbar. + */ + public void setMaximum(int maximum) + { + if (maximum != getMaximum()) + { + model.setMaximum(maximum); + fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, maximum); + } + } + + /** + * This method returns the model's isAjusting value. + * + * @return The model's isAdjusting value. + */ + public boolean getValueIsAdjusting() + { + return model.getValueIsAdjusting(); + } + + /** + * This method sets the model's isAdjusting value. + * + * @param b The new isAdjusting value. + */ + public void setValueIsAdjusting(boolean b) + { + model.setValueIsAdjusting(b); + } + + /** + * This method sets the value, extent, minimum and + * maximum. + * + * @param newValue The new value. + * @param newExtent The new extent. + * @param newMin The new minimum. + * @param newMax The new maximum. + */ + public void setValues(int newValue, int newExtent, int newMin, int newMax) + { + if (!isEnabled()) + newValue = model.getValue(); + // It seems to be that on any change the value is fired. + if (newValue != getValue() || newExtent != getVisibleAmount() || + newMin != getMinimum() || newMax != getMaximum()) + { + model.setRangeProperties(newValue, newExtent, newMin, newMax, + model.getValueIsAdjusting()); + fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, newValue); + } + } + + /** + * This method adds an AdjustmentListener to the scroll bar. + * + * @param listener The listener to add. + */ + public void addAdjustmentListener(AdjustmentListener listener) + { + listenerList.add(AdjustmentListener.class, listener); + } + + /** + * This method removes an AdjustmentListener from the scroll bar. + * + * @param listener The listener to remove. + */ + public void removeAdjustmentListener(AdjustmentListener listener) + { + listenerList.remove(AdjustmentListener.class, listener); + } + + /** + * This method returns an arry of all AdjustmentListeners listening to + * this scroll bar. + * + * @return An array of AdjustmentListeners listening to this scroll bar. + */ + public AdjustmentListener[] getAdjustmentListeners() + { + return (AdjustmentListener[]) listenerList.getListeners(AdjustmentListener.class); + } + + /** + * This method is called to fired AdjustmentEvents to the listeners + * of this scroll bar. All AdjustmentEvents that are fired + * will have an ID of ADJUSTMENT_VALUE_CHANGED and a type of + * TRACK. + * + * @param id The ID of the adjustment event. + * @param type The Type of change. + * @param value The new value for the property that was changed.. + */ + protected void fireAdjustmentValueChanged(int id, int type, int value) + { + Object[] adjustmentListeners = listenerList.getListenerList(); + AdjustmentEvent adjustmentEvent = new AdjustmentEvent(this, + AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + AdjustmentEvent.TRACK, + value); + for (int i = adjustmentListeners.length - 2; i >= 0; i -= 2) + { + if (adjustmentListeners[i] == AdjustmentListener.class) + ((AdjustmentListener) adjustmentListeners[i + 1]).adjustmentValueChanged(adjustmentEvent); + } + } + + /** + * This method returns the minimum size for this scroll bar. + * + * @return The minimum size. + */ + public Dimension getMinimumSize() + { + return ui.getMinimumSize(this); + } + + /** + * This method returns the maximum size for this scroll bar. + * + * @return The maximum size. + */ + public Dimension getMaximumSize() + { + return ui.getMaximumSize(this); + } + + /** + * This method overrides the setEnabled in JComponent. + * When the scroll bar is disabled, the knob cannot + * be moved. + * + * @param x Whether the scrollbar is enabled. + */ + public void setEnabled(boolean x) + { + // nothing special needs to be done here since we + // just check the enabled setting before changing the value. + super.setEnabled(x); + } + + /** + * A string that describes this JScrollBar. Normally only used + * for debugging. + * + * @return A string describing this JScrollBar. + */ + protected String paramString() + { + return "JScrollBar"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJScrollBar(); + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JScrollPane.java b/libjava/classpath/javax/swing/JScrollPane.java new file mode 100644 index 0000000..377f05a --- /dev/null +++ b/libjava/classpath/javax/swing/JScrollPane.java @@ -0,0 +1,733 @@ +/* JScrollPane.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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 javax.accessibility.Accessible; +import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ScrollPaneUI; +import javax.swing.plaf.UIResource; + +/** + * A component that embeds another component and enables it to be scrolled + * both in horizontal and vertical direction. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Property Stored in Bound?
columnHeader scrollPane yes
columnHeaderView columnHeader no
componentOrientation scrollPane yes
horizontalScrollBar scrollPane yes
horizontalScrollBarPolicy scrollPane yes
layout scrollPane yes
rowHeader scrollPane yes
rowHeaderView rowHeader no
validateRoot scrollPane no
verticalScrollBar scrollPane yes
verticalScrollBarPolicy scrollPane yes
viewport scrollPane yes
viewportBorder scrollPane yes
viewportBorderBounds scrollPane no
viewportView viewport no
wheelScrollingEnabled scrollPane yes
+ */ +public class JScrollPane + extends JComponent + implements Accessible, ScrollPaneConstants +{ + private static final long serialVersionUID = 5203525440012340014L; + + protected JViewport columnHeader; + protected JViewport rowHeader; + + protected Component lowerLeft; + protected Component lowerRight; + protected Component upperLeft; + protected Component upperRight; + + protected JScrollBar horizontalScrollBar; + protected int horizontalScrollBarPolicy; + protected JScrollBar verticalScrollBar; + protected int verticalScrollBarPolicy; + + protected JViewport viewport; + + Border viewportBorder; + boolean wheelScrollingEnabled; + ChangeListener scrollListener; + + public JViewport getColumnHeader() + { + return columnHeader; + } + + public Component getCorner(String key) { + if (getComponentOrientation() + == ComponentOrientation.LEFT_TO_RIGHT) + { + if (key == LOWER_LEADING_CORNER) + key = LOWER_LEFT_CORNER; + else if (key == LOWER_TRAILING_CORNER) + key = LOWER_RIGHT_CORNER; + else if (key == UPPER_LEADING_CORNER) + key = UPPER_LEFT_CORNER; + else if (key == UPPER_TRAILING_CORNER) + key = UPPER_RIGHT_CORNER; + } + else if (getComponentOrientation() + == ComponentOrientation.RIGHT_TO_LEFT) + { + if (key == LOWER_LEADING_CORNER) + key = LOWER_RIGHT_CORNER; + else if (key == LOWER_TRAILING_CORNER) + key = LOWER_LEFT_CORNER; + else if (key == UPPER_LEADING_CORNER) + key = UPPER_RIGHT_CORNER; + else if (key == UPPER_TRAILING_CORNER) + key = UPPER_LEFT_CORNER; + } + + if (key == LOWER_RIGHT_CORNER) + return lowerRight; + else if (key == UPPER_RIGHT_CORNER) + return upperRight; + else if (key == LOWER_LEFT_CORNER) + return lowerLeft; + else if (key == UPPER_LEFT_CORNER) + return upperLeft; + return null; + } + + public JScrollBar getHorizontalScrollBar() + { + return horizontalScrollBar; + } + + public int getHorizontalScrollBarPolicy() + { + return horizontalScrollBarPolicy; + } + + public JViewport getRowHeader() + { + return rowHeader; + } + + public JScrollBar getVerticalScrollBar() + { + return verticalScrollBar; + } + + public int getVerticalScrollBarPolicy() + { + return verticalScrollBarPolicy; + } + + public JViewport getViewport() + { + return viewport; + } + + public Border getViewportBorder() + { + return viewportBorder; + } + + public Rectangle getViewportBorderBounds() + { + if (viewportBorder == null) + { + if (getViewport() == null) + return new Rectangle(0,0,0,0); + else + return getViewport().getBounds(); + } + else + { + Insets i = viewportBorder.getBorderInsets(getViewport()); + if (getViewport() == null) + return new Rectangle(0,0, + i.left+i.right, i.top+i.bottom); + else + { + Rectangle b = getViewport().getBounds(); + return new Rectangle(b.x - i.left, + b.y - i.top, + b.width + i.left + i.right, + b.height + i.top + i.bottom); + } + } + } + + public boolean isWheelScrollingEnabled() + { + return wheelScrollingEnabled; + } + + + + private void sync() + { + LayoutManager m = super.getLayout(); + if (m != null && m instanceof ScrollPaneLayout) + { + ScrollPaneLayout sl = (ScrollPaneLayout) m; + sl.syncWithScrollPane(this); + } + } + + private void removeNonNull(Component c) + { + if (c != null) + remove(c); + } + + private void addNonNull(Component c) + { + if (c != null) + add(c); + } + + public void setComponentOrientation(ComponentOrientation co) + { + ComponentOrientation old = super.getComponentOrientation(); + super.setComponentOrientation(co); + firePropertyChange("componentOrientation", old, co); + sync(); + } + + public void setColumnHeader(JViewport h) + { + if (columnHeader == h) + return; + + JViewport old = columnHeader; + removeNonNull(old); + columnHeader = h; + addNonNull(h); + firePropertyChange("columnHeader", old, h); + sync(); + } + + public void setColumnHeaderView(Component c) + { + if (columnHeader == null) + setColumnHeader(createViewport()); + columnHeader.setView(c); + sync(); + } + + public void setCorner(String key, Component c) + { + if (getComponentOrientation() + == ComponentOrientation.LEFT_TO_RIGHT) + { + if (key == LOWER_LEADING_CORNER) + key = LOWER_LEFT_CORNER; + else if (key == LOWER_TRAILING_CORNER) + key = LOWER_RIGHT_CORNER; + else if (key == UPPER_LEADING_CORNER) + key = UPPER_LEFT_CORNER; + else if (key == UPPER_TRAILING_CORNER) + key = UPPER_RIGHT_CORNER; + } + else if (getComponentOrientation() + == ComponentOrientation.RIGHT_TO_LEFT) + { + if (key == LOWER_LEADING_CORNER) + key = LOWER_RIGHT_CORNER; + else if (key == LOWER_TRAILING_CORNER) + key = LOWER_LEFT_CORNER; + else if (key == UPPER_LEADING_CORNER) + key = UPPER_RIGHT_CORNER; + else if (key == UPPER_TRAILING_CORNER) + key = UPPER_LEFT_CORNER; + } + + if (key == LOWER_RIGHT_CORNER) + { + removeNonNull(lowerRight); + lowerRight = c; + addNonNull(c); + } + else if (key == UPPER_RIGHT_CORNER) + { + removeNonNull(upperRight); + upperRight = c; + addNonNull(c); + } + else if (key == LOWER_LEFT_CORNER) + { + removeNonNull(lowerLeft); + lowerLeft = c; + addNonNull(c); + } + else if (key == UPPER_LEFT_CORNER) + { + removeNonNull(upperLeft); + upperLeft = c; + addNonNull(c); + } + else + throw new IllegalArgumentException("unknown corner " + key); + sync(); + } + + public void setHorizontalScrollBar(JScrollBar h) + { + if (horizontalScrollBar == h) + return; + + JScrollBar old = horizontalScrollBar; + removeNonNull(old); + horizontalScrollBar = h; + addNonNull(h); + 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) + { + if (horizontalScrollBarPolicy == h) + return; + + if (h != HORIZONTAL_SCROLLBAR_AS_NEEDED + && h != HORIZONTAL_SCROLLBAR_NEVER + && h != HORIZONTAL_SCROLLBAR_ALWAYS) + throw new IllegalArgumentException("unknown horizontal scrollbar policy"); + + int old = horizontalScrollBarPolicy; + horizontalScrollBarPolicy = h; + firePropertyChange("horizontalScrollBarPolicy", old, h); + sync(); + } + + public void setLayout(LayoutManager l) + { + LayoutManager old = super.getLayout(); + ScrollPaneLayout tmp = (ScrollPaneLayout) l; + super.setLayout(l); + tmp.syncWithScrollPane(this); + firePropertyChange("layout", old, l); + sync(); + } + + public void setRowHeader(JViewport v) + { + if (rowHeader == v) + return; + + JViewport old = rowHeader; + removeNonNull(old); + rowHeader = v; + addNonNull(v); + firePropertyChange("rowHeader", old, v); + sync(); + } + + public void setRowHeaderView(Component c) + { + if (rowHeader == null) + setRowHeader(createViewport()); + rowHeader.setView(c); + sync(); + } + + public void setVerticalScrollBar(JScrollBar v) + { + if (verticalScrollBar == v) + return; + + JScrollBar old = verticalScrollBar; + removeNonNull(old); + verticalScrollBar = v; + addNonNull(v); + 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) + { + if (verticalScrollBarPolicy == v) + return; + + if (v != VERTICAL_SCROLLBAR_AS_NEEDED + && v != VERTICAL_SCROLLBAR_NEVER + && v != VERTICAL_SCROLLBAR_ALWAYS) + throw new IllegalArgumentException("unknown vertical scrollbar policy"); + + int old = verticalScrollBarPolicy; + verticalScrollBarPolicy = v; + firePropertyChange("verticalScrollBarPolicy", old, v); + sync(); + } + + public void setWheelScrollingEnabled(boolean b) + { + if (wheelScrollingEnabled == b) + return; + + boolean old = wheelScrollingEnabled; + wheelScrollingEnabled = b; + firePropertyChange("wheelScrollingEnabled", old, b); + sync(); + } + + public void setViewport(JViewport v) + { + if (viewport == v) + return; + + JViewport old = viewport; + removeNonNull(old); + if (old != null) + old.removeChangeListener(scrollListener); + viewport = v; + if (v != null) + v.addChangeListener(scrollListener); + addNonNull(v); + revalidate(); + repaint(); + firePropertyChange("viewport", old, v); + sync(); + } + + public void setViewportBorder(Border b) + { + if (viewportBorder == b) + return; + + Border old = viewportBorder; + viewportBorder = b; + firePropertyChange("viewportBorder", old, b); + sync(); + } + + public void setViewportView(Component view) + { + if (getViewport() == null) + { + setViewport(createViewport()); + } + + if (view != null) + { + getViewport().setView(view); + } + sync(); + } + + public boolean isValidateRoot() + { + 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 JScrollPane without a view. The scrollbar + * policy is set to {@link #VERTICAL_SCROLLBAR_AS_NEEDED} and + * {@link #HORIZONTAL_SCROLLBAR_AS_NEEDED}. + * + * @param view the component that is embedded inside the JScrollPane + */ + public JScrollPane() + { + this(null); + } + + /** + * Creates a new JScrollPane that embeds the specified + * view component, displaying vertical and horizontal scrollbars + * as needed. + * + * @param view the component that is embedded inside the JScrollPane + */ + public JScrollPane(Component view) + { + this(view, + VERTICAL_SCROLLBAR_AS_NEEDED, + HORIZONTAL_SCROLLBAR_AS_NEEDED); + } + + /** + * Creates a new JScrollPane without a view; The scrollbar + * policies are set to vsbPolicy and hsbPolicy. + * + * @param vsbPolicy the vertical scrollbar policy to set + * @param hsbPolicy the vertical scrollbar policy to set + * + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_ALWAYS} + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_AS_NEEDED} + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_NEVER} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_ALWAYS} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_AS_NEEDED} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_NEVER} + */ + public JScrollPane(int vsbPolicy, int hsbPolicy) + { + this(null, vsbPolicy, hsbPolicy); + } + + /** + * Creates a new JScrollPane that embeds the specified + * view component; The scrollbar + * policies are set to vsbPolicy and hsbPolicy. + * + * @param vsbPolicy the vertical scrollbar policy to set + * @param hsbPolicy the vertical scrollbar policy to set + * + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_ALWAYS} + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_AS_NEEDED} + * @see {@link ScrollPaneConstants#HORIZONTAL_SCROLLBAR_NEVER} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_ALWAYS} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_AS_NEEDED} + * @see {@link ScrollPaneConstants#VERTICAL_SCROLLBAR_NEVER} + */ + public JScrollPane(Component view, int vsbPolicy, int hsbPolicy) + { + scrollListener = createScrollListener(); + setVerticalScrollBarPolicy(vsbPolicy); + setVerticalScrollBar(createVerticalScrollBar()); + setHorizontalScrollBarPolicy(hsbPolicy); + setHorizontalScrollBar(createHorizontalScrollBar()); + viewport = createViewport(); + if (view != null) + getViewport().setView(view); + viewport.addChangeListener(scrollListener); + add(viewport,0); + setLayout(new ScrollPaneLayout()); + setOpaque(false); + updateUI(); + } + + + public JScrollBar createHorizontalScrollBar() + { + return new ScrollBar(SwingConstants.HORIZONTAL); + } + + public JScrollBar createVerticalScrollBar() + { + return new ScrollBar(SwingConstants.VERTICAL); + } + + protected JViewport createViewport() + { + return new JViewport(); + } + + public String getUIClassID() + { + return "ScrollPaneUI"; + } + + public void updateUI() + { + ScrollPaneUI b = (ScrollPaneUI)UIManager.getUI(this); + setUI(b); + } + + /** + * This method returns the scrollpane's UI delegate. + * + * @return The scrollpane's UI delegate. + */ + public ScrollPaneUI getUI() + { + return (ScrollPaneUI) ui; + } + + /** + * This method sets the scrollpane's UI delegate. + * + * @param ui The scrollpane's UI delegate. + */ + public void setUI(ScrollPaneUI ui) + { + super.setUI(ui); + } + + protected class ScrollBar + extends JScrollBar + implements UIResource + { + private static final long serialVersionUID = -42032395320987283L; + + public ScrollBar(int orientation) + { + super(orientation); + } + + public int getBlockIncrement(int direction) + { + Component view = JScrollPane.this.getViewport().getView(); + if (view == null || (! (view instanceof Scrollable))) + return super.getBlockIncrement(direction); + else + { + Scrollable s = (Scrollable) view; + return s.getScrollableBlockIncrement(JScrollPane.this.getViewport().getViewRect(), + this.getOrientation(), + direction); + } + } + + public int getUnitIncrement(int direction) + { + Component view = JScrollPane.this.getViewport().getView(); + if (view == null || (! (view instanceof Scrollable))) + return super.getUnitIncrement(direction); + else + { + Scrollable s = (Scrollable) view; + return s.getScrollableUnitIncrement(JScrollPane.this.getViewport().getViewRect(), + this.getOrientation(), + direction); + } + } + } +} diff --git a/libjava/classpath/javax/swing/JSeparator.java b/libjava/classpath/javax/swing/JSeparator.java new file mode 100644 index 0000000..064c465 --- /dev/null +++ b/libjava/classpath/javax/swing/JSeparator.java @@ -0,0 +1,197 @@ +/* JSeparator.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.plaf.SeparatorUI; + + +/** + * The JSeparator. It is mostly used to divide/space out + * components. + */ +public class JSeparator extends JComponent implements SwingConstants, + Accessible +{ + /** + * AccessibleJSeparator + */ + protected class AccessibleJSeparator extends AccessibleJComponent + { + private static final long serialVersionUID = 916332890553201095L; + + /** + * Constructor AccessibleJSeparator + * + * @param component TODO + */ + protected AccessibleJSeparator() + { + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.SEPARATOR; + } + } + + private static final long serialVersionUID = 125301223445282357L; + + /** The orientation of the JSeparator. */ + private transient int orientation = HORIZONTAL; + + /** + * Creates a new horizontal JSeparator object. + */ + public JSeparator() + { + this(HORIZONTAL); + } + + /** + * Creates a new JSeparator object with the given orientation. + * + * @param orientation The orientation of the JSeparator. + */ + public JSeparator(int orientation) + { + if (orientation != HORIZONTAL && orientation != VERTICAL) + throw new IllegalArgumentException(orientation + + " is not a valid orientation."); + this.orientation = orientation; + updateUI(); + } + + /** + * This method returns the UI delegate being + * used with the JSeparator. + * + * @return SeparatorUI The JSeparator's UI delegate. + */ + public SeparatorUI getUI() + { + return (SeparatorUI) ui; + } + + /** + * This method sets the UI delegate to use + * with the JSeparator. + * + * @param ui The UI delegate to use. + */ + public void setUI(SeparatorUI ui) + { + super.setUI(ui); + } + + /** + * This method resets the UI delegate to the + * default for the current look and feel. + */ + public void updateUI() + { + setUI((SeparatorUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns the identifier string + * that is used to determine the UI delegate + * from the current look and feel. + * + * @return String The identifier string for the UI. + */ + public String getUIClassID() + { + return "SeparatorUI"; + } + + /** + * This method returns the JSeparator's orientation. + * + * @return int The JSeparator's orientation. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method changes the JSeparator's orientation. + * + * @param orientation The JSeparator's orientation. + */ + public void setOrientation(int orientation) + { + if (orientation != HORIZONTAL && orientation != VERTICAL) + throw new IllegalArgumentException(orientation + + " is not a valid orientation."); + this.orientation = orientation; + } + + /** + * This method returns a string desribing the JSeparator. + * Normally only used in debugging. + * + * @return String A string describing the JSeparator. + */ + protected String paramString() + { + return "JSeparator"; + } + + /** + * getAccessibleContext + * + * @return AccessibleContext + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJSeparator(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JSlider.java b/libjava/classpath/javax/swing/JSlider.java new file mode 100644 index 0000000..7f99511 --- /dev/null +++ b/libjava/classpath/javax/swing/JSlider.java @@ -0,0 +1,907 @@ +/* JSlider.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Dimension; +import java.awt.MenuContainer; +import java.awt.image.ImageObserver; +import java.io.Serializable; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.SliderUI; + +/** + * The JSlider is a Swing component that allows selection of a value within a + * range by adjusting a thumb in a track. The values for the minimum, + * maximum, extent and value are stored in a {@link + * DefaultBoundedRangeModel}. + * + *

+ * JSliders have the following properties: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Property Stored in Bound?
extent model no
inverted slider yes
labelTable slider yes
majorTickSpacing slider yes
maximum model no
minimum model no
minorTickSpacing slider yes
model slider yes
orientation slider yes
paintLabels slider yes
paintTicks slider yes
snapToTicks slider no
value model no
valueIsAdjusting model no
+ * + *

+ * The various behavioral aspects of these properties follows: + *

+ * + * + */ +public class JSlider extends JComponent implements SwingConstants, Accessible, + ImageObserver, + MenuContainer, Serializable +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -1441275936141218479L; + + /** + * DOCUMENT ME! + */ + protected class AccessibleJSlider extends JComponent.AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = -6301740148041106789L; + + /** + * Creates a new AccessibleJSlider object. + * + * @param value0 DOCUMENT ME! + */ + protected AccessibleJSlider() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * setCurrentAccessibleValue + * + * @param value0 TODO + * + * @return boolean + */ + public boolean setCurrentAccessibleValue(Number value0) + { + return false; + } + + /** + * getMinimumAccessibleValue + * + * @return Number + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * getMaximumAccessibleValue + * + * @return Number + */ + public Number getMaximumAccessibleValue() + { + return null; + } + } + + /** Whether or not this slider paints its ticks. */ + private transient boolean paintTicks = false; + + /** Whether or not this slider paints its track. */ + private transient boolean paintTrack = true; + + /** Whether or not this slider paints its labels. */ + private transient boolean paintLabels = false; + + /** + * A dictionary of (Integer, Component) pairs where each Component is a + * JLabel and the Integer determines where the label will be painted. + */ + private transient Dictionary labelTable; + + /** The model used to describe the slider. */ + protected BoundedRangeModel sliderModel; + + /** The space between major ticks. */ + protected int majorTickSpacing; + + /** The space between minor ticks. */ + protected int minorTickSpacing; + + /** Whether the slider snaps its values to ticks. */ + protected boolean snapToTicks = true; + + /** The orientation of the slider. */ + protected int orientation = HORIZONTAL; + + /** Whether the slider is inverted. */ + private transient boolean isInverted; + + /** The ChangeListener that listens to the model. */ + protected ChangeListener changeListener; + + /** The ChangeEvent that is passed to all listeners of this slider. */ + protected transient ChangeEvent changeEvent; + + /** + * Creates a new horizontal JSlider object with a minimum of 0, a maximum of + * 100, and a value of 50. + */ + public JSlider() + { + this(HORIZONTAL, 0, 100, 50); + } + + /** + * Creates a new JSlider object with the given orientation and a minimum of + * 0, a maximum of 100, and a value of 50. + * + * @param orientation The orientation of the slider. + */ + public JSlider(int orientation) + { + this(orientation, 0, 100, 50); + } + + /** + * Creates a new horizontal JSlider object with the given maximum and + * minimum and a value that is halfway between the minimum and the + * maximum. + * + * @param minimum The minimum value of the JSlider. + * @param maximum The maximum value of the JSlider. + */ + public JSlider(int minimum, int maximum) + { + this(HORIZONTAL, minimum, maximum, (maximum + minimum) / 2); + } + + /** + * Creates a new horizontal JSlider object with the given minimum, maximum, + * and value. + * + * @param minimum The minimum value of the JSlider. + * @param maximum The maximum value of the JSlider. + * @param value The initial value of the JSlider. + */ + public JSlider(int minimum, int maximum, int value) + { + this(HORIZONTAL, minimum, maximum, value); + } + + /** + * Creates a new JSlider object with the given orientation, minimum, + * maximum, and value. + * + * @param orientation The orientation of the JSlider. + * @param minimum The minimum value of the JSlider. + * @param maximum The maximum value of the JSlider. + * @param value The initial value of the JSlider. + */ + public JSlider(int orientation, int minimum, int maximum, int value) + { + sliderModel = new DefaultBoundedRangeModel(value, 0, minimum, maximum); + if (orientation != HORIZONTAL && orientation != VERTICAL) + throw new IllegalArgumentException(orientation + " is not a legal orientation"); + this.orientation = orientation; + changeListener = createChangeListener(); + sliderModel.addChangeListener(changeListener); + updateUI(); + } + + /** + * Creates a new horizontal JSlider object with the given model. + * + * @param model The model the slider will be created with. + */ + public JSlider(BoundedRangeModel model) + { + if (model == null) + sliderModel = new DefaultBoundedRangeModel(50, 0, 0, 100); + else + sliderModel = model; + changeListener = createChangeListener(); + sliderModel.addChangeListener(changeListener); + updateUI(); + } + + /** + * This method returns the current value of the slider. + * + * @return The value of the slider stored in the model. + */ + public int getValue() + { + return sliderModel.getValue(); + } + + /** + * This method sets the value of the slider. + * + * @param value The slider's new value. + */ + public void setValue(int value) + { + sliderModel.setValue(value); + } + + /** + * This method returns the slider's UI delegate. + * + * @return The slider's UI delegate. + */ + public SliderUI getUI() + { + return (SliderUI) ui; + } + + /** + * This method sets the slider's UI delegate. + * + * @param ui A SliderUI object to use with this slider. + */ + public void setUI(SliderUI ui) + { + super.setUI(ui); + } + + /** + * This method sets this slider's UI to the UIManager's default for the + * current look and feel. + */ + public void updateUI() + { + setUI((SliderUI) UIManager.getUI(this)); + invalidate(); + repaint(); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for the slider. + * + * @return The Look and Feel classID. "SliderUI" + */ + public String getUIClassID() + { + return "SliderUI"; + } + + /** + * Creates a ChangeListener for this Slider. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener() + { + return new ChangeListener() + { + public void stateChanged(ChangeEvent ce) + { + // No need to trigger a repaint since the UI listens to the model + // as well. All we need to do is pass on the stateChanged event + // to our listeners. + fireStateChanged(); + } + }; + } + + /** + * This method registers a listener to this slider. The listener will be + * informed of new ChangeEvents. + * + * @param listener The listener to register. + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * This method removes a listener from this slider. + * + * @param listener The listener to remove. + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * This method is called whenever the model fires a ChangeEvent. It should + * propagate the ChangeEvent to its listeners with a new ChangeEvent that + * identifies the slider as the source. + */ + protected void fireStateChanged() + { + Object[] changeListeners = listenerList.getListenerList(); + if (changeEvent == null) + changeEvent = new ChangeEvent(this); + for (int i = changeListeners.length - 2; i >= 0; i -= 2) + { + if (changeListeners[i] == ChangeListener.class) + ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent); + } + } + + /** + * This method returns an array of all ChangeListeners listening to this + * slider. + * + * @return An array of ChangeListeners listening to this slider. + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * This method returns the model of the slider. + * + * @return The slider's model. + */ + public BoundedRangeModel getModel() + { + return sliderModel; + } + + /** + * This method changes the "model" property. It also needs to unregister + * any listeners to the old model and register any listeners to the new + * model. + * + * @param model The model to use with the slider. + */ + public void setModel(BoundedRangeModel model) + { + // I didn't do the null pointer check on purpose. + // If you try it with Sun's, it'll go ahead and set it to null + // and bork the next time it tries to access the model. + if (model != sliderModel) + { + BoundedRangeModel oldModel = sliderModel; + sliderModel = model; + oldModel.removeChangeListener(changeListener); + sliderModel.addChangeListener(changeListener); + firePropertyChange("model", oldModel, sliderModel); + } + } + + /** + * This method returns the minimum value of the slider. + * + * @return The minimum value of the slider. + */ + public int getMinimum() + { + return sliderModel.getMinimum(); + } + + /** + * This method sets the minimum value of the slider. + * + * @param minimum The minimum value of the slider. + */ + public void setMinimum(int minimum) + { + sliderModel.setMinimum(minimum); + } + + /** + * This method returns the maximum value of the slider. + * + * @return The maximum value of the slider. + */ + public int getMaximum() + { + return sliderModel.getMaximum(); + } + + /** + * This method sets the maximum value of the slider. + * + * @param maximum The maximum value of the slider. + */ + public void setMaximum(int maximum) + { + sliderModel.setMaximum(maximum); + } + + /** + * This method returns this slider's isAdjusting value which is true if the + * thumb is being dragged. + * + * @return The slider's isAdjusting value. + */ + public boolean getValueIsAdjusting() + { + return sliderModel.getValueIsAdjusting(); + } + + /** + * This method sets the isAdjusting value for the slider. + * + * @param adjusting The slider's isAdjusting value. + */ + public void setValueIsAdjusting(boolean adjusting) + { + sliderModel.setValueIsAdjusting(adjusting); + } + + /** + * This method returns the extent value for this slider. + * + * @return The extent value for this slider. + */ + public int getExtent() + { + return sliderModel.getExtent(); + } + + /** + * This method sets the extent value for this slider. + * + * @param extent The extent value for this slider. + */ + public void setExtent(int extent) + { + sliderModel.setExtent(extent); + } + + /** + * This method returns the slider orientation. + * + * @return The orientation of the slider. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method changes the "orientation" property of this slider. If the + * orientation is not VERTICAL or HORIZONTAL, this method does nothing. + * + * @param orientation The orientation of this slider. + */ + public void setOrientation(int orientation) + { + if (orientation != VERTICAL && orientation != HORIZONTAL) + throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL"); + if (orientation != this.orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange("orientation", oldOrientation, + this.orientation); + } + } + + /** + * This method returns the label table for this slider. + * + * @return The label table for this slider. + */ + public Dictionary getLabelTable() + { + return labelTable; + } + + /** + * This method changes the "labelTable" property of this slider. + * + * @param table The label table for this slider. + */ + public void setLabelTable(Dictionary table) + { + if (table != labelTable) + { + Dictionary oldTable = labelTable; + labelTable = table; + firePropertyChange("labelTable", oldTable, labelTable); + } + } + + /** + * This method is called to reset UI delegates for the labels in the + * labelTable to a default for the current look and feel. + */ + protected void updateLabelUIs() + { + if (labelTable == null) + return; + for (Enumeration list = labelTable.elements(); list.hasMoreElements();) + { + JLabel label = (JLabel) list.nextElement(); + label.updateUI(); + } + } + + /** + * Creates a hashtable of (Integer, JLabel) pairs that can be used as a + * label table for this slider. The labels will start from the sliders + * minimum and increase by the increment. Each label will have a text + * string indicating their integer value. + * + * @param increment The increment to between labels. + * + * @return A hashtable with the labels and their keys. + */ + public Hashtable createStandardLabels(int increment) + { + return createStandardLabels(increment, sliderModel.getMinimum()); + } + + /** + * Creates a hashtable of (Integer, JLabel) pairs that can be used as a + * label table for this slider. The labels will start from the given start + * value and increase by the increment. Each label will have a text string + * indicating their integer value. + * + * @param increment The increment to between labels. + * @param start The value to start from. + * + * @return A hashtable with the labels and their keys. + */ + public Hashtable createStandardLabels(int increment, int start) + { + Hashtable table = new Hashtable(); + JLabel label; + Dimension dim; + + int max = sliderModel.getMaximum(); + + for (int i = start; i <= max; i += increment) + { + label = new JLabel(String.valueOf(i)); + label.setVerticalAlignment(CENTER); + label.setHorizontalAlignment(CENTER); + + // Make sure these labels have the width and height + // they want. + dim = label.getPreferredSize(); + label.setBounds(label.getX(), label.getY(), + (int) dim.getWidth(), + (int) dim.getHeight()); + table.put(new Integer(i), label); + } + return table; + } + + /** + * This method returns whether the slider is inverted. Horizontal sliders + * that are not inverted will have the minimums on the left. If they are + * inverted, the minimums will be on the right. Vertical sliders that are + * not inverted will have the minimums at the bottom. If they are inverted, + * the minimums will be at the top. + * + * @return Whether this slider is inverted. + */ + public boolean getInverted() + { + return isInverted; + } + + /** + * This method changes the "inverted" property for this slider.Horizontal + * sliders that are not inverted will have the minimums on the left. If + * they are inverted, the minimums will be on the right. Vertical sliders + * that are not inverted will have the minimums at the bottom. If they are + * inverted, the minimums will be at the top. However, if the slider's + * componentOrientation is set to RIGHT_TO_LEFT, then everything gets + * reversed again. + * + * @param inverted Whether the slider should be inverted. + */ + public void setInverted(boolean inverted) + { + if (isInverted != inverted) + { + boolean oldInverted = isInverted; + isInverted = inverted; + firePropertyChange("inverted", oldInverted, isInverted); + } + } + + /** + * This method returns the amount of units between each major tick mark. + * + * @return The amount of units between each major tick mark. + */ + public int getMajorTickSpacing() + { + return majorTickSpacing; + } + + /** + * This method changes the "majorTickSpacing" property for this slider. The + * major tick spacing is the amount of units between each major tick mark. + * + * @param spacing The amount of units between each major tick mark. + */ + public void setMajorTickSpacing(int spacing) + { + if (majorTickSpacing != spacing) + { + int oldSpacing = majorTickSpacing; + majorTickSpacing = spacing; + firePropertyChange("majorTickSpacing", oldSpacing, + majorTickSpacing); + } + } + + /** + * This method returns the amount of units between each minor tick mark. + * + * @return The amount of units between each minor tick mark. + */ + public int getMinorTickSpacing() + { + return minorTickSpacing; + } + + /** + * This method changes the "minorTickSpacing" property for this slider. The + * minor tick spacing is the amount of units between each minor tick mark. + * + * @param spacing The amount of units between each minor tick mark. + */ + public void setMinorTickSpacing(int spacing) + { + if (minorTickSpacing != spacing) + { + int oldSpacing = minorTickSpacing; + minorTickSpacing = spacing; + firePropertyChange("minorTickSpacing", oldSpacing, + minorTickSpacing); + } + } + + /** + * This method returns whether this slider is snapping to ticks. Sliders + * that snap to ticks will automatically move the thumb to the nearest tick + * mark. + * + * @return Whether this slider snaps to ticks. + */ + public boolean getSnapToTicks() + { + return snapToTicks; + } + + /** + * This method sets whether this slider will snap to ticks. Sliders that + * snap to ticks will automatically move the thumb to the nearest tick + * mark. + * + * @param snap Whether this slider snaps to ticks. + */ + public void setSnapToTicks(boolean snap) + { + if (snap != snapToTicks) + { + snapToTicks = snap; + fireStateChanged(); + } + } + + /** + * This method returns whether the slider will paint its tick marks. In + * addition to setting this property to true, one of minor tick spacing or + * major tick spacing must be set to a value greater than 0 in order for + * ticks to be painted. + * + * @return Whether ticks will be painted. + */ + public boolean getPaintTicks() + { + return paintTicks; + } + + /** + * This method changes the "paintTicks" property for this slider. In + * addition to setting this property to true, one of minor tick spacing or + * major tick spacing must be set to a value greater than 0 in order for + * ticks to be painted. + * + * @param paint Whether ticks will be painted. + */ + public void setPaintTicks(boolean paint) + { + if (paint != paintTicks) + { + boolean oldPaintTicks = paintTicks; + paintTicks = paint; + firePropertyChange("paintTicks", oldPaintTicks, paintTicks); + } + } + + /** + * This method returns whether the track will be painted. + * + * @return Whether the track will be painted. + */ + public boolean getPaintTrack() + { + return paintTrack; + } + + /** + * This method sets whether the track will be painted. + * + * @param paint Whether the track will be painted. + */ + public void setPaintTrack(boolean paint) + { + paintTrack = paint; + } + + /** + * This method returns whether labels will be painted. + * + * @return Whether labels will be painted. + */ + public boolean getPaintLabels() + { + return paintLabels; + } + + /** + * This method changes the "paintLabels" property. + * + * @param paint Whether labels will be painted. + */ + public void setPaintLabels(boolean paint) + { + if (paint != paintLabels) + { + boolean oldPaintLabels = paintLabels; + paintLabels = paint; + firePropertyChange("paintLabels", oldPaintLabels, paintLabels); + } + } + + /** + * This method is used primarily for debugging purposes and returns a string + * that can be used to represent this slider. + * + * @return A string representing this slider. + */ + protected String paramString() + { + return "JSlider"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJSlider(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JSpinner.java b/libjava/classpath/javax/swing/JSpinner.java new file mode 100644 index 0000000..96fe10f --- /dev/null +++ b/libjava/classpath/javax/swing/JSpinner.java @@ -0,0 +1,622 @@ +/* JSpinner.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import javax.swing.border.EtchedBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.SpinnerUI; +import javax.swing.text.DateFormatter; + +/** + * A JSpinner is a component which typically contains a numeric value and a + * way to manipulate the value. + * + * @author Ka-Hing Cheung + * + * @since 1.4 + */ +public class JSpinner extends JComponent +{ + /** + * DOCUMENT ME! + */ + public static class DefaultEditor extends JPanel implements ChangeListener, + PropertyChangeListener, + LayoutManager + { + private JSpinner spinner; + + /** The JFormattedTextField that backs the editor. */ + JFormattedTextField ftf; + + /** + * For compatability with Sun's JDK 1.4.2 rev. 5 + */ + private static final long serialVersionUID = -5317788736173368172L; + + /** + * Creates a new DefaultEditor object. + * + * @param spinner the JSpinner associated with this editor + */ + public DefaultEditor(JSpinner spinner) + { + super(); + setLayout(this); + this.spinner = spinner; + ftf = new JFormattedTextField(); + add(ftf); + ftf.setValue(spinner.getValue()); + spinner.addChangeListener(this); + } + + /** + * Returns the JSpinner object for this editor. + */ + public JSpinner getSpinner() + { + return spinner; + } + + /** + * DOCUMENT ME! + */ + public void commitEdit() + throws ParseException + { + } /* TODO */ + + /** + * DOCUMENT ME! + * + * @param spinner DOCUMENT ME! + */ + public void dismiss(JSpinner spinner) + { + spinner.removeChangeListener(this); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JFormattedTextField getTextField() + { + return ftf; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + */ + public void layoutContainer(Container parent) + { + Insets insets = getInsets(); + Dimension size = getSize(); + ftf.setBounds(insets.left, insets.top, + size.width - insets.left - insets.right, + size.height - insets.top - insets.bottom); + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension minimumLayoutSize(Container parent) + { + Insets insets = getInsets(); + Dimension minSize = ftf.getMinimumSize(); + return new Dimension(minSize.width + insets.left + insets.right, + minSize.height + insets.top + insets.bottom); + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension preferredLayoutSize(Container parent) + { + Insets insets = getInsets(); + Dimension prefSize = ftf.getPreferredSize(); + return new Dimension(prefSize.width + insets.left + insets.right, + prefSize.height + insets.top + insets.bottom); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent event) + { + } /* TODO */ + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + public void stateChanged(ChangeEvent event) + { + } /* TODO */ + + /* no-ops */ + public void removeLayoutComponent(Component child) + { + } + + /** + * DOCUMENT ME! + * + * @param name DOCUMENT ME! + * @param child DOCUMENT ME! + */ + public void addLayoutComponent(String name, Component child) + { + } + } + + /** + * DOCUMENT ME! + */ + public static class NumberEditor extends DefaultEditor + { + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 3791956183098282942L; + + /** + * Creates a new NumberEditor object. + * + * @param spinner DOCUMENT ME! + */ + public NumberEditor(JSpinner spinner) + { + super(spinner); + } + + /** + * Creates a new NumberEditor object. + * + * @param spinner DOCUMENT ME! + */ + public NumberEditor(JSpinner spinner, String decimalFormatPattern) + { + super(spinner); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public DecimalFormat getFormat() + { + return null; + } + + public SpinnerNumberModel getModel() + { + return (SpinnerNumberModel) getSpinner().getModel(); + } + } + + /** + * An editor class for a JSpinner that is used + * for displaying and editing dates (e.g. that uses + * SpinnerDateModel as model). + * + * The editor uses a {@link JTextField} with the value + * displayed by a {@link DateFormatter} instance. + */ + public static class DateEditor extends DefaultEditor + { + + /** The serialVersionUID. */ + private static final long serialVersionUID = -4279356973770397815L; + + /** The DateFormat instance used to format the date. */ + SimpleDateFormat dateFormat; + + /** + * Creates a new instance of DateEditor for the specified + * JSpinner. + * + * @param spinner the JSpinner for which to + * create a DateEditor instance + */ + public DateEditor(JSpinner spinner) + { + super(spinner); + init(new SimpleDateFormat()); + } + + /** + * Creates a new instance of DateEditor for the specified + * JSpinner using the specified date format + * pattern. + * + * @param spinner the JSpinner for which to + * create a DateEditor instance + * @param dateFormatPattern the date format to use + * + * @see SimpleDateFormat(String) + */ + public DateEditor(JSpinner spinner, String dateFormatPattern) + { + super(spinner); + init(new SimpleDateFormat(dateFormatPattern)); + } + + /** + * Initializes the JFormattedTextField for this editor. + * + * @param the date format to use in the formatted text field + */ + private void init(SimpleDateFormat format) + { + dateFormat = format; + getTextField().setFormatterFactory( + new JFormattedTextField.AbstractFormatterFactory() + { + public JFormattedTextField.AbstractFormatter + getFormatter(JFormattedTextField ftf) + { + return new DateFormatter(dateFormat); + } + }); + } + + /** + * Returns the SimpleDateFormat instance that is used to + * format the date value. + * + * @return the SimpleDateFormat instance that is used to + * format the date value + */ + public SimpleDateFormat getFormat() + { + return dateFormat; + } + + /** + * Returns the {@link SpinnerDateModel} that is edited by this editor. + * + * @return the SpinnerDateModel that is edited by this editor + */ + public SpinnerDateModel getModel() + { + return (SpinnerDateModel) getSpinner().getModel(); + } + } + + private static final long serialVersionUID = 3412663575706551720L; + + /** DOCUMENT ME! */ + private SpinnerModel model; + + /** DOCUMENT ME! */ + private JComponent editor; + + /** DOCUMENT ME! */ + private ChangeListener listener = new ChangeListener() + { + public void stateChanged(ChangeEvent evt) + { + fireStateChanged(); + } + }; + + /** + * Creates a JSpinner with SpinnerNumberModel + * + * @see javax.swing.SpinnerNumberModel + */ + public JSpinner() + { + this(new SpinnerNumberModel()); + } + + /** + * Creates a JSpinner with the specific model and sets the default editor + * + * @param model DOCUMENT ME! + */ + public JSpinner(SpinnerModel model) + { + this.model = model; + model.addChangeListener(listener); + setEditor(createEditor(model)); + updateUI(); + } + + /** + * If the editor is JSpinner.DefaultEditor, then forwards the + * call to it, otherwise do nothing. + * + * @throws ParseException DOCUMENT ME! + */ + public void commitEdit() throws ParseException + { + if (editor instanceof DefaultEditor) + ((DefaultEditor) editor).commitEdit(); + } + + /** + * Gets the current editor + * + * @return the current editor + * + * @see #setEditor + */ + public JComponent getEditor() + { + return editor; + } + + /** + * Changes the current editor to the new editor. This methods should remove + * the old listeners (if any) and adds the new listeners (if any). + * + * @param editor the new editor + * + * @throws IllegalArgumentException DOCUMENT ME! + * + * @see #getEditor + */ + public void setEditor(JComponent editor) + { + if (editor == null) + throw new IllegalArgumentException("editor may not be null"); + + if (this.editor instanceof DefaultEditor) + ((DefaultEditor) editor).dismiss(this); + else if (this.editor instanceof ChangeListener) + removeChangeListener((ChangeListener) this.editor); + + if (editor instanceof ChangeListener) + addChangeListener((ChangeListener) editor); + + this.editor = editor; + } + + /** + * Gets the underly model. + * + * @return the underly model + */ + public SpinnerModel getModel() + { + return model; + } + + /** + * Sets a new underlying model. + * + * @param newModel the new model to set + * + * @exception IllegalArgumentException if newModel is null + */ + public void setModel(SpinnerModel newModel) + { + if (newModel == null) + throw new IllegalArgumentException(); + + if (model == newModel) + return; + + SpinnerModel oldModel = model; + model = newModel; + firePropertyChange("model", oldModel, newModel); + + if (editor == null) + setEditor(createEditor(model)); + } + + /** + * Gets the next value without changing the current value. + * + * @return the next value + * + * @see javax.swing.SpinnerModel#getNextValue + */ + public Object getNextValue() + { + return model.getNextValue(); + } + + /** + * Gets the previous value without changing the current value. + * + * @return the previous value + * + * @see javax.swing.SpinnerModel#getPreviousValue + */ + public Object getPreviousValue() + { + return model.getPreviousValue(); + } + + /** + * Gets the SpinnerUI that handles this spinner + * + * @return the SpinnerUI + */ + public SpinnerUI getUI() + { + return (SpinnerUI) ui; + } + + /** + * Gets the current value of the spinner, according to the underly model, + * not the UI. + * + * @return the current value + * + * @see javax.swing.SpinnerModel#getValue + */ + public Object getValue() + { + return model.getValue(); + } + + /** + * DOCUMENT ME! + * + * @param value DOCUMENT ME! + */ + public void setValue(Object value) + { + model.setValue(value); + } + + /** + * This method returns a name to identify which look and feel class will be + * the UI delegate for this spinner. + * + * @return The UIClass identifier. "SpinnerUI" + */ + public String getUIClassID() + { + return "SpinnerUI"; + } + + /** + * This method resets the spinner's UI delegate to the default UI for the + * current look and feel. + */ + public void updateUI() + { + setUI((SpinnerUI) UIManager.getUI(this)); + } + + /** + * This method sets the spinner's UI delegate. + * + * @param ui The spinner's UI delegate. + */ + public void setUI(SpinnerUI ui) + { + super.setUI(ui); + } + + /** + * Adds a ChangeListener + * + * @param listener the listener to add + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * Remove a particular listener + * + * @param listener the listener to remove + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * Gets all the ChangeListeners + * + * @return all the ChangeListeners + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Fires a ChangeEvent to all the ChangeListeners + * added to this JSpinner + */ + protected void fireStateChanged() + { + ChangeEvent evt = new ChangeEvent(this); + ChangeListener[] listeners = getChangeListeners(); + + for (int i = 0; i < listeners.length; ++i) + listeners[i].stateChanged(evt); + } + + /** + * Creates an editor for this JSpinner. Really, it should be a + * JSpinner.DefaultEditor, but since that should be + * implemented by a JFormattedTextField, and one is not written, I am just + * using a dummy one backed by a JLabel. + * + * @param model DOCUMENT ME! + * + * @return the default editor + */ + protected JComponent createEditor(SpinnerModel model) + { + if (model instanceof SpinnerDateModel) + return new DateEditor(this); + else if (model instanceof SpinnerNumberModel) + return new NumberEditor(this); + else + return new DefaultEditor(this); + } +} diff --git a/libjava/classpath/javax/swing/JSplitPane.java b/libjava/classpath/javax/swing/JSplitPane.java new file mode 100644 index 0000000..d7abce9 --- /dev/null +++ b/libjava/classpath/javax/swing/JSplitPane.java @@ -0,0 +1,815 @@ +/* JSplitPane.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Graphics; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.plaf.SplitPaneUI; + +/** + * This class implements JSplitPane. It is used to divide two components. By + * dragging the SplitPane's divider, the user can resize the two components. + * Note that the divider cannot resize a component to smaller than it's + * minimum size. + */ +public class JSplitPane extends JComponent implements Accessible +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJSplitPane extends JComponent.AccessibleJComponent + implements AccessibleValue + { + private static final long serialVersionUID = -1788116871416305366L; + + /** + * Creates a new AccessibleJSplitPane object. + * + * @param value0 DOCUMENT ME! + */ + protected AccessibleJSplitPane() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean setCurrentAccessibleValue(Number value0) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMaximumAccessibleValue() + { + return null; + } + } + + private static final long serialVersionUID = -5634142046175988380L; + + /** The constraints string used to add components to the bottom. */ + public static final String BOTTOM = "bottom"; + + /** The property fired when the continuousLayout property changes. */ + public static final String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout"; + + /** The property fired when the divider property changes. */ + public static final String DIVIDER = "divider"; + + /** The property fired when the divider location property changes. */ + public static final String DIVIDER_LOCATION_PROPERTY = "dividerLocation"; + + /** The property fired when the divider size property changes. */ + public static final String DIVIDER_SIZE_PROPERTY = "dividerSize"; + + /** + * The value of the orientation when the components are split horizontally. + */ + public static final int HORIZONTAL_SPLIT = 1; + + /** The property fired when the last divider location property changes. */ + public static final String LAST_DIVIDER_LOCATION_PROPERTY = "lastDividerLocation"; + + /** The constraints string used to add components to the left. */ + public static final String LEFT = "left"; + + /** The property fired when the one touch expandable property changes. */ + public static final String ONE_TOUCH_EXPANDABLE_PROPERTY = "oneTouchExpandable"; + + /** The property fired when the orientation property changes. */ + public static final String ORIENTATION_PROPERTY = "orientation"; + + /** The property fired when the resize weight property changes. */ + public static final String RESIZE_WEIGHT_PROPERTY = "resizeWeight"; + + /** The constraints string used to add components to the right. */ + public static final String RIGHT = "right"; + + /** The constraints string used to add components to the top. */ + public static final String TOP = "top"; + + /** The value of the orientation when the components are split vertically. */ + public static final int VERTICAL_SPLIT = 0; + + /** Whether the JSplitPane uses continuous layout. */ + protected boolean continuousLayout; + + /** Whether the JSplitPane uses one touch expandable buttons. */ + protected boolean oneTouchExpandable = false; + + // This is the master dividerSize variable and sets the BasicSplitPaneDivider one accordingly + + /** The size of the divider. */ + protected int dividerSize = 10; + + /** The last location of the divider given by the UI. */ + protected int lastDividerLocation; + + /** The orientation of the JSplitPane. */ + protected int orientation; + + /** The component on the top or left. */ + protected Component leftComponent; + + /** The component on the right or bottom. */ + protected Component rightComponent; + + /** Determines how extra space should be allocated. */ + private transient double resizeWeight; + + /** + * Creates a new JSplitPane object with the given orientation, layout mode, + * and left and right components. + * + * @param newOrientation The orientation to use. + * @param newContinuousLayout The layout mode to use. + * @param newLeftComponent The left component. + * @param newRightComponent The right component. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public JSplitPane(int newOrientation, boolean newContinuousLayout, + Component newLeftComponent, Component newRightComponent) + { + if (newOrientation != HORIZONTAL_SPLIT && newOrientation != VERTICAL_SPLIT) + throw new IllegalArgumentException("orientation is invalid."); + orientation = newOrientation; + continuousLayout = newContinuousLayout; + setLeftComponent(newLeftComponent); + setRightComponent(newRightComponent); + + updateUI(); + } + + /** + * Creates a new JSplitPane object using nonContinuousLayout mode, the given + * orientation and left and right components. + * + * @param newOrientation The orientation to use. + * @param newLeftComponent The left component. + * @param newRightComponent The right component. + */ + public JSplitPane(int newOrientation, Component newLeftComponent, + Component newRightComponent) + { + this(newOrientation, false, newLeftComponent, newRightComponent); + } + + /** + * Creates a new JSplitPane object with the given layout mode and + * orientation. + * + * @param newOrientation The orientation to use. + * @param newContinuousLayout The layout mode to use. + */ + public JSplitPane(int newOrientation, boolean newContinuousLayout) + { + this(newOrientation, newContinuousLayout, null, null); + } + + /** + * Creates a new JSplitPane object using a nonContinuousLayout mode and the + * given orientation. + * + * @param newOrientation The orientation to use. + */ + public JSplitPane(int newOrientation) + { + this(newOrientation, false, null, null); + } + + /** + * Creates a new JSplitPane object using HORIZONTAL_SPLIT and a + * nonContinuousLayout mode. + */ + public JSplitPane() + { + this(HORIZONTAL_SPLIT, false, null, null); + } + + /** + * This method adds a component to the JSplitPane. The constraints object is + * a string that identifies where this component should go. If the + * constraints is not a known one, it will throw an + * IllegalArgumentException. The valid constraints are LEFT, TOP, RIGHT, + * BOTTOM and DIVIDER. + * + * @param comp The component to add. + * @param constraints The constraints string to use. + * @param index Where to place to component in the list of components. + * + * @throws IllegalArgumentException When the constraints is not a known identifier. + */ + protected void addImpl(Component comp, Object constraints, int index) + { + int left = 0; + int right = 1; + int div = 2; + int place; + if (constraints == null) + { + if (leftComponent == null) + constraints = LEFT; + else if (rightComponent == null) + constraints = RIGHT; + } + + if (constraints instanceof String) + { + String placement = (String) constraints; + + if (placement.equals(BOTTOM) || placement.equals(RIGHT)) + { + if (rightComponent != null) + remove(rightComponent); + rightComponent = comp; + } + else if (placement.equals(LEFT) || placement.equals(TOP)) + { + if (leftComponent != null) + remove(leftComponent); + leftComponent = comp; + } + else if (placement.equals(DIVIDER)) + constraints = null; + else + throw new IllegalArgumentException("Constraints is not a known identifier."); + + super.addImpl(comp, constraints, index); + } + invalidate(); + layout(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJSplitPane(); + + return accessibleContext; + } + + /** + * This method returns the bottom component. + * + * @return The bottom component. + */ + public Component getBottomComponent() + { + return rightComponent; + } + + /** + * This method returns the location of the divider. This method is passed to + * the UI. + * + * @return The location of the divider. + */ + public int getDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getDividerLocation(this); + else + return -1; + } + + /** + * This method returns the size of the divider. + * + * @return The size of the divider. + */ + public int getDividerSize() + { + return dividerSize; + } + + /** + * This method returns the last divider location. + * + * @return The last divider location. + */ + public int getLastDividerLocation() + { + return lastDividerLocation; + } + + /** + * This method returns the left component. + * + * @return The left component. + */ + public Component getLeftComponent() + { + return leftComponent; + } + + /** + * This method returns the maximum divider location. This method is passed + * to the UI. + * + * @return DOCUMENT ME! + */ + public int getMaximumDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getMaximumDividerLocation(this); + else + return -1; + } + + /** + * This method returns the minimum divider location. This method is passed + * to the UI. + * + * @return The minimum divider location. + */ + public int getMinimumDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getMinimumDividerLocation(this); + else + return -1; + } + + /** + * This method returns the orientation that the JSplitPane is using. + * + * @return The current orientation. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method returns the current resize weight. + * + * @return The current resize weight. + */ + public double getResizeWeight() + { + return resizeWeight; + } + + /** + * This method returns the right component. + * + * @return The right component. + */ + public Component getRightComponent() + { + return rightComponent; + } + + /** + * This method returns the top component. + * + * @return The top component. + */ + public Component getTopComponent() + { + return leftComponent; + } + + /** + * This method returns the UI. + * + * @return The UI. + */ + public SplitPaneUI getUI() + { + return (SplitPaneUI) ui; + } + + /** + * This method returns true if the JSplitPane is using a continuousLayout. + * + * @return True if using a continuousLayout. + */ + public boolean isContinuousLayout() + { + return continuousLayout; + } + + /** + * This method returns true if the divider has one touch expandable buttons. + * + * @return True if one touch expandable is used. + */ + public boolean isOneTouchExpandable() + { + return oneTouchExpandable; + } + + /** + * This method returns true. + * + * @return true. + */ + public boolean isValidateRoot() + { + return true; + } + + /** + * This method overrides JComponent's paintChildren so the UI can be + * messaged when the children have finished painting. + * + * @param g The Graphics object to paint with. + */ + protected void paintChildren(Graphics g) + { + super.paintChildren(g); + if (ui != null) + ((SplitPaneUI) ui).finishedPaintingChildren(this, g); + } + + /** + * This method returns a String that describes this JSplitPane. The string + * is primarily used for debugging purposes. + * + * @return A String used for debugging purposes. + */ + protected String paramString() + { + return "JSplitPane"; + } + + /** + * This method removes the given component from the JSplitPane. + * + * @param component The Component to remove. + */ + public void remove(Component component) + { + if (component == leftComponent) + leftComponent = null; + else if (component == rightComponent) + rightComponent = null; + super.remove(component); + } + + /** + * This method removes the component at the given index. + * + * @param index The index of the component to remove. + */ + public void remove(int index) + { + Component component = getComponent(index); + if (component == leftComponent) + leftComponent = null; + else if (component == rightComponent) + rightComponent = null; + super.remove(index); + } + + /** + * This method removes all components from the JSplitPane. + */ + public void removeAll() + { + leftComponent = null; + rightComponent = null; + super.removeAll(); + } + + /** + * This method resets all children of the JSplitPane to their preferred + * sizes. + */ + public void resetToPreferredSizes() + { + if (ui != null) + ((SplitPaneUI) ui).resetToPreferredSizes(this); + } + + /** + * This method sets the bottom component. + * + * @param comp The Component to be placed at the bottom. + */ + public void setBottomComponent(Component comp) + { + if (comp != null) + add(comp, BOTTOM); + else + add(new JButton("right button"), BOTTOM); + } + + /** + * This method sets the layout mode for the JSplitPane. + * + * @param newContinuousLayout Whether the JSplitPane is in continuousLayout + * mode. + */ + public void setContinuousLayout(boolean newContinuousLayout) + { + if (newContinuousLayout != continuousLayout) + { + boolean oldValue = continuousLayout; + continuousLayout = newContinuousLayout; + firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldValue, + continuousLayout); + } + } + + /** + * This method sets the location of the divider. A value of 0 sets the + * divider to the farthest left. A value of 1 sets the divider to the + * farthest right. + * + * @param proportionalLocation A double that describes the location of the + * divider. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void setDividerLocation(double proportionalLocation) + { + if (proportionalLocation > 1 || proportionalLocation < 0) + throw new IllegalArgumentException("proportion has to be between 0 and 1."); + + int max = (orientation == HORIZONTAL_SPLIT) ? getWidth() : getHeight(); + setDividerLocation((int) (proportionalLocation * max)); + } + + /** + * This method sets the location of the divider. + * + * @param location The location of the divider. + */ + public void setDividerLocation(int location) + { + if (ui != null && location != getDividerLocation()) + { + int oldLocation = getDividerLocation(); + ((SplitPaneUI) ui).setDividerLocation(this, location); + firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldLocation, location); + } + } + + /** + * This method sets the size of the divider. + * + * @param newSize The size of the divider. + */ + public void setDividerSize(int newSize) + { + if (newSize != dividerSize) + { + int oldSize = dividerSize; + dividerSize = newSize; + firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, dividerSize); + } + } + + // This doesn't appear to do anything when set from user side. + // so it probably is only used from the UI side to change the + // lastDividerLocation var. + + /** + * This method sets the last location of the divider. + * + * @param newLastLocation The last location of the divider. + */ + public void setLastDividerLocation(int newLastLocation) + { + if (newLastLocation != lastDividerLocation) + { + int oldValue = lastDividerLocation; + lastDividerLocation = newLastLocation; + firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldValue, + lastDividerLocation); + } + } + + /** + * This method sets the left component. + * + * @param comp The left component. + */ + public void setLeftComponent(Component comp) + { + if (comp != null) + add(comp, LEFT); + else + add(new JButton("left button"), LEFT); + } + + /** + * This method sets whether the divider has one touch expandable buttons. + * The one touch expandable buttons can expand the size of either component + * to the maximum allowed size. + * + * @param newValue Whether the divider will have one touch expandable + * buttons. + */ + public void setOneTouchExpandable(boolean newValue) + { + if (newValue != oneTouchExpandable) + { + boolean oldValue = oneTouchExpandable; + oneTouchExpandable = newValue; + firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, + oneTouchExpandable); + } + } + + /** + * This method sets the orientation of the JSplitPane. + * + * @param orientation The orientation of the JSplitPane. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void setOrientation(int orientation) + { + if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT) + throw new IllegalArgumentException("orientation must be one of VERTICAL_SPLIT, HORIZONTAL_SPLIT"); + if (orientation != this.orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, + this.orientation); + } + } + + /** + * This method determines how extra space will be distributed among the left + * and right components. A value of 0 will allocate all extra space to the + * right component. A value of 1 indicates that all extra space will go to + * the left component. A value in between 1 and 0 will split the space + * accordingly. + * + * @param value The resize weight. + */ + public void setResizeWeight(double value) + { + resizeWeight = value; + } + + /** + * This method sets the right component. + * + * @param comp The right component. + */ + public void setRightComponent(Component comp) + { + if (comp != null) + add(comp, RIGHT); + else + add(new JButton("right button"), RIGHT); + } + + /** + * This method sets the top component. + * + * @param comp The top component. + */ + public void setTopComponent(Component comp) + { + if (comp != null) + add(comp, TOP); + else + add(new JButton("left button"), TOP); + } + + /** + * This method sets the UI used by the JSplitPane. + * + * @param ui The UI to use. + */ + public void setUI(SplitPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method resets the UI to the one specified by the current Look and + * Feel. + */ + public void updateUI() + { + setUI((SplitPaneUI) UIManager.getUI(this)); + invalidate(); + repaint(); + } + + /** + * This method returns a string identifier to determine which UI class it + * needs. + * + * @return A string that identifies it's UI class. + */ + public String getUIClassID() + { + return "SplitPaneUI"; + } +} diff --git a/libjava/classpath/javax/swing/JTabbedPane.java b/libjava/classpath/javax/swing/JTabbedPane.java new file mode 100644 index 0000000..828a69a --- /dev/null +++ b/libjava/classpath/javax/swing/JTabbedPane.java @@ -0,0 +1,1478 @@ +/* JTabbedPane.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.io.Serializable; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +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. + * + *

+ * Tabs can be oriented in several ways. They can be above, below, left and + * right of the component. Tabs can either wrap around (by creating multiple + * rows of tabs) or they can be scrolled (where only a subset of the tabs + * can be seen at once). More tabs can be added by calling the + * add/addTab/insertTab methods. + *

+ */ +public class JTabbedPane extends JComponent implements Serializable, + Accessible, + SwingConstants +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJTabbedPane extends JComponent.AccessibleJComponent + implements AccessibleSelection, ChangeListener + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = 7610530885966830483L; + + /** + * Creates a new AccessibleJTabbedPane object. + */ + public AccessibleJTabbedPane() + { + super(); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void stateChanged(ChangeEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Accessible getAccessibleChild(int i) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleSelection getAccessibleSelection() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param p DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Accessible getAccessibleAt(Point p) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getAccessibleSelectionCount() + { + return 0; + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Accessible getAccessibleSelection(int i) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isAccessibleChildSelected(int i) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + */ + public void addAccessibleSelection(int i) + { + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + */ + public void removeAccessibleSelection(int i) + { + } + + /** + * DOCUMENT ME! + */ + public void clearAccessibleSelection() + { + } + + /** + * DOCUMENT ME! + */ + public void selectAllAccessibleSelection() + { + } + } + + /** + * A helper class that listens for changes to the model. + */ + protected class ModelListener implements ChangeListener, Serializable + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = 497359819958114132L; + + /** + * Creates a new ModelListener object. + */ + protected ModelListener() + { + } + + /** + * This method is called whenever the model is changed. + * + * @param e The ChangeEvent that is passed from the model. + */ + public void stateChanged(ChangeEvent e) + { + // Propagate to our listeners. + fireStateChanged(); + } + } + + /** + * A private class that holds all the information for each tab. + */ + private class Page + { + /** The tooltip string. */ + private String tip; + + /** The component associated with the tab. */ + private Component component; + + /** The active icon associated with the tab. */ + private transient Icon icon; + + /** The disabled icon associated with the tab. */ + private transient Icon disabledIcon; + + /** The tab's enabled status. */ + private transient boolean enabled = true; + + /** The string painted on the tab. */ + private transient String title; + + /** The background color of the tab. */ + private transient Color bg; + + /** The foreground color of the tab. */ + private transient Color fg; + + /** The mnemonic associated with the tab. */ + private transient int mnemonicKey; + + /** The index of the underlined character in the string. */ + private transient int underlinedChar = -1; + + /** + * Creates a new data storage for the tab. + * + * @param title The string displayed on the tab. + * @param icon The active icon displayed on the tab. + * @param component The component associated with the tab. + * @param tip The tooltip associated with the tab. + */ + protected Page(String title, Icon icon, Component component, String tip) + { + this.title = title; + this.icon = icon; + this.component = component; + this.tip = tip; + } + + /** + * This method returns the component associated with the tab. + * + * @return The component associated with the tab. + */ + public Component getComponent() + { + return component; + } + + /** + * This method sets the component associated with the tab. + * + * @param c The component associated with the tab. + */ + public void setComponent(Component c) + { + remove(component); + this.component = c; + add(c); + } + + /** + * This method returns the tooltip string. + * + * @return The tooltip string. + */ + public String getTip() + { + return tip; + } + + /** + * This method sets the tooltip string. + * + * @param tip The tooltip string. + */ + public void setTip(String tip) + { + this.tip = tip; + } + + /** + * This method returns the background color. + * + * @return The background color. + */ + public Color getBackground() + { + return bg; + } + + /** + * This method sets the background color. + * + * @param background The background color. + */ + public void setBackground(Color background) + { + bg = background; + } + + /** + * This method returns the foreground color. + * + * @return The foreground color. + */ + public Color getForeground() + { + return fg; + } + + /** + * This method sets the foreground color. + * + * @param foreground The foreground color. + */ + public void setForeground(Color foreground) + { + fg = foreground; + } + + /** + * This method returns the title associated with the tab. + * + * @return The title of the tab. + */ + public String getTitle() + { + return title; + } + + /** DOCUMENT ME! */ + private static final long serialVersionUID = 1614381073220130939L; + + /** + * This method sets the title of the tab. + * + * @param text The title of the tab. + */ + public void setTitle(String text) + { + title = text; + if (title != null && title.length() <= underlinedChar) + setDisplayedMnemonicIndex(title.length() - 1); + } + + /** + * This method returns the active icon. + * + * @return The active icon. + */ + public Icon getIcon() + { + return icon; + } + + /** + * This method sets the active icon. + * + * @param icon The active icon. + */ + public void setIcon(Icon icon) + { + this.icon = icon; + } + + /** + * This method returns the disabled icon. + * + * @return The disabled icon. + */ + public Icon getDisabledIcon() + { + if (disabledIcon == null && icon instanceof ImageIcon) + setDisabledIcon(icon); + return disabledIcon; + } + + /** + * This method sets the disabled icon. + * + * @param disabledIcon The disabled icon. + */ + public void setDisabledIcon(Icon disabledIcon) + { + this.disabledIcon = disabledIcon; + } + + /** + * This method returns whether the tab is enabled. + * + * @return Whether the tab is enabled. + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * This method sets whether the tab is enabled. + * + * @param enabled Whether this tab is enabled. + */ + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } + + /** + * This method returns the mnemonic. + * + * @return The mnemonic. + */ + public int getMnemonic() + { + return (int) mnemonicKey; + } + + /** + * This method sets the mnemonic. If the title is set, it will update the + * mnemonicIndex. + * + * @param key The mnemonic. + */ + public void setMnemonic(int key) + { + setMnemonic((char) key); + } + + /** + * This method sets the mnemonic. If the title is set, it will update the + * mnemonicIndex. + * + * @param aChar The mnemonic. + */ + public void setMnemonic(char aChar) + { + mnemonicKey = aChar; + if (title != null) + setDisplayedMnemonicIndex(title.indexOf(mnemonicKey)); + } + + /** + * This method returns the mnemonicIndex. + * + * @return The mnemonicIndex. + */ + public int getDisplayedMnemonicIndex() + { + return underlinedChar; + } + + /** + * This method sets the mnemonicIndex. + * + * @param index The mnemonicIndex. + * + * @throws IllegalArgumentException If index less than -1 || index greater + * or equal to title.length. + */ + public void setDisplayedMnemonicIndex(int index) + throws IllegalArgumentException + { + if (index < -1 || title != null && index >= title.length()) + throw new IllegalArgumentException(); + + if (title == null || mnemonicKey == 0 || (index > -1 && title.charAt(index) != mnemonicKey)) + index = -1; + + underlinedChar = index; + } + } + + private static final long serialVersionUID = 1614381073220130939L; + + /** The changeEvent used to fire changes to listeners. */ + protected ChangeEvent changeEvent; + + /** The listener that listens to the model. */ + protected ChangeListener changeListener; + + /** The model that describes this JTabbedPane. */ + protected SingleSelectionModel model; + + /** Indicates that the TabbedPane is in scrolling mode. */ + public static final int SCROLL_TAB_LAYOUT = 1; + + /** Indicates that the TabbedPane is in wrap mode. */ + public static final int WRAP_TAB_LAYOUT = 0; + + /** The current tabPlacement of the TabbedPane. */ + protected int tabPlacement = SwingConstants.TOP; + + /** The current tabLayoutPolicy of the TabbedPane. */ + private transient int layoutPolicy; + + /** The list of tabs associated with the TabbedPane. */ + transient Vector tabs = new Vector(); + + /** + * Creates a new JTabbedPane object with tabs on top and using wrap tab + * layout. + */ + public JTabbedPane() + { + this(SwingConstants.TOP, WRAP_TAB_LAYOUT); + } + + /** + * Creates a new JTabbedPane object using wrap tab layout and the given + * tabPlacement. + * + * @param tabPlacement Where the tabs will be placed. + */ + public JTabbedPane(int tabPlacement) + { + this(tabPlacement, WRAP_TAB_LAYOUT); + } + + /** + * Creates a new JTabbedPane object with the given tabPlacement and + * tabLayoutPolicy. + * + * @param tabPlacement Where the tabs will be placed. + * @param tabLayoutPolicy The way tabs will be placed. + * + * @throws IllegalArgumentException If tabLayoutPolicy or tabPlacement are + * not valid. + */ + public JTabbedPane(int tabPlacement, int tabLayoutPolicy) + { + if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT + && tabPlacement != LEFT) + throw new IllegalArgumentException("tabPlacement is not valid."); + if (tabLayoutPolicy != SCROLL_TAB_LAYOUT + && tabLayoutPolicy != WRAP_TAB_LAYOUT) + throw new IllegalArgumentException("tabLayoutPolicy is not valid."); + this.tabPlacement = tabPlacement; + layoutPolicy = tabLayoutPolicy; + + changeEvent = new ChangeEvent(this); + changeListener = createChangeListener(); + + model = new DefaultSingleSelectionModel(); + model.addChangeListener(changeListener); + + updateUI(); + } + + /** + * This method returns the UI used to display the JTabbedPane. + * + * @return The UI used to display the JTabbedPane. + */ + public TabbedPaneUI getUI() + { + return (TabbedPaneUI) ui; + } + + /** + * This method sets the UI used to display the JTabbedPane. + * + * @param ui The UI used to display the JTabbedPane. + */ + public void setUI(TabbedPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method restores the UI to the defaults given by the UIManager. + */ + public void updateUI() + { + setUI((TabbedPaneUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns a string identifier that is used to determine which + * UI will be used with the JTabbedPane. + * + * @return A string identifier for the UI. + */ + public String getUIClassID() + { + return "TabbedPaneUI"; + } + + /** + * This method creates a ChangeListener that is used to listen to the model + * for events. + * + * @return A ChangeListener to listen to the model. + */ + protected ChangeListener createChangeListener() + { + return new ModelListener(); + } + + /** + * This method adds a ChangeListener to the JTabbedPane. + * + * @param l The ChangeListener to add. + */ + public void addChangeListener(ChangeListener l) + { + listenerList.add(ChangeListener.class, l); + } + + /** + * This method removes a ChangeListener to the JTabbedPane. + * + * @param l The ChangeListener to remove. + */ + public void removeChangeListener(ChangeListener l) + { + listenerList.remove(ChangeListener.class, l); + } + + /** + * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners. + */ + protected void fireStateChanged() + { + Object[] changeListeners = listenerList.getListenerList(); + if (changeEvent == null) + changeEvent = new ChangeEvent(this); + for (int i = changeListeners.length - 2; i >= 0; i -= 2) + { + if (changeListeners[i] == ChangeListener.class) + ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent); + } + } + + /** + * This method returns all ChangeListeners registered with the JTabbedPane. + * + * @return The ChangeListeners registered with the JTabbedPane. + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) super.getListeners(ChangeListener.class); + } + + /** + * This method returns the model used with the JTabbedPane. + * + * @return The JTabbedPane's model. + */ + public SingleSelectionModel getModel() + { + return model; + } + + /** + * This method changes the model property of the JTabbedPane. + * + * @param model The new model to use with the JTabbedPane. + */ + public void setModel(SingleSelectionModel model) + { + if (model != this.model) + { + SingleSelectionModel oldModel = this.model; + this.model.removeChangeListener(changeListener); + this.model = model; + this.model.addChangeListener(changeListener); + firePropertyChange("model", oldModel, this.model); + } + } + + /** + * This method returns the tabPlacement. + * + * @return The tabPlacement used with the JTabbedPane. + */ + public int getTabPlacement() + { + return tabPlacement; + } + + /** + * This method changes the tabPlacement property of the JTabbedPane. + * + * @param tabPlacement The tabPlacement to use. + * + * @throws IllegalArgumentException If tabPlacement is not one of TOP, + * BOTTOM, LEFT, or RIGHT. + */ + public void setTabPlacement(int tabPlacement) + { + if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT + && tabPlacement != LEFT) + throw new IllegalArgumentException("tabPlacement is not valid."); + if (tabPlacement != this.tabPlacement) + { + int oldPlacement = this.tabPlacement; + this.tabPlacement = tabPlacement; + firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement); + } + } + + /** + * This method returns the tabLayoutPolicy. + * + * @return The tabLayoutPolicy. + */ + public int getTabLayoutPolicy() + { + return layoutPolicy; + } + + /** + * This method changes the tabLayoutPolicy property of the JTabbedPane. + * + * @param tabLayoutPolicy The tabLayoutPolicy to use. + * + * @throws IllegalArgumentException If tabLayoutPolicy is not one of + * SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT. + */ + public void setTabLayoutPolicy(int tabLayoutPolicy) + { + if (tabLayoutPolicy != SCROLL_TAB_LAYOUT + && tabLayoutPolicy != WRAP_TAB_LAYOUT) + throw new IllegalArgumentException("tabLayoutPolicy is not valid."); + if (tabLayoutPolicy != layoutPolicy) + { + int oldPolicy = layoutPolicy; + layoutPolicy = tabLayoutPolicy; + firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy); + } + } + + /** + * This method returns the index of the tab that is currently selected. + * + * @return The index of the selected tab. + */ + public int getSelectedIndex() + { + return model.getSelectedIndex(); + } + + /** + * This method checks the index. + * + * @param index The index to check. + * @param start DOCUMENT ME! + * @param end DOCUMENT ME! + * + * @throws IndexOutOfBoundsException DOCUMENT ME! + */ + private void checkIndex(int index, int start, int end) + { + if (index < start || index >= end) + throw new IndexOutOfBoundsException("Index < " + start + " || Index >= " + + end); + } + + /** + * This method sets the selected index. This method will hide the old + * component and show the new component. + * + * @param index The index to set it at. + */ + public void setSelectedIndex(int index) + { + checkIndex(index, -1, tabs.size()); + if (index != getSelectedIndex()) + { + if (getSelectedIndex() != -1 && getSelectedComponent() != null) + getSelectedComponent().hide(); + if (index != -1 && getComponentAt(index) != null) + getComponentAt(index).show(); + model.setSelectedIndex(index); + } + } + + /** + * This method returns the component at the selected index. + * + * @return The component at the selected index. + */ + public Component getSelectedComponent() + { + return getComponentAt(getSelectedIndex()); + } + + /** + * This method sets the component at the selected index. + * + * @param c The component associated with the selected index. + */ + public void setSelectedComponent(Component c) + { + if (c.getParent() == this) + setSelectedIndex(indexOfComponent(c)); + else + setComponentAt(getSelectedIndex(), c); + } + + /** + * 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. + */ + public void insertTab(String title, Icon icon, Component component, + String tip, int index) + { + Page p = new Page(title, icon, component, tip); + tabs.insertElementAt(p, index); + + // Hide the component so we don't see it. Do it before we parent it + // so we don't trigger a repaint. + if (component != null) + { + component.hide(); + super.add(component); + } + + if (getSelectedIndex() == -1) + setSelectedIndex(0); + + layout(); + repaint(); + } + + /** + * 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. + */ + public void addTab(String title, Icon icon, Component component, String tip) + { + insertTab(title, icon, component, tip, tabs.size()); + } + + /** + * 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. + */ + public void addTab(String title, Icon icon, Component component) + { + insertTab(title, icon, component, null, tabs.size()); + } + + /** + * This method adds a tab to the JTabbedPane. + * + * @param title The title of the tab. + * @param component The associated component. + */ + public void addTab(String title, Component component) + { + insertTab(title, null, component, null, tabs.size()); + } + + /** + * This method adds a tab to the JTabbedPane. The title of the tab is the + * Component's name. If the Component is an instance of UIResource, it + * doesn't add the tab and instead add the component directly to the + * JTabbedPane. + * + * @param component The associated component. + * + * @return The Component that was added. + */ + public Component add(Component component) + { + if (component instanceof UIResource) + super.add(component); + else + insertTab(component.getName(), null, component, null, tabs.size()); + return component; + } + + /** + * This method adds a tab to the JTabbedPane. If the Component is an + * 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. + * + * @return The Component that was added. + */ + public Component add(String title, Component component) + { + if (component instanceof UIResource) + super.add(component); + else + insertTab(title, null, component, null, tabs.size()); + return component; + } + + /** + * This method adds a tab to the JTabbedPane. If the Component is an + * instance of UIResource, it doesn't add the tab and instead add the + * component directly to the JTabbedPane. + * + * @param component The associated component. + * @param index The index to insert the tab at. + * + * @return The Component that was added. + */ + public Component add(Component component, int index) + { + if (component instanceof UIResource) + super.add(component); + else + insertTab(component.getName(), null, component, null, index); + return component; + } + + /** + * This method adds a tab to the JTabbedPane. If the Component is an + * instance of UIResource, it doesn't add the tab and instead add the + * component directly to the JTabbedPane. If the constraints object is an + * icon, it will be used as the tab's icon. If the constraints object is a + * string, we will use it as the title. + * + * @param component The associated component. + * @param constraints The constraints object. + */ + public void add(Component component, Object constraints) + { + add(component, constraints, tabs.size()); + } + + /** + * This method adds a tab to the JTabbedPane. If the Component is an + * instance of UIResource, it doesn't add the tab and instead add the + * component directly to the JTabbedPane. If the constraints object is an + * icon, it will be used as the tab's icon. If the constraints object is a + * string, we will use it as the title. + * + * @param component The associated component. + * @param constraints The constraints object. + * @param index The index to insert the tab at. + */ + public void add(Component component, Object constraints, int index) + { + if (component instanceof UIResource) + super.add(component); + else + { + if (constraints instanceof String) + insertTab((String) constraints, null, component, null, index); + else + insertTab(component.getName(), + (constraints instanceof Icon) ? (Icon) constraints : null, + component, null, index); + } + } + + /** + * 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. + * + * @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); + } + + /** + * 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. + * + * @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). + * + * @param index The index of the tab to remove. + */ + public void remove(int index) + { + removeTabAt(index); + } + + /** + * This method removes all tabs and associated components from the + * JTabbedPane. + */ + public void removeAll() + { + for (int i = tabs.size() - 1; i >= 0; i--) + removeTabAt(i); + } + + /** + * This method returns how many tabs are in the JTabbedPane. + * + * @return The number of tabs in the JTabbedPane. + */ + public int getTabCount() + { + return tabs.size(); + } + + /** + * This method returns the number of runs used to paint the JTabbedPane. + * + * @return The number of runs. + */ + public int getTabRunCount() + { + return ((TabbedPaneUI) ui).getTabRunCount(this); + } + + /** + * This method returns the tab title given the index. + * + * @param index The index of the tab. + * + * @return The title for the tab. + */ + public String getTitleAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getTitle(); + } + + /** + * This method returns the active icon given the index. + * + * @param index The index of the tab. + * + * @return The active icon for the tab. + */ + public Icon getIconAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getIcon(); + } + + /** + * This method returns the disabled icon given the index. + * + * @param index The index of the tab. + * + * @return The disabled icon for the tab. + */ + public Icon getDisabledIconAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getDisabledIcon(); + } + + /** + * This method returns the tooltip string for the tab. + * + * @param index The index of the tab. + * + * @return The tooltip string for the tab. + */ + public String getToolTipTextAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getTip(); + } + + /** + * This method returns the foreground color for the tab. + * + * @param index The index of the tab. + * + * @return The foreground color for the tab. + */ + public Color getForegroundAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getForeground(); + } + + /** + * This method returns the background color for the tab. + * + * @param index The index of the tab. + * + * @return The background color for the tab. + */ + public Color getBackgroundAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getBackground(); + } + + /** + * This method returns the component associated with the tab. + * + * @param index The index of the tab. + * + * @return The component associated with the tab. + */ + public Component getComponentAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).getComponent(); + } + + /** + * This method returns whether this tab is enabled. Disabled tabs cannot be + * selected. + * + * @param index The index of the tab. + * + * @return Whether the tab is enabled. + */ + public boolean isEnabledAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((Page) tabs.elementAt(index)).isEnabled(); + } + + /** + * This method returns the mnemonic for the tab. + * + * @param tabIndex The index of the tab. + * + * @return The mnemonic for the tab. + */ + public int getMnemonicAt(int tabIndex) + { + checkIndex(tabIndex, 0, tabs.size()); + return ((Page) tabs.elementAt(tabIndex)).getMnemonic(); + } + + /** + * This method returns the mnemonic index for the tab. + * + * @param tabIndex The index of the tab. + * + * @return The mnemonic index for the tab. + */ + public int getDisplayedMnemonicIndexAt(int tabIndex) + { + checkIndex(tabIndex, 0, tabs.size()); + return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex(); + } + + /** + * This method returns the bounds of the tab given the index. + * + * @param index The index of the tab. + * + * @return A rectangle describing the bounds of the tab. + */ + public Rectangle getBoundsAt(int index) + { + checkIndex(index, 0, tabs.size()); + return ((TabbedPaneUI) ui).getTabBounds(this, index); + } + + /** + * This method sets the title of the tab. + * + * @param index The index of the tab. + * @param title The new title. + */ + public void setTitleAt(int index, String title) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setTitle(title); + } + + /** + * This method sets the icon of the tab. + * + * @param index The index of the tab. + * @param icon The new icon. + */ + public void setIconAt(int index, Icon icon) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setIcon(icon); + } + + /** + * This method sets the disabled icon of the tab. + * + * @param index The index of the tab. + * @param disabledIcon The new disabled icon. + */ + public void setDisabledIconAt(int index, Icon disabledIcon) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon); + } + + /** + * This method sets the tooltip text of the tab. + * + * @param index The index of the tab. + * @param toolTipText The tooltip text. + */ + public void setToolTipTextAt(int index, String toolTipText) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setTip(toolTipText); + } + + /** + * This method sets the background color of the tab. + * + * @param index The index of the tab. + * @param background The background color of the tab. + */ + public void setBackgroundAt(int index, Color background) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setBackground(background); + } + + /** + * This method sets the foreground color of the tab. + * + * @param index The index of the tab. + * @param foreground The foreground color of the tab. + */ + public void setForegroundAt(int index, Color foreground) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setForeground(foreground); + } + + /** + * This method sets whether the tab is enabled. + * + * @param index The index of the tab. + * @param enabled Whether the tab is enabled. + */ + public void setEnabledAt(int index, boolean enabled) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setEnabled(enabled); + } + + /** + * This method sets the component associated with the tab. + * + * @param index The index of the tab. + * @param component The component associated with the tab. + */ + public void setComponentAt(int index, Component component) + { + checkIndex(index, 0, tabs.size()); + ((Page) tabs.elementAt(index)).setComponent(component); + } + + /** + * This method sets the displayed mnemonic index of the tab. + * + * @param tabIndex The index of the tab. + * @param mnemonicIndex The mnemonic index. + */ + public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex) + { + checkIndex(tabIndex, 0, tabs.size()); + ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex); + } + + /** + * This method sets the mnemonic for the tab. + * + * @param tabIndex The index of the tab. + * @param mnemonic The mnemonic. + */ + public void setMnemonicAt(int tabIndex, int mnemonic) + { + checkIndex(tabIndex, 0, tabs.size()); + ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic); + } + + /** + * This method finds the index of a tab given the title. + * + * @param title The title that belongs to a tab. + * + * @return The index of the tab that has the title or -1 if not found. + */ + public int indexOfTab(String title) + { + int index = -1; + for (int i = 0; i < tabs.size(); i++) + { + if (((Page) tabs.elementAt(i)).getTitle().equals(title)) + { + index = i; + break; + } + } + return index; + } + + /** + * This method finds the index of a tab given the icon. + * + * @param icon The icon that belongs to a tab. + * + * @return The index of the tab that has the icon or -1 if not found. + */ + public int indexOfTab(Icon icon) + { + int index = -1; + for (int i = 0; i < tabs.size(); i++) + { + if (((Page) tabs.elementAt(i)).getIcon() == icon) + { + index = i; + break; + } + } + return index; + } + + /** + * This method finds the index of a tab given the component. + * + * @param component A component associated with a tab. + * + * @return The index of the tab that has this component or -1 if not found. + */ + public int indexOfComponent(Component component) + { + int index = -1; + for (int i = 0; i < tabs.size(); i++) + { + if (((Page) tabs.elementAt(i)).getComponent() == component) + { + index = i; + break; + } + } + return index; + } + + /** + * This method returns a tab index given an (x,y) location. The origin of + * the (x,y) pair will be the JTabbedPane's top left position. The tab + * returned will be the one that contains the point. This method is + * delegated to the UI. + * + * @param x The x coordinate of the point. + * @param y The y coordinate of the point. + * + * @return The index of the tab that contains the point. + */ + public int indexAtLocation(int x, int y) + { + return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y); + } + + /** + * This method returns the tooltip text given a mouse event. + * + * @param event The mouse event. + * + * @return The tool tip text that is associated with this mouse event. + */ + public String getToolTipText(MouseEvent event) + { + int index = indexAtLocation(event.getX(), event.getY()); + return ((Page) tabs.elementAt(index)).getTip(); + } + + /** + * This method returns a string representation of this JTabbedPane. It is + * mainly used for debugging purposes. + * + * @return A string representation of this JTabbedPane. + */ + protected String paramString() + { + return "JTabbedPane"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJTabbedPane(); + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JTable.java b/libjava/classpath/javax/swing/JTable.java new file mode 100644 index 0000000..505a460 --- /dev/null +++ b/libjava/classpath/javax/swing/JTable.java @@ -0,0 +1,2170 @@ +/* JTable.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.Date; +import java.util.Hashtable; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.event.TableColumnModelListener; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.plaf.TableUI; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.DefaultTableColumnModel; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; + +public class JTable extends JComponent + implements TableModelListener, Scrollable, TableColumnModelListener, + ListSelectionListener, CellEditorListener, Accessible +{ + + /** + * A cell renderer for boolean values. + */ + private class BooleanCellRenderer + extends DefaultTableCellRenderer + { + + /** + * The CheckBox that is used for rendering. + */ + private JCheckBox checkBox = new JCheckBox(); + + /** + * Returns the component that is used for rendering the value. + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, int row, + int column) + { + Boolean boolValue = (Boolean) value; + checkBox.setSelected(boolValue.booleanValue()); + return checkBox; + } + } + + /** + * A cell renderer for Date values. + */ + private class DateCellRenderer + extends DefaultTableCellRenderer + { + /** + * Returns the component that is used for rendering the value. + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, int row, + int column) + { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + if (value instanceof Date) + { + Date dateValue = (Date) value; + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); + setText(df.format(dateValue)); + } + return this; + } + } + + /** + * A cell renderer for Double values. + */ + private class DoubleCellRenderer + extends DefaultTableCellRenderer + { + /** + * Creates a new instance of NumberCellRenderer. + */ + public DoubleCellRenderer() + { + setHorizontalAlignment(JLabel.RIGHT); + } + + /** + * Returns the component that is used for rendering the value. + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, int row, + int column) + { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + if (value instanceof Double) + { + Double doubleValue = (Double) value; + NumberFormat nf = NumberFormat.getInstance(); + setText(nf.format(doubleValue.doubleValue())); + } + return this; + } + } + + /** + * A cell renderer for Float values. + */ + private class FloatCellRenderer + extends DefaultTableCellRenderer + { + /** + * Creates a new instance of NumberCellRenderer. + */ + public FloatCellRenderer() + { + setHorizontalAlignment(JLabel.RIGHT); + } + + /** + * Returns the component that is used for rendering the value. + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, int row, + int column) + { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + if (value instanceof Float) + { + Float floatValue = (Float) value; + NumberFormat nf = NumberFormat.getInstance(); + setText(nf.format(floatValue.floatValue())); + } + return this; + } + } + + /** + * A cell renderer for Number values. + */ + private class NumberCellRenderer + extends DefaultTableCellRenderer + { + /** + * Creates a new instance of NumberCellRenderer. + */ + public NumberCellRenderer() + { + setHorizontalAlignment(JLabel.RIGHT); + } + } + + /** + * A cell renderer for Icon values. + */ + private class IconCellRenderer + extends DefaultTableCellRenderer + { + /** + * Returns the component that is used for rendering the value. + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, int row, + int column) + { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + if (value instanceof Icon) + { + Icon iconValue = (Icon) value; + setIcon(iconValue); + } + return this; + } + } + + private static final long serialVersionUID = 3876025080382781659L; + + + /** + * When resizing columns, do not automatically change any columns. In this + * case the table should be enclosed in a {@link JScrollPane} in order to + * accomodate cases in which the table size exceeds its visible area. + */ + public static final int AUTO_RESIZE_OFF = 0; + + /** + * When resizing column i, automatically change only the + * single column i+1 to provide or absorb excess space + * requirements. + */ + public static final int AUTO_RESIZE_NEXT_COLUMN = 1; + + /** + * When resizing column i in a table of n + * columns, automatically change all columns in the range [i+1, + * n), uniformly, to provide or absorb excess space requirements. + */ + public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2; + + /** + * When resizing column i in a table of n + * columns, automatically change all columns in the range [0, + * n) (with the exception of column i) uniformly, to provide or + * absorb excess space requirements. + */ + public static final int AUTO_RESIZE_ALL_COLUMNS = 4; + + /** + * When resizing column i in a table of n + * columns, automatically change column n-1 (the last column + * in the table) to provide or absorb excess space requirements. + */ + public static final int AUTO_RESIZE_LAST_COLUMN = 3; + + + /** + * A table mapping {@link java.lang.Class} objects to + * {@link TableCellEditor} objects. This table is consulted by the + * FIXME + */ + protected Hashtable defaultEditorsByColumnClass; + + /** + * A table mapping {@link java.lang.Class} objects to + * {@link TableCellEditor} objects. This table is consulted by the + * FIXME + */ + protected Hashtable defaultRenderersByColumnClass; + + /** + * The column that is edited, -1 if the table is not edited currently. + */ + protected int editingColumn; + + /** + * The row that is edited, -1 if the table is not edited currently. + */ + protected int editingRow; + + /** + * The component that is used for editing. + * null if the table is not editing currently. + * + */ + protected transient Component editorComp; + + /** + * Whether or not the table should automatically compute a matching + * {@link TableColumnModel} and assign it to the {@link #columnModel} + * property when the {@link #dataModel} property is changed. + * + * @see #setModel(TableModel) + * @see #createColumnsFromModel() + * @see #setColumnModel(TableColumnModel) + * @see #setAutoCreateColumnsFromModel(boolean) + * @see #getAutoCreateColumnsFromModel() + */ + protected boolean autoCreateColumnsFromModel; + + /** + * A numeric code specifying the resizing behavior of the table. Must be + * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link + * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link + * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}. + * + * @see #doLayout() + * @see #setAutoResizeMode(int) + * @see #getAutoResizeMode() + */ + protected int autoResizeMode; + + /** + * The height in pixels of any row of the table. All rows in a table are + * of uniform height. This differs from column width, which varies on a + * per-column basis, and is stored in the individual columns of the + * {@link #columnModel}. + * + * @see #getRowHeight() + * @see #setRowHeight(int) + * @see TableColumn#getWidth() + * @see TableColumn#setWidth(int) + */ + protected int rowHeight; + + /** + * The height in pixels of the gap left between any two rows of the table. + * + * @see #setRowMargin(int) + * @see #getRowHeight() + * @see #getIntercellSpacing() + * @see #setIntercellSpacing(Dimension) + * @see TableColumnModel#getColumnMargin() + * @see TableColumnModel#setColumnMargin(int) + */ + protected int rowMargin; + + /** + * Whether or not the table should allow row selection. If the table + * allows both row and column selection, it is said to allow + * "cell selection". Previous versions of the JDK supported cell + * selection as an independent concept, but it is now represented solely + * in terms of simultaneous row and column selection. + * + * @see TableColumnModel#getColumnSelectionAllowed() + * @see #setRowSelectionAllowed(boolean) + * @see #getRowSelectionAllowed() + * @see #getCellSelectionEnabled() + * @see #setCellSelectionEnabled(boolean) + */ + protected boolean rowSelectionAllowed; + + /** + * @deprecated Use {@link #rowSelectionAllowed}, {@link + * #getColumnSelectionAllowed}, or the combined methods {@link + * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}. + */ + protected boolean cellSelectionEnabled; + + /** + * The model for data stored in the table. Confusingly, the published API + * requires that this field be called dataModel, despite its + * property name. The table listens to its model as a {@link + * TableModelListener}. + * + * @see #tableChanged(TableModelEvent) + * @see TableModel#addTableModelListener(TableModelListener) + */ + protected TableModel dataModel; + + /** + *

A model of various aspects of the columns of the table, not + * including the data stored in them. The {@link TableColumnModel} + * is principally concerned with holding a set of {@link TableColumn} + * objects, each of which describes the display parameters of a column + * and the numeric index of the column from the data model which the + * column is presenting.

+ * + *

The TableColumnModel also contains a {@link ListSelectionModel} which + * indicates which columns are currently selected. This selection model + * works in combination with the {@link #selectionModel} of the table + * itself to specify a table selection: a combination of row and + * column selections.

+ * + *

Most application programmers do not need to work with this property + * at all: setting {@link #autoCreateColumnsFromModel} will construct the + * columnModel automatically, and the table acts as a facade for most of + * the interesting properties of the columnModel anyways.

+ * + * @see #setColumnModel(TableColumnModel) + * @see #getColumnModel() + */ + protected TableColumnModel columnModel; + + /** + * A model of the rows of this table which are currently selected. This + * model is used in combination with the column selection model held as a + * member of the {@link #columnModel} property, to represent the rows and + * columns (or both: cells) of the table which are currently selected. + * + * @see #rowSelectionAllowed + * @see #setSelectionModel(ListSelectionModel) + * @see #getSelectionModel() + * @see TableColumnModel#getSelectionModel() + * @see ListSelectionModel#addListSelectionListener(ListSelectionListener) + */ + protected ListSelectionModel selectionModel; + + /** + * The accessibleContext property. + */ + protected AccessibleContext accessibleContext; + + /** + * The current cell editor. + */ + protected TableCellEditor cellEditor; + + /** + * Whether or not drag-and-drop is enabled on this table. + * + * @see #setDragEnabled() + * @see #getDragEnabled() + */ + private boolean dragEnabled; + + /** + * The color to paint the grid lines of the table, when either {@link + * #showHorizontalLines} or {@link #showVerticalLines} is set. + * + * @see #setGridColor(Color) + * @see #getGridColor() + */ + protected Color gridColor; + + /** + * The size this table would prefer its viewport assume, if it is + * contained in a {@link JScrollPane}. + * + * @see #setPreferredScrollableViewportSize(Dimension) + * @see #getPreferredScrollableViewportSize() + */ + protected Dimension preferredViewportSize; + + /** + * The color to paint the background of selected cells. Fires a property + * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY} + * when its value changes. + * + * @see #setSelectionBackground(Color) + * @see #getSelectionBackground() + */ + protected Color selectionBackground; + + /** + * The name carried in property change events when the {@link + * #selectionBackground} property changes. + */ + private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground"; + + /** + * The color to paint the foreground of selected cells. Fires a property + * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY} + * when its value changes. + * + * @see #setSelectionForeground(Color) + * @see #getSelectionForeground() + */ + protected Color selectionForeground; + + /** + * The name carried in property change events when the + * {@link #selectionForeground} property changes. + */ + private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground"; + + /** + * The showHorizontalLines property. + */ + protected boolean showHorizontalLines; + + /** + * The showVerticalLines property. + */ + protected boolean showVerticalLines; + + /** + * The tableHeader property. + */ + protected JTableHeader tableHeader; + + + /** + * Creates a new JTable instance. + */ + public JTable () + { + this(null, null, null); + } + + /** + * Creates a new JTable instance. + * + * @param numRows an int value + * @param numColumns an int value + */ + public JTable (int numRows, int numColumns) + { + this(new DefaultTableModel(numRows, numColumns)); + } + + /** + * Creates a new JTable instance. + * + * @param data an Object[][] value + * @param columnNames an Object[] value + */ + public JTable(Object[][] data, Object[] columnNames) + { + this(new DefaultTableModel(data, columnNames)); + } + + /** + * Creates a new JTable instance. + * + * @param dm a TableModel value + */ + public JTable (TableModel dm) + { + this(dm, null, null); + } + + /** + * Creates a new JTable instance. + * + * @param dm a TableModel value + * @param cm a TableColumnModel value + */ + public JTable (TableModel dm, TableColumnModel cm) + { + this(dm, cm, null); + } + + /** + * Creates a new JTable instance. + * + * @param dm a TableModel value + * @param cm a TableColumnModel value + * @param sm a ListSelectionModel value + */ + public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm) + { + setModel(dm == null ? createDefaultDataModel() : dm); + setSelectionModel(sm == null ? createDefaultSelectionModel() : sm); + + this.columnModel = cm; + initializeLocalVars(); + updateUI(); + } + + protected void initializeLocalVars() + { + setTableHeader(createDefaultTableHeader()); + this.autoCreateColumnsFromModel = false; + if (columnModel == null) + { + this.autoCreateColumnsFromModel = true; + createColumnsFromModel(); + } + this.columnModel.addColumnModelListener(this); + + this.defaultRenderersByColumnClass = new Hashtable(); + createDefaultRenderers(); + + this.defaultEditorsByColumnClass = new Hashtable(); + createDefaultEditors(); + + this.autoResizeMode = AUTO_RESIZE_ALL_COLUMNS; + this.rowHeight = 16; + this.rowMargin = 1; + this.rowSelectionAllowed = true; + // this.accessibleContext = new AccessibleJTable(); + this.cellEditor = null; + // COMPAT: Both Sun and IBM have drag enabled + this.dragEnabled = true; + this.preferredViewportSize = new Dimension(450,400); + this.showHorizontalLines = true; + this.showVerticalLines = true; + this.editingColumn = -1; + this.editingRow = -1; + setIntercellSpacing(new Dimension(1,1)); + } + + /** + * Creates a new JTable instance. + * + * @param data a Vector value + * @param columnNames a Vector value + */ + public JTable(Vector data, Vector columnNames) + { + this(new DefaultTableModel(data, columnNames)); + } + + public void addColumn(TableColumn column) + { + if (column.getHeaderValue() == null) + { + String name = dataModel.getColumnName(column.getModelIndex()); + column.setHeaderValue(name); + } + + columnModel.addColumn(column); + } + + protected void createDefaultEditors() + { + //FIXME: Create the editor object. + } + + protected void createDefaultRenderers() + { + setDefaultRenderer(Boolean.class, new BooleanCellRenderer()); + setDefaultRenderer(Number.class, new NumberCellRenderer()); + setDefaultRenderer(Double.class, new DoubleCellRenderer()); + setDefaultRenderer(Double.class, new FloatCellRenderer()); + setDefaultRenderer(Date.class, new DateCellRenderer()); + setDefaultRenderer(Icon.class, new IconCellRenderer()); + } + + /** + * @deprecated 1.0.2, replaced by new JScrollPane(JTable) + */ + public static JScrollPane createScrollPaneForTable(JTable table) + { + return new JScrollPane(table); + } + + protected TableColumnModel createDefaultColumnModel() + { + return new DefaultTableColumnModel(); + } + + protected TableModel createDefaultDataModel() + { + return new DefaultTableModel(); + } + + protected ListSelectionModel createDefaultSelectionModel() + { + return new DefaultListSelectionModel(); + } + + protected JTableHeader createDefaultTableHeader() + { + 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) + { + revalidate(); + repaint(); + } + + public void columnMarginChanged (ChangeEvent event) + { + revalidate(); + repaint(); + } + + public void columnMoved (TableColumnModelEvent event) + { + revalidate(); + repaint(); + } + + public void columnRemoved (TableColumnModelEvent event) + { + revalidate(); + repaint(); + } + + public void columnSelectionChanged (ListSelectionEvent event) + { + repaint(); + } + + public void editingCanceled (ChangeEvent event) + { + repaint(); + } + + public void editingStopped (ChangeEvent event) + { + repaint(); + } + + public void tableChanged (TableModelEvent event) + { + // update the column model from the table model if the structure has + // changed and the flag autoCreateColumnsFromModel is set + if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW) + && autoCreateColumnsFromModel) + + createColumnsFromModel(); + + repaint(); + } + + public void valueChanged (ListSelectionEvent event) + { + repaint(); + } + + /** + * Returns index of the column that contains specified point + * or -1 if this table doesn't contain this point. + * + * @param point point to identify the column + * @return index of the column that contains specified point or + * -1 if this table doesn't contain this point. + */ + public int columnAtPoint(Point point) + { + int x0 = getLocation().x; + int ncols = getColumnCount(); + Dimension gap = getIntercellSpacing(); + TableColumnModel cols = getColumnModel(); + int x = point.x; + + for (int i = 0; i < ncols; ++i) + { + int width = cols.getColumn(i).getWidth() + (gap == null ? 0 : gap.width); + if (0 <= x && x < width) + return i; + x -= width; + } + + return -1; + } + + /** + * Returns index of the row that contains specified point or + * -1 if this table doesn't contain this point. + * + * @param point point to identify the row + * @return index of the row that contains specified point or + * -1 if this table doesn't contain this point. + */ + public int rowAtPoint(Point point) + { + int y0 = getLocation().y; + int nrows = getRowCount(); + Dimension gap = getIntercellSpacing(); + int height = getRowHeight() + (gap == null ? 0 : gap.height); + int y = point.y; + + for (int i = 0; i < nrows; ++i) + { + if (0 <= y && y < height) + return i; + y -= height; + } + + return -1; + } + + /** + * Calculate the visible rectangle for a particular row and column. The + * row and column are specified in visual terms; the column may not match + * the {@link #dataModel} column. + * + * @param row the visible row to get the cell rectangle of + * + * @param column the visible column to get the cell rectangle of, which may + * differ from the {@link #dataModel} column + * + * @param includeSpacing whether or not to include the cell margins in the + * resulting cell. If false, the result will only contain the + * inner area of the target cell, not including its margins. + * + * @return a rectangle enclosing the specified cell + */ + public Rectangle getCellRect(int row, + int column, + boolean includeSpacing) + { + int height = getHeight(); + int width = columnModel.getColumn(column).getWidth(); + int x_gap = columnModel.getColumnMargin(); + int y_gap = rowMargin; + + column = Math.max(0, Math.min(column, getColumnCount() - 1)); + row = Math.max(0, Math.min(row, getRowCount() - 1)); + + int x = 0; + int y = (height + y_gap) * row; + + for (int i = 0; i < column; ++i) + { + x += columnModel.getColumn(i).getWidth(); + x += x_gap; + } + + if (includeSpacing) + return new Rectangle(x, y, width, height); + else + return new Rectangle(x, y, width - x_gap, height - y_gap); + } + + public void clearSelection() + { + selectionModel.clearSelection(); + getColumnModel().getSelectionModel().clearSelection(); + } + + /** + * Get the value of the selectedRow property by delegation to + * the {@link ListSelectionModel#getMinSelectionIndex} method of the + * {@link #selectionModel} field. + * + * @return The current value of the selectedRow property + */ + public int getSelectedRow () + { + return selectionModel.getMinSelectionIndex(); + } + + /** + * Get the value of the {@link #selectionModel} property. + * + * @return The current value of the property + */ + public ListSelectionModel getSelectionModel() + { + //Neither Sun nor IBM returns null if rowSelection not allowed + return selectionModel; + } + + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) + { + if (orientation == SwingConstants.VERTICAL) + return visibleRect.height * direction; + else + return visibleRect.width * direction; + } + + /** + * Get the value of the scrollableTracksViewportHeight property. + * + * @return The constant value false + */ + public boolean getScrollableTracksViewportHeight() + { + return false; + } + + /** + * Get the value of the scrollableTracksViewportWidth property. + * + * @return true unless the {@link #autoResizeMode} property is + * AUTO_RESIZE_OFF + */ + public boolean getScrollableTracksViewportWidth() + { + if (autoResizeMode == AUTO_RESIZE_OFF) + return false; + else + return true; + } + + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) + { + // FIXME: I don't exactly know what sun does here. in both cases they + // pick values which do *not* simply expose the next cell in a given + // scroll direction. + + if (orientation == SwingConstants.VERTICAL) + return rowHeight; + else + { + int sum = 0; + for (int i = 0; i < getColumnCount(); ++i) + sum += columnModel.getColumn(0).getWidth(); + return getColumnCount() == 0 ? 10 : sum / getColumnCount(); + } + } + + + public TableCellEditor getCellEditor(int row, int column) + { + TableCellEditor editor = columnModel.getColumn(column).getCellEditor(); + + if (editor == null) + editor = getDefaultEditor(dataModel.getColumnClass(column)); + + return editor; + } + + public TableCellEditor getDefaultEditor(Class columnClass) + { + if (defaultEditorsByColumnClass.containsKey(columnClass)) + return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass); + else + { + // FIXME: We have at least an editor for Object.class in our defaults. + TableCellEditor r = new DefaultCellEditor(new JTextField()); + defaultEditorsByColumnClass.put(columnClass, r); + return r; + } + } + + + + public TableCellRenderer getCellRenderer(int row, int column) + { + TableCellRenderer renderer = + columnModel.getColumn(column).getCellRenderer(); + + if (renderer == null) + renderer = getDefaultRenderer(dataModel.getColumnClass(column)); + + return renderer; + } + + public void setDefaultRenderer(Class columnClass, TableCellRenderer rend) + { + defaultRenderersByColumnClass.put(columnClass, rend); + } + + public TableCellRenderer getDefaultRenderer(Class columnClass) + { + if (defaultRenderersByColumnClass.containsKey(columnClass)) + return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass); + else + { + TableCellRenderer r = new DefaultTableCellRenderer(); + defaultRenderersByColumnClass.put(columnClass, r); + return r; + } + } + + public int convertColumnIndexToModel(int vc) + { + if (vc < 0) + return vc; + else + return columnModel.getColumn(vc).getModelIndex(); + } + + public int convertColumnIndexToView(int mc) + { + if (mc < 0) + return mc; + int ncols = getColumnCount(); + for (int vc = 0; vc < ncols; ++vc) + { + if (columnModel.getColumn(vc).getModelIndex() == mc) + return vc; + } + return -1; + } + + public Component prepareRenderer(TableCellRenderer renderer, + int row, + int column) + { + boolean rsa = getRowSelectionAllowed(); + boolean csa = getColumnSelectionAllowed(); + boolean rs = rsa ? getSelectionModel().isSelectedIndex(row) : false; + boolean cs = csa ? columnModel.getSelectionModel().isSelectedIndex(column) : false; + boolean isSelected = ((rsa && csa && rs && cs) + || (rsa && !csa && rs) + || (!rsa && csa && cs)); + + return renderer.getTableCellRendererComponent(this, + dataModel.getValueAt(row, + convertColumnIndexToModel(column)), + isSelected, + false, // hasFocus + row, column); + } + + + /** + * Get the value of the {@link #autoCreateColumnsFromModel} property. + * + * @return The current value of the property + */ + public boolean getAutoCreateColumnsFromModel() + { + return autoCreateColumnsFromModel; + } + + /** + * Get the value of the {@link #autoResizeMode} property. + * + * @return The current value of the property + */ + public int getAutoResizeMode() + { + return autoResizeMode; + } + + /** + * Get the value of the {@link #rowHeight} property. + * + * @return The current value of the property + */ + public int getRowHeight() + { + return rowHeight; + } + + /** + * Get the value of the {@link #rowMargin} property. + * + * @return The current value of the property + */ + public int getRowMargin() + { + return rowMargin; + } + + /** + * Get the value of the {@link #rowSelectionAllowed} property. + * + * @return The current value of the property + */ + public boolean getRowSelectionAllowed() + { + return rowSelectionAllowed; + } + + /** + * Get the value of the {@link #cellSelectionEnabled} property. + * + * @return The current value of the property + */ + public boolean getCellSelectionEnabled() + { + return getColumnSelectionAllowed() && getRowSelectionAllowed(); + } + + /** + * Get the value of the {@link #dataModel} property. + * + * @return The current value of the property + */ + public TableModel getModel() + { + return dataModel; + } + + /** + * Get the value of the columnCount property by + * delegation to the @{link #columnModel} field. + * + * @return The current value of the columnCount property + */ + public int getColumnCount() + { + return columnModel.getColumnCount(); + } + + /** + * Get the value of the rowCount property by + * delegation to the @{link #dataModel} field. + * + * @return The current value of the rowCount property + */ + public int getRowCount() + { + return dataModel.getRowCount(); + } + + /** + * Get the value of the {@link #columnModel} property. + * + * @return The current value of the property + */ + public TableColumnModel getColumnModel() + { + return columnModel; + } + + /** + * Get the value of the selectedColumn property by + * delegation to the @{link #columnModel} field. + * + * @return The current value of the selectedColumn property + */ + public int getSelectedColumn() + { + return columnModel.getSelectionModel().getMinSelectionIndex(); + } + + private static int countSelections(ListSelectionModel lsm) + { + int lo = lsm.getMinSelectionIndex(); + int hi = lsm.getMaxSelectionIndex(); + int sum = 0; + if (lo != -1 && hi != -1) + { + switch (lsm.getSelectionMode()) + { + case ListSelectionModel.SINGLE_SELECTION: + sum = 1; + break; + + case ListSelectionModel.SINGLE_INTERVAL_SELECTION: + sum = hi - lo + 1; + break; + + case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + if (lsm.isSelectedIndex(i)) + ++sum; + break; + } + } + return sum; + } + + private static int[] getSelections(ListSelectionModel lsm) + { + int sz = countSelections(lsm); + int [] ret = new int[sz]; + + int lo = lsm.getMinSelectionIndex(); + int hi = lsm.getMaxSelectionIndex(); + int j = 0; + java.util.ArrayList ls = new java.util.ArrayList(); + if (lo != -1 && hi != -1) + { + switch (lsm.getSelectionMode()) + { + case ListSelectionModel.SINGLE_SELECTION: + ret[0] = lo; + break; + + case ListSelectionModel.SINGLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + ret[j++] = i; + break; + + case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + if (lsm.isSelectedIndex(i)) + ret[j++] = i; + break; + } + } + return ret; + } + + /** + * Get the value of the selectedColumnCount property by + * delegation to the @{link #columnModel} field. + * + * @return The current value of the selectedColumnCount property + */ + public int getSelectedColumnCount() + { + return countSelections(columnModel.getSelectionModel()); + } + + /** + * Get the value of the selectedColumns property by + * delegation to the @{link #columnModel} field. + * + * @return The current value of the selectedColumns property + */ + public int[] getSelectedColumns() + { + return getSelections(columnModel.getSelectionModel()); + } + + /** + * Get the value of the columnSelectionAllowed property. + * + * @return The current value of the columnSelectionAllowed property + */ + public boolean getColumnSelectionAllowed() + { + return getColumnModel().getColumnSelectionAllowed(); + } + + /** + * Get the value of the selectedRowCount property by + * delegation to the @{link #selectionModel} field. + * + * @return The current value of the selectedRowCount property + */ + public int getSelectedRowCount() + { + return countSelections(selectionModel); + } + + /** + * Get the value of the selectedRows property by + * delegation to the @{link #selectionModel} field. + * + * @return The current value of the selectedRows property + */ + public int[] getSelectedRows() + { + return getSelections(selectionModel); + } + + /** + * Get the value of the {@link #accessibleContext} property. + * + * @return The current value of the property + */ + public AccessibleContext getAccessibleContext() + { + return accessibleContext; + } + + /** + * Get the value of the {@link #cellEditor} property. + * + * @return The current value of the property + */ + public TableCellEditor getCellEditor() + { + return cellEditor; + } + + /** + * Get the value of the {@link #dragEnabled} property. + * + * @return The current value of the property + */ + public boolean getDragEnabled() + { + return dragEnabled; + } + + /** + * Get the value of the {@link #gridColor} property. + * + * @return The current value of the property + */ + public Color getGridColor() + { + return gridColor; + } + + /** + * Get the value of the intercellSpacing property. + * + * @return The current value of the property + */ + public Dimension getIntercellSpacing() + { + return new Dimension(columnModel.getColumnMargin(), rowMargin); + } + + /** + * Get the value of the {@link #preferredViewportSize} property. + * + * @return The current value of the property + */ + public Dimension getPreferredScrollableViewportSize() + { + return preferredViewportSize; + } + + /** + * Get the value of the {@link #selectionBackground} property. + * + * @return The current value of the property + */ + public Color getSelectionBackground() + { + return selectionBackground; + } + + /** + * Get the value of the {@link #selectionForeground} property. + * + * @return The current value of the property + */ + public Color getSelectionForeground() + { + return selectionForeground; + } + + /** + * Get the value of the {@link #showHorizontalLines} property. + * + * @return The current value of the property + */ + public boolean getShowHorizontalLines() + { + return showHorizontalLines; + } + + /** + * Get the value of the {@link #showVerticalLines} property. + * + * @return The current value of the property + */ + public boolean getShowVerticalLines() + { + return showVerticalLines; + } + + /** + * Get the value of the {@link #tableHeader} property. + * + * @return The current value of the property + */ + public JTableHeader getTableHeader() + { + return tableHeader; + } + + /** + * Removes specified column from displayable columns of this table. + * + * @param column column to removed + */ + public void removeColumn(TableColumn column) + { + columnModel.removeColumn(column); + } + + /** + * Moves column at the specified index to new given location. + * + * @param column index of the column to move + * @param targetColumn index specifying new location of the column + */ + public void moveColumn(int column,int targetColumn) + { + columnModel.moveColumn(column, targetColumn); + } + + /** + * Set the value of the {@link #autoCreateColumnsFromModel} flag. If the + * flag changes from false to true, the + * {@link #createDefaultColumnsFromModel()} method is called. + * + * @param autoCreate the new value of the flag. + */ + public void setAutoCreateColumnsFromModel(boolean autoCreate) + { + if (autoCreateColumnsFromModel != autoCreate) + { + autoCreateColumnsFromModel = autoCreate; + if (autoCreate) + createDefaultColumnsFromModel(); + } + } + + /** + * Set the value of the {@link #autoResizeMode} property. + * + * @param a The new value of the autoResizeMode property + */ + public void setAutoResizeMode(int a) + { + autoResizeMode = a; + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #rowHeight} property. + * + * @param r The new value of the rowHeight property + */ + public void setRowHeight(int r) + { + if (rowHeight < 1) + throw new IllegalArgumentException(); + + rowHeight = r; + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #rowMargin} property. + * + * @param r The new value of the rowMargin property + */ + public void setRowMargin(int r) + { + rowMargin = r; + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #rowSelectionAllowed} property. + * + * @param r The new value of the rowSelectionAllowed property + */ + public void setRowSelectionAllowed(boolean r) + { + rowSelectionAllowed = r; + repaint(); + } + + /** + * Set the value of the {@link #cellSelectionEnabled} property. + * + * @param c The new value of the cellSelectionEnabled property + */ + public void setCellSelectionEnabled(boolean c) + { + setColumnSelectionAllowed(c); + setRowSelectionAllowed(c); + // for backward-compatibility sake: + cellSelectionEnabled = true; + } + + /** + *

Set the value of the {@link #dataModel} property.

+ * + *

Unregister this as a {@link TableModelListener} from + * previous {@link #dataModel} and register it with new parameter + * m.

+ * + * @param m The new value of the model property + */ + public void setModel(TableModel m) + { + // Throw exception is m is null. + if (m == null) + throw new IllegalArgumentException(); + + // Don't do anything if setting the current model again. + if (dataModel == m) + return; + + // Remove table as TableModelListener from old model. + if (dataModel != null) + dataModel.removeTableModelListener(this); + + if (m != null) + { + // Set property. + dataModel = m; + + // Add table as TableModelListener to new model. + dataModel.addTableModelListener(this); + + // Automatically create columns. + if (autoCreateColumnsFromModel) + createColumnsFromModel(); + } + + // Repaint table. + revalidate(); + repaint(); + } + + /** + *

Set the value of the {@link #columnModel} property.

+ * + *

Unregister this as a {@link TableColumnModelListener} + * from previous {@link #columnModel} and register it with new parameter + * c.

+ * + * @param c The new value of the columnModel property + */ + public void setColumnModel(TableColumnModel c) + { + if (c == null) + throw new IllegalArgumentException(); + TableColumnModel tmp = columnModel; + if (tmp != null) + tmp.removeColumnModelListener(this); + if (c != null) + c.addColumnModelListener(this); + columnModel = c; + if (dataModel != null && columnModel != null) + { + int ncols = getColumnCount(); + for (int i = 0; i < ncols; ++i) + columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i)); + } + + // according to Sun's spec we also have to set the tableHeader's + // column model here + if (tableHeader != null) + tableHeader.setColumnModel(c); + + revalidate(); + repaint(); + } + + /** + * Set the value of the columnSelectionAllowed property. + * + * @param c The new value of the property + */ + public void setColumnSelectionAllowed(boolean c) + { + getColumnModel().setColumnSelectionAllowed(c); + repaint(); + } + + /** + *

Set the value of the {@link #selectionModel} property.

+ * + *

Unregister this as a {@link ListSelectionListener} + * from previous {@link #selectionModel} and register it with new + * parameter s.

+ * + * @param s The new value of the selectionModel property + */ + public void setSelectionModel(ListSelectionModel s) + { + if (s == null) + throw new IllegalArgumentException(); + ListSelectionModel tmp = selectionModel; + if (tmp != null) + tmp.removeListSelectionListener(this); + if (s != null) + s.addListSelectionListener(this); + selectionModel = s; + } + + /** + * Set the value of the selectionMode property by + * delegation to the {@link #selectionModel} field. The same selection + * mode is set for row and column selection models. + * + * @param s The new value of the property + */ + public void setSelectionMode(int s) + { + selectionModel.setSelectionMode(s); + columnModel.getSelectionModel().setSelectionMode(s); + + repaint(); + } + + /** + *

Set the value of the {@link #cellEditor} property.

+ * + *

Unregister this as a {@link CellEditorListener} from + * previous {@link #cellEditor} and register it with new parameter + * c.

+ * + * @param c The new value of the cellEditor property + */ + public void setCellEditor(TableCellEditor c) + { + TableCellEditor tmp = cellEditor; + if (tmp != null) + tmp.removeCellEditorListener(this); + if (c != null) + c.addCellEditorListener(this); + cellEditor = c; + } + + /** + * Set the value of the {@link #dragEnabled} property. + * + * @param d The new value of the dragEnabled property + */ + public void setDragEnabled(boolean d) + { + dragEnabled = d; + } + + /** + * Set the value of the {@link #gridColor} property. + * + * @param g The new value of the gridColor property + */ + public void setGridColor(Color g) + { + gridColor = g; + repaint(); + } + + /** + * Set the value of the intercellSpacing property. + * + * @param i The new value of the intercellSpacing property + */ + public void setIntercellSpacing(Dimension i) + { + rowMargin = i.height; + columnModel.setColumnMargin(i.width); + repaint(); + } + + /** + * Set the value of the {@link #preferredViewportSize} property. + * + * @param p The new value of the preferredViewportSize property + */ + public void setPreferredScrollableViewportSize(Dimension p) + { + preferredViewportSize = p; + revalidate(); + repaint(); + } + + /** + *

Set the value of the {@link #selectionBackground} property.

+ * + *

Fire a PropertyChangeEvent with name {@link + * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if + * selectionBackground changed.

+ * + * @param s The new value of the selectionBackground property + */ + public void setSelectionBackground(Color s) + { + Color tmp = selectionBackground; + selectionBackground = s; + if (((tmp == null && s != null) + || (s == null && tmp != null) + || (tmp != null && s != null && !tmp.equals(s)))) + firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s); + repaint(); + } + + /** + *

Set the value of the {@link #selectionForeground} property.

+ * + *

Fire a PropertyChangeEvent with name {@link + * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if + * selectionForeground changed.

+ * + * @param s The new value of the selectionForeground property + */ + public void setSelectionForeground(Color s) + { + Color tmp = selectionForeground; + selectionForeground = s; + if (((tmp == null && s != null) + || (s == null && tmp != null) + || (tmp != null && s != null && !tmp.equals(s)))) + firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s); + repaint(); + } + + /** + * Set the value of the showGrid property. + * + * @param s The new value of the showGrid property + */ + public void setShowGrid(boolean s) + { + setShowVerticalLines(s); + setShowHorizontalLines(s); + } + + /** + * Set the value of the {@link #showHorizontalLines} property. + * + * @param s The new value of the showHorizontalLines property + */ + public void setShowHorizontalLines(boolean s) + { + showHorizontalLines = s; + repaint(); + } + + /** + * Set the value of the {@link #showVerticalLines} property. + * + * @param s The new value of the showVerticalLines property + */ + public void setShowVerticalLines(boolean s) + { + showVerticalLines = s; + repaint(); + } + + /** + * Set the value of the {@link #tableHeader} property. + * + * @param t The new value of the tableHeader property + */ + public void setTableHeader(JTableHeader t) + { + if (tableHeader != null) + tableHeader.setTable(null); + tableHeader = t; + if (tableHeader != null) + tableHeader.setTable(this); + revalidate(); + repaint(); + } + + protected void configureEnclosingScrollPane() + { + JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this); + if (jsp != null && tableHeader != null) + { + jsp.setColumnHeaderView(tableHeader); + } + } + + protected void unconfigureEnclosingScrollPane() + { + JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this); + if (jsp != null) + { + jsp.setColumnHeaderView(null); + } + } + + + public void addNotify() + { + super.addNotify(); + configureEnclosingScrollPane(); + } + + public void removeNotify() + { + super.addNotify(); + unconfigureEnclosingScrollPane(); + } + + + /** + * This distributes the superfluous width in a table evenly on its columns. + * + * The implementation used here is different to that one described in + * the JavaDocs. It is much simpler, and seems to work very well. + * + * TODO: correctly implement the algorithm described in the JavaDoc + */ + private void distributeSpill(TableColumn[] cols, int spill) + { + int average = spill / cols.length; + for (int i = 0; i < cols.length; i++) + { + cols[i].setWidth(cols[i].getWidth() + average); + } + } + + public void doLayout() + { + TableColumn resizingColumn = null; + + int ncols = getColumnCount(); + if (ncols < 1) + return; + + int[] pref = new int[ncols]; + int prefSum = 0; + int rCol = -1; + + if (tableHeader != null) + resizingColumn = tableHeader.getResizingColumn(); + + for (int i = 0; i < ncols; ++i) + { + TableColumn col = columnModel.getColumn(i); + int p = col.getWidth(); + pref[i] = p; + prefSum += p; + if (resizingColumn == col) + rCol = i; + } + + int spill = getWidth() - prefSum; + + if (resizingColumn != null) + { + TableColumn col; + TableColumn [] cols; + + switch (getAutoResizeMode()) + { + case AUTO_RESIZE_LAST_COLUMN: + col = columnModel.getColumn(ncols-1); + col.setWidth(col.getPreferredWidth() + spill); + break; + + case AUTO_RESIZE_NEXT_COLUMN: + col = columnModel.getColumn(ncols-1); + col.setWidth(col.getPreferredWidth() + spill); + break; + + case AUTO_RESIZE_ALL_COLUMNS: + cols = new TableColumn[ncols]; + for (int i = 0; i < ncols; ++i) + cols[i] = columnModel.getColumn(i); + distributeSpill(cols, spill); + break; + + case AUTO_RESIZE_SUBSEQUENT_COLUMNS: + cols = new TableColumn[ncols]; + for (int i = rCol; i < ncols; ++i) + cols[i] = columnModel.getColumn(i); + distributeSpill(cols, spill); + break; + + case AUTO_RESIZE_OFF: + default: + } + } + else + { + TableColumn [] cols = new TableColumn[ncols]; + for (int i = 0; i < ncols; ++i) + cols[i] = columnModel.getColumn(i); + distributeSpill(cols, spill); + } + } + + /** + * @deprecated Replaced by doLayout() + */ + public void sizeColumnsToFit(boolean lastColumnOnly) + { + doLayout(); + } + + /** + * Obsolete since JDK 1.4. Please use doLayout(). + */ + public void sizeColumnsToFit(int resizingColumn) + { + doLayout(); + } + + public String getUIClassID() + { + return "TableUI"; + } + + /** + * This method returns the table's UI delegate. + * + * @return The table's UI delegate. + */ + public TableUI getUI() + { + return (TableUI) ui; + } + + /** + * This method sets the table's UI delegate. + * + * @param ui The table's UI delegate. + */ + public void setUI(TableUI ui) + { + super.setUI(ui); + } + + public void updateUI() + { + setUI((TableUI) UIManager.getUI(this)); + revalidate(); + repaint(); + } + + public Class getColumnClass(int column) + { + return dataModel.getColumnClass(column); + } + + public String getColumnName(int column) + { + int modelColumn = columnModel.getColumn(column).getModelIndex(); + return dataModel.getColumnName(modelColumn); + } + + public int getEditingColumn() + { + return editingColumn; + } + + public void setEditingColumn(int column) + { + editingColumn = column; + } + + public int getEditingRow() + { + return editingRow; + } + + public void setEditingRow(int column) + { + editingRow = column; + } + + public Component getEditorComponent() + { + return editorComp; + } + + public boolean isEditing() + { + return editorComp != null; + } + + public void setDefaultEditor(Class columnClass, TableCellEditor editor) + { + if (editor != null) + defaultEditorsByColumnClass.put(columnClass, editor); + else + defaultEditorsByColumnClass.remove(columnClass); + } + + public void addColumnSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getColumnCount()-1) + || index1 < 0 || index1 > (getColumnCount()-1))) + throw new IllegalArgumentException("Column index out of range."); + + getColumnModel().getSelectionModel().addSelectionInterval(index0, index1); + } + + public void addRowSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getRowCount()-1) + || index1 < 0 || index1 > (getRowCount()-1))) + throw new IllegalArgumentException("Row index out of range."); + + getSelectionModel().addSelectionInterval(index0, index1); + } + + public void setColumnSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getColumnCount()-1) + || index1 < 0 || index1 > (getColumnCount()-1))) + throw new IllegalArgumentException("Column index out of range."); + + getColumnModel().getSelectionModel().setSelectionInterval(index0, index1); + } + + public void setRowSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getRowCount()-1) + || index1 < 0 || index1 > (getRowCount()-1))) + throw new IllegalArgumentException("Row index out of range."); + + getSelectionModel().setSelectionInterval(index0, index1); + } + + public void removeColumnSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getColumnCount()-1) + || index1 < 0 || index1 > (getColumnCount()-1))) + throw new IllegalArgumentException("Column index out of range."); + + getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1); + } + + public void removeRowSelectionInterval(int index0, int index1) + { + if ((index0 < 0 || index0 > (getRowCount()-1) + || index1 < 0 || index1 > (getRowCount()-1))) + throw new IllegalArgumentException("Row index out of range."); + + getSelectionModel().removeSelectionInterval(index0, index1); + } + + public boolean isColumnSelected(int column) + { + return getColumnModel().getSelectionModel().isSelectedIndex(column); + } + + public boolean isRowSelected(int row) + { + return getSelectionModel().isSelectedIndex(row); + } + + public boolean isCellSelected(int row, int column) + { + return isRowSelected(row) && isColumnSelected(column); + } + + public void selectAll() + { + setColumnSelectionInterval(0, getColumnCount() - 1); + setRowSelectionInterval(0, getRowCount() - 1); + } + + public Object getValueAt(int row, int column) + { + return dataModel.getValueAt(row, convertColumnIndexToModel(column)); + } + + public void setValueAt(Object value, int row, int column) + { + dataModel.setValueAt(value, row, convertColumnIndexToModel(column)); + } + + public TableColumn getColumn(Object identifier) + { + return columnModel.getColumn(columnModel.getColumnIndex(identifier)); + } + + /** + * Returns true if the specified cell is editable, and + * false otherwise. + * + * @param row the row index. + * @param column the column index. + * + * @return A boolean. + */ + public boolean isCellEditable(int row, int column) + { + return dataModel.isCellEditable(row, convertColumnIndexToModel(column)); + } + + /** + * Clears any existing columns from the JTable's + * {@link TableColumnModel} and creates new columns to match the values in + * the data ({@link TableModel}) used by the table. + * + * @see #setAutoCreateColumnsFromModel(boolean) + */ + public void createDefaultColumnsFromModel() + { + // remove existing columns + int columnIndex = columnModel.getColumnCount() - 1; + while (columnIndex >= 0) + { + columnModel.removeColumn(columnModel.getColumn(columnIndex)); + columnIndex--; + } + + // add new columns to match the TableModel + int columnCount = dataModel.getColumnCount(); + for (int c = 0; c < columnCount; c++) + { + TableColumn column = new TableColumn(c); + column.setIdentifier(dataModel.getColumnName(c)); + columnModel.addColumn(column); + } + } + + public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend) + { + if (toggle && extend) + { + // Leave the selection state as is, but move the anchor + // index to the specified location + selectionModel.setAnchorSelectionIndex(rowIndex); + getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex); + } + else if (toggle) + { + // Toggle the state of the specified cell + if (isCellSelected(rowIndex,columnIndex)) + { + selectionModel.removeSelectionInterval(rowIndex,rowIndex); + getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex); + } + else + { + selectionModel.addSelectionInterval(rowIndex,rowIndex); + getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex); + } + } + else if (extend) + { + // Extend the previous selection from the anchor to the + // specified cell, clearing all other selections + selectionModel.setLeadSelectionIndex(rowIndex); + getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex); + } + else + { + // Clear the previous selection and ensure the new cell + // is selected + selectionModel.clearSelection(); + selectionModel.setSelectionInterval(rowIndex,rowIndex); + getColumnModel().getSelectionModel().clearSelection(); + getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex); + + + } + } +} diff --git a/libjava/classpath/javax/swing/JTextArea.java b/libjava/classpath/javax/swing/JTextArea.java new file mode 100644 index 0000000..fb35eb3 --- /dev/null +++ b/libjava/classpath/javax/swing/JTextArea.java @@ -0,0 +1,550 @@ +/* JTextArea.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Rectangle; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.JTextComponent; +import javax.swing.text.PlainDocument; +import javax.swing.text.View; + +/** + * The JTextArea component provides a multi-line area for displaying + * and editing plain text. The component is designed to act as a lightweight + * replacement for the heavyweight java.awt.TextArea component, + * which provides similar functionality using native widgets. + *

+ * + * This component has additional functionality to the AWT class. It follows + * the same design pattern as seen in other text components, such as + * JTextField, JTextPane and JEditorPane, + * and embodied in JTextComponent. These classes separate the text + * (the model) from its appearance within the onscreen component (the view). The + * text is held within a javax.swing.text.Document object, which can + * also maintain relevant style information where necessary. As a result, it is the + * document that should be monitored for textual changes, via + * DocumentEvents delivered to registered + * DocumentListeners, rather than this component. + *

+ * + * Unlike java.awt.TextArea, JTextArea does not + * handle scrolling. Instead, this functionality is delegated to a + * JScrollPane, which can contain the text area and handle + * scrolling when required. Likewise, the word wrapping functionality + * of the AWT component is converted to a property of this component + * and the rows and columns properties + * are used in calculating the preferred size of the scroll pane's + * view port. + * + * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see java.awt.TextArea + * @see javax.swing.JTextComponent + * @see javax.swing.JTextField + * @see javax.swing.JTextPane + * @see javax.swing.JEditorPane + * @see javax.swing.text.Document + * @see javax.swing.text.DocumentEvent + * @see javax.swing.text.DocumentListener + */ + +public class JTextArea extends JTextComponent +{ + /** + * Compatible with Sun's JDK + */ + private static final long serialVersionUID = -6141680179310439825L; + + /** + * The number of rows used by the component. + */ + private int rows; + + /** + * The number of columns used by the component. + */ + private int columns; + + /** + * Whether line wrapping is enabled or not. + */ + private boolean lineWrap; + + /** + * The number of characters equal to a tab within the text. + */ + private int tabSize = 8; + + private boolean wrapStyleWord; + + /** + * Creates a new JTextArea object. + */ + public JTextArea() + { + this(null, null, 0, 0); + } + + /** + * Creates a new JTextArea object. + * + * @param text the initial text + */ + public JTextArea(String text) + { + this(null, text, 0, 0); + } + + /** + * Creates a new JTextArea object. + * + * @param rows the number of rows + * @param columns the number of cols + * + * @exception IllegalArgumentException if rows or columns are negative + */ + public JTextArea(int rows, int columns) + { + this(null, null, rows, columns); + } + + /** + * Creates a new JTextArea object. + * + * @param text the initial text + * @param rows the number of rows + * @param columns the number of cols + * + * @exception IllegalArgumentException if rows or columns are negative + */ + public JTextArea(String text, int rows, int columns) + { + this(null, text, rows, columns); + } + + /** + * Creates a new JTextArea object. + * + * @param the document model to use + */ + public JTextArea(Document doc) + { + this(doc, null, 0, 0); + } + + /** + * Creates a new JTextArea object. + * + * @param the document model to use + * @param text the initial text + * @param rows the number of rows + * @param columns the number of cols + * + * @exception IllegalArgumentException if rows or columns are negative + */ + public JTextArea(Document doc, String text, int rows, int columns) + { + setDocument(doc == null ? createDefaultModel() : doc); + setText(text); + setRows(rows); + setColumns(columns); + } + + /** + * Appends the supplied text to the current contents + * of the document model. + * + * @param toAppend the text to append + */ + public void append(String toAppend) + { + try + { + getDocument().insertString(getText().length(), toAppend, null); + } + catch (BadLocationException exception) + { + /* This shouldn't happen in theory -- but, if it does... */ + throw new RuntimeException("Unexpected exception occurred.", exception); + } + } + + /** + * Creates the default document model. + * + * @return a new default model + */ + protected Document createDefaultModel() + { + return new PlainDocument(); + } + + /** + * Returns true if the width of this component should be forced + * to match the width of a surrounding view port. When line wrapping + * is turned on, this method returns true. + * + * @return true if lines are wrapped. + */ + public boolean getScrollableTracksViewportWidth() + { + return lineWrap ? true : super.getScrollableTracksViewportWidth(); + } + + /** + * Returns the increment that is needed to expose exactly one new line + * of text. This is implemented here to return the values of + * {@link #getRowHeight} and {@link getColumnWidth}, depending on + * the value of the argument direction. + * + * @param visibleRect the view area that is visible in the viewport + * @param orientation either {@link SwingConstants.VERTICAL} or + * {@link SwingConstants.HORIZONTAL} + * @param direction less than zero for up/left scrolling, greater + * than zero for down/right scrolling + * + * @return the increment that is needed to expose exactly one new row + * or column of text + * + * @throws IllegalArgumentException if orientation is invalid + */ + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, + int direction) + { + if (orientation == SwingConstants.VERTICAL) + return getRowHeight(); + else if (orientation == SwingConstants.HORIZONTAL) + return getColumnWidth(); + else + throw new IllegalArgumentException("orientation must be either " + + "javax.swing.SwingConstants.VERTICAL " + + "or " + + "javax.swing.SwingConstants.HORIZONTAL" + ); + } + + /** + * Returns the preferred size of that text component in the case + * it is embedded within a JScrollPane. This uses the column and + * row settings if they are explicitly set, or fall back to + * the superclass's behaviour. + * + * @return the preferred size of that text component in the case + * it is embedded within a JScrollPane + */ + public Dimension getPreferredScrollableViewportSize() + { + if ((rows > 0) && (columns > 0)) + return new Dimension(columns * getColumnWidth(), rows * getRowHeight()); + else + return super.getPreferredScrollableViewportSize(); + } + + /** + * Returns the UI class ID string. + * + * @return the string "TextAreaUI" + */ + public String getUIClassID() + { + return "TextAreaUI"; + } + + /** + * Returns the current number of columns. + * + * @return number of columns + */ + public int getColumns() + { + return columns; + } + + /** + * Sets the number of rows. + * + * @param columns number of columns + * + * @exception IllegalArgumentException if columns is negative + */ + public void setColumns(int columns) + { + if (columns < 0) + throw new IllegalArgumentException(); + + this.columns = columns; + } + + /** + * Returns the current number of rows. + * + * @return number of rows + */ + public int getRows() + { + return rows; + } + + /** + * Sets the number of rows. + * + * @param columns number of columns + * + * @exception IllegalArgumentException if rows is negative + */ + public void setRows(int rows) + { + if (rows < 0) + throw new IllegalArgumentException(); + + this.rows = rows; + } + + /** + * Checks whether line wrapping is enabled. + * + * @return true if line wrapping is enabled, + * false otherwise + */ + public boolean getLineWrap() + { + return lineWrap; + } + + /** + * Enables/disables line wrapping. + * + * @param wrapping true to enable line wrapping, + * false otherwise + */ + public void setLineWrap(boolean flag) + { + if (lineWrap == flag) + return; + + boolean oldValue = lineWrap; + lineWrap = flag; + firePropertyChange("lineWrap", oldValue, lineWrap); + } + + /** + * Checks whether word style wrapping is enabled. + * + * @return true if word style wrapping is enabled, + * false otherwise + */ + public boolean getWrapStyleWord() + { + return wrapStyleWord; + } + + /** + * Enables/Disables word style wrapping. + * + * @param flag true to enable word style wrapping, + * false otherwise + */ + public void setWrapStyleWord(boolean flag) + { + if (wrapStyleWord == flag) + return; + + boolean oldValue = wrapStyleWord; + wrapStyleWord = flag; + firePropertyChange("wrapStyleWord", oldValue, wrapStyleWord); + } + + /** + * Returns the number of characters used for a tab. + * This defaults to 8. + * + * @return the current number of spaces used for a tab. + */ + public int getTabSize() + { + return tabSize; + } + + /** + * Sets the number of characters used for a tab to the + * supplied value. If a change to the tab size property + * occurs (i.e. newSize != tabSize), a property change event + * is fired. + * + * @param newSize The new number of characters to use for a tab. + */ + public void setTabSize(int newSize) + { + if (tabSize == newSize) + return; + + int oldValue = tabSize; + tabSize = newSize; + firePropertyChange("tabSize", oldValue, tabSize); + } + + protected int getColumnWidth() + { + FontMetrics metrics = getToolkit().getFontMetrics(getFont()); + return metrics.charWidth('m'); + } + + public int getLineCount() + { + return getDocument().getDefaultRootElement().getElementCount(); + } + + public int getLineStartOffset(int line) + throws BadLocationException + { + int lineCount = getLineCount(); + + if (line < 0 || line > lineCount) + throw new BadLocationException("Non-existing line number", line); + + Element lineElem = getDocument().getDefaultRootElement().getElement(line); + return lineElem.getStartOffset(); + } + + public int getLineEndOffset(int line) + throws BadLocationException + { + int lineCount = getLineCount(); + + if (line < 0 || line > lineCount) + throw new BadLocationException("Non-existing line number", line); + + Element lineElem = getDocument().getDefaultRootElement().getElement(line); + return lineElem.getEndOffset(); + } + + public int getLineOfOffset(int offset) + throws BadLocationException + { + Document doc = getDocument(); + + if (offset < doc.getStartPosition().getOffset() + || offset >= doc.getEndPosition().getOffset()) + throw new BadLocationException("offset outside of document", offset); + + return doc.getDefaultRootElement().getElementIndex(offset); + } + + protected int getRowHeight() + { + FontMetrics metrics = getToolkit().getFontMetrics(getFont()); + return metrics.getHeight(); + } + + /** + * Inserts the supplied text at the specified position. Nothing + * happens in the case that the model or the supplied string is null + * or of zero length. + * + * @param string The string of text to insert. + * @param position The position at which to insert the supplied text. + * @throws IllegalArgumentException if the position is < 0 or greater + * than the length of the current text. + */ + public void insert(String string, int position) + { + // Retrieve the document model. + Document doc = getDocument(); + + // Check the model and string for validity. + if (doc == null + || string == null + || string.length() == 0) + return; + + // Insert the text into the model. + try + { + doc.insertString(position, string, null); + } + catch (BadLocationException e) + { + throw new IllegalArgumentException("The supplied position, " + + position + ", was invalid."); + } + } + + public void replaceRange(String text, int start, int end) + { + Document doc = getDocument(); + + if (start > end + || start < doc.getStartPosition().getOffset() + || end >= doc.getEndPosition().getOffset()) + throw new IllegalArgumentException(); + + try + { + doc.remove(start, end - start); + doc.insertString(start, text, null); + } + catch (BadLocationException e) + { + // This cannot happen as we check offset above. + } + } + + /** + * Returns the preferred size for the JTextArea. This is the maximum of + * the size that is needed to display the content and the requested size + * as per {@link #getColumns} and {@link #getRows}. + * + * @return the preferred size of the JTextArea + */ + public Dimension getPreferredSize() + { + int reqWidth = getColumns() * getColumnWidth(); + int reqHeight = getRows() * getRowHeight(); + View view = getUI().getRootView(this); + int neededWidth = (int) view.getPreferredSpan(View.HORIZONTAL); + int neededHeight = (int) view.getPreferredSpan(View.VERTICAL); + return new Dimension(Math.max(reqWidth, neededWidth), + Math.max(reqHeight, neededHeight)); + } +} diff --git a/libjava/classpath/javax/swing/JTextField.java b/libjava/classpath/javax/swing/JTextField.java new file mode 100644 index 0000000..7d8407f --- /dev/null +++ b/libjava/classpath/javax/swing/JTextField.java @@ -0,0 +1,441 @@ +/* JTextField.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +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; +import javax.swing.text.TextAction; + +public class JTextField extends JTextComponent + implements SwingConstants +{ + /** + * AccessibleJTextField + */ + protected class AccessibleJTextField extends AccessibleJTextComponent + { + private static final long serialVersionUID = 8255147276740453036L; + + /** + * Constructor AccessibleJTextField + */ + protected AccessibleJTextField() + { + } + + /** + * getAccessibleStateSet + * @return AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + } + + private static final long serialVersionUID = 353853209832607592L; + + private static final Action[] actions; + + /** + * Name of the action that gets sent when the content of the text field + * gets accepted. + */ + public static final String notifyAction = "notify-field-accept"; + + static + { + actions = new Action[1]; + actions[0] = new TextAction(notifyAction) + { + public void actionPerformed(ActionEvent event) + { + JTextField textField = (JTextField) event.getSource(); + textField.fireActionPerformed(); + } + }; + } + + private int columns; + private int align; + private int scrollOffset; + + /** @since 1.3 */ + private Action action; + + /** @since 1.3 */ + private String actionCommand; + + private PropertyChangeListener actionPropertyChangeListener; + + /** + * Creates a new instance of JTextField. + */ + public JTextField() + { + this(null, null, 0); + } + + /** + * Creates a new instance of JTextField. + * + * @param text the initial text + */ + public JTextField(String text) + { + this(null, text, 0); + } + + /** + * Creates a new instance of JTextField. + * + * @param columns the number of columns + * + * @exception IllegalArgumentException if columns %lt; 0 + */ + public JTextField(int columns) + { + this(null, null, columns); + } + + /** + * Creates a new instance of JTextField. + * + * @param text the initial text + * @param columns the number of columns + * + * @exception IllegalArgumentException if columns %lt; 0 + */ + public JTextField(String text, int columns) + { + this(null, text, columns); + } + + /** + * Creates a new instance of JTextField. + * + * @param doc the document to use + * @param text the initial text + * @param columns the number of columns + * + * @exception IllegalArgumentException if columns %lt; 0 + */ + public JTextField(Document doc, String text, int columns) + { + if (columns < 0) + throw new IllegalArgumentException(); + + this.columns = columns; + + setDocument(doc == null ? createDefaultModel() : doc); + + if (text != null) + setText(text); + + // default value for alignment + align = LEADING; + } + + /** + * Creates the default model for this text field. + * This implementation returns an instance of PlainDocument. + * + * @return a new instance of the default model + */ + protected Document createDefaultModel() + { + // subclassed to swallow newlines + return new PlainDocument() { + public void insertString(int offset, String str, AttributeSet a) + throws BadLocationException + { + if (str.indexOf('\n') == -1) + super.insertString(offset, str, a); + } + }; + } + + /** + * Returns the class ID for the UI. + * + * @return "TextFieldUI"; + */ + public String getUIClassID() + { + return "TextFieldUI"; + } + + /** + * Adds a new listener object to this text field. + * + * @param listener the listener to add + */ + public void addActionListener(ActionListener listener) + { + listenerList.add(ActionListener.class, listener); + } + + /** + * Removes a listener object from this text field. + * + * @param listener the listener to remove + */ + public void removeActionListener(ActionListener listener) + { + listenerList.remove(ActionListener.class, listener); + } + + /** + * Returns all registered ActionListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) getListeners(ActionListener.class); + } + + /** + * Sends an action event to all registered + * ActionListener objects. + */ + protected void fireActionPerformed() + { + ActionEvent event = new ActionEvent(this, 0, notifyAction); + ActionListener[] listeners = getActionListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].actionPerformed(event); + } + + /** + * Returns the number of columns of this text field. + * + * @return the number of columns + */ + public int getColumns() + { + return columns; + } + + public void setColumns(int columns) + { + if (columns < 0) + throw new IllegalArgumentException(); + + this.columns = columns; + invalidate(); + repaint(); + } + + public int getHorizontalAlignment() + { + return align; + } + + public void setHorizontalAlignment(int newAlign) + { + if (align == newAlign) + return; + + int oldAlign = align; + align = newAlign; + firePropertyChange("horizontalAlignment", oldAlign, newAlign); + invalidate(); + repaint(); + } + + public void setFont(Font newFont) + { + super.setFont(newFont); + revalidate(); + } + + public Dimension getPreferredSize() + { + Dimension size = super.getPreferredSize(); + + if (columns != 0) + size.width = columns * getColumnWidth(); + + return size; + } + + /** + * Returns the scroll offset in pixels. + * + * @return the scroll offset + */ + public int getScrollOffset() + { + return scrollOffset; + } + + /** + * Sets the scroll offset in pixels. + * + * @param offset the scroll offset + */ + public void setScrollOffset(int offset) + { + scrollOffset = offset; + } + + public Action[] getActions() + { + return TextAction.augmentList(super.getActions(), actions); + } + + public void postActionEvent() + { + String command = actionCommand != null ? actionCommand : getText(); + ActionEvent event = new ActionEvent(this, 0, command); + ActionListener[] listeners = getActionListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].actionPerformed(event); + } + + /** + * @since 1.3 + */ + public Action getAction() + { + return action; + } + + /** + * @since 1.3 + */ + public void setAction(Action newAction) + { + if (action == newAction) + return; + + if (action != null) + { + removeActionListener(action); + action.removePropertyChangeListener(actionPropertyChangeListener); + actionPropertyChangeListener = null; + } + + Action oldAction = action; + action = newAction; + + if (action != null) + { + addActionListener(action); + actionPropertyChangeListener = + createActionPropertyChangeListener(action); + action.addPropertyChangeListener(actionPropertyChangeListener); + } + + firePropertyChange("horizontalAlignment", oldAction, newAction); + } + + /** + * @since 1.3 + */ + public void setActionCommand(String command) + { + actionCommand = command; + } + + /** + * @since 1.3 + */ + protected PropertyChangeListener createActionPropertyChangeListener(Action action) + { + return new PropertyChangeListener() + { + 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()); + } + } + }; + } + + /** + * @since 1.3 + */ + protected void configurePropertiesFromAction(Action action) + { + if (action != null) + { + setEnabled(action.isEnabled()); + setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION)); + } + else + { + setEnabled(true); + setToolTipText(null); + } + } + + protected int getColumnWidth() + { + FontMetrics metrics = getToolkit().getFontMetrics(getFont()); + return metrics.charWidth('m'); + } +} diff --git a/libjava/classpath/javax/swing/JTextPane.java b/libjava/classpath/javax/swing/JTextPane.java new file mode 100644 index 0000000..5321812 --- /dev/null +++ b/libjava/classpath/javax/swing/JTextPane.java @@ -0,0 +1,270 @@ +/* JTextPane.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.io.IOException; +import java.io.ObjectOutputStream; + +import javax.swing.text.AttributeSet; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.Style; +import javax.swing.text.StyledDocument; +import javax.swing.text.StyledEditorKit; + +/** + * JTextPane + * @author Andrew Selkirk + * @version 1.0 + */ +public class JTextPane extends JEditorPane { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * uiClassID + */ + private static final String uiClassID = "TextPaneUI"; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor JTextPane + */ + public JTextPane() { + // TODO + } // JTextPane() + + /** + * Constructor JTextPane + * @param document TODO + */ + public JTextPane(StyledDocument document) { + // TODO + } // JTextPane() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getUIClassID + * @returns String + */ + public String getUIClassID() { + return uiClassID; + } // getUIClassID() + + /** + * setDocument + * @param document TODO + */ + public void setDocument(Document document) { + super.setDocument(document); // TODO + } // setDocument() + + /** + * getStyledDocument + * @returns StyledDocument + */ + public StyledDocument getStyledDocument() { + return null; // TODO + } // getStyledDocument() + + /** + * setStyledDocument + * @param document TODO + */ + public void setStyledDocument(StyledDocument document) { + // TODO + } // setStyledDocument() + + /** + * replaceSelection + * @param content TODO + */ + public void replaceSelection(String content) { + super.replaceSelection(content); // TODO + } // replaceSelection() + + /** + * insertComponent + * @param component TODO + */ + public void insertComponent(Component component) { + // TODO + } // insertComponent() + + /** + * insertIcon + * @param icon TODO + */ + public void insertIcon(Icon icon) { + // TODO + } // insertIcon() + + /** + * addStyle + * @param nm TODO + * @param parent TODO + * @returns Style + */ + public Style addStyle(String nm, Style parent) { + return null; // TODO + } // addStyle() + + /** + * removeStyle + * @param nm TODO + */ + public void removeStyle(String nm) { + // TODO + } // removeStyle() + + /** + * getStyle + * @param nm TODO + * @returns Style + */ + public Style getStyle(String nm) { + return null; // TODO + } // getStyle() + + /** + * getLogicalStyle + * @returns Style + */ + public Style getLogicalStyle() { + return null; // TODO + } // getLogicalStyle() + + /** + * setLogicalStyle + * @param style TODO + */ + public void setLogicalStyle(Style style) { + // TODO + } // setLogicalStyle() + + /** + * getCharacterAttributes + * @returns AttributeSet + */ + public AttributeSet getCharacterAttributes() { + return null; // TODO + } // getCharacterAttributes() + + /** + * setCharacterAttributes + * @param attribute TODO + * @param replace TODO + */ + public void setCharacterAttributes(AttributeSet attribute, + boolean replace) { + // TODO + } // setCharacterAttributes() + + /** + * getParagraphAttributes + * @returns AttributeSet + */ + public AttributeSet getParagraphAttributes() { + return null; // TODO + } // getParagraphAttributes() + + /** + * setParagraphAttributes + * @param attribute TODO + * @param replace TODO + */ + public void setParagraphAttributes(AttributeSet attribute, + boolean replace) { + // TODO + } // setParagraphAttributes() + + /** + * getInputAttributes + * @returns MutableAttributeSet + */ + public MutableAttributeSet getInputAttributes() { + return null; // TODO + } // getInputAttributes() + + /** + * getStyledEditorKit + * @returns StyledEditorKit + */ + protected final StyledEditorKit getStyledEditorKit() { + return null; // TODO + } // getStyledEditorKit() + + /** + * createDefaultEditorKit + * @returns EditorKit + */ + protected EditorKit createDefaultEditorKit() { + return super.createDefaultEditorKit(); // TODO + } // createDefaultEditorKit() + + /** + * setEditorKit + * @param editor TODO + */ + public final void setEditorKit(EditorKit editor) { + super.setEditorKit(editor); // TODO + } // setEditorKit() + + /** + * paramString + * @returns String + */ + protected String paramString() { + return super.paramString(); // TODO + } // paramString() + + +} // JTextPane diff --git a/libjava/classpath/javax/swing/JToggleButton.java b/libjava/classpath/javax/swing/JToggleButton.java new file mode 100644 index 0000000..0e1b9e6 --- /dev/null +++ b/libjava/classpath/javax/swing/JToggleButton.java @@ -0,0 +1,323 @@ +/* JToggleButton.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.swing.plaf.ButtonUI; + +/** + * The JToggleButton component provides a stateful button, + * which can be either selected or unselected. This provides the basis + * for the implementations of radio buttons (JRadioButton) + * and check boxes (JCheckBox). + * + * @author Michael Koch (konqueror@gmx.de) + * @author Graydon Hoare (graydon@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see JRadioButton + * @see JCheckBox + * @since 1.2 + */ +public class JToggleButton extends AbstractButton implements Accessible +{ + /** + * This class provides accessibility support for the toggle button. + */ + protected class AccessibleJToggleButton + extends AccessibleAbstractButton + implements ItemListener + { + private static final long serialVersionUID = -8652952712161229225L; + + /** + * Constructor for the accessible toggle button. + */ + public AccessibleJToggleButton() + { + super(); + /* Register the accessible toggle button as a listener for item events */ + addItemListener(this); + } + + /** + * Returns the accessible role for the toggle button. + * + * @return An instance of AccessibleRole, describing + * the role of the toggle button. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.TOGGLE_BUTTON; + } + + /** + * Monitors the toggle button for state changes and fires accessible + * property change events when they occur. + * + * @param event the event that occurred. + */ + public void itemStateChanged(ItemEvent event) + { + /* Fire a state property change event as the button's state has changed */ + if (event.getStateChange() == ItemEvent.SELECTED) + { + /* State has changed from unselected (null) to selected */ + firePropertyChange(ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.SELECTED); + } + else + { + /* State has changed from selected to unselected (null) */ + firePropertyChange(ACCESSIBLE_STATE_PROPERTY, AccessibleState.ENABLED, null); + } + } + + } + + /** + * The model handles the storage and maintenance of the state of + * the toggle button. This follows the same paradigm (the MVC + * or Model-View-Controller design pattern) employed by + * other Swing components, where the data associated with a component + * is stored separately from the display aspects. + */ + public static class ToggleButtonModel extends DefaultButtonModel + { + /** + * 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. + * + * @param b true if the button is pressed down. + */ + public void setPressed(boolean p) + { + // cannot change PRESSED state unless button is enabled + if (! isEnabled()) + return; + + // if this call does not represent a CHANGE in state, then return + if ((p && isPressed()) || (!p && !isPressed())) + return; + + // make the change + if (p) + stateMask = stateMask | PRESSED; + else + stateMask = stateMask & (~PRESSED); + + // notify interested ChangeListeners + fireStateChanged(); + + // setPressed(false) == mouse release on us, + // if we were armed, we flip the selected state. + if (!p && isArmed()) + { + fireActionPerformed(new ActionEvent(this, + ActionEvent.ACTION_PERFORMED, + actionCommand)); + setSelected(! isSelected()); + } + } + } + + /** + * Compatible with Sun's JDK. + */ + private static final long serialVersionUID = -3128248873429850443L; + + /** + * Constructs an unselected toggle button with no text or icon. + */ + public JToggleButton() + { + this(null, null, false); + } + + /** + * Constructs a toggle button using the labelling, state + * and icon specified by the supplied action. + * + * @param a the action to use to define the properties of the button. + */ + public JToggleButton(Action a) + { + this(); + setAction(a); + } + + /** + * Constructs an unselected toggle button with the supplied icon + * and no text. + * + * @param icon the icon to use. + */ + public JToggleButton(Icon icon) + { + this(null, icon, false); + } + + /** + * Constructs a toggle button with the supplied icon and state. + * + * @param icon the icon to use. + * @param selected if true, the toggle button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JToggleButton(Icon icon, boolean selected) + { + this(null, icon, selected); + } + + /** + * Constructs an unselected toggle button using the supplied text + * and no icon. + * + * @param text the text to use. + */ + public JToggleButton(String text) + { + this(text, null, false); + } + + /** + * Constructs a toggle button with the supplied text and state. + * + * @param text the text to use. + * @param selected if true, the toggle button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JToggleButton(String text, boolean selected) + { + this(text, null, selected); + } + + /** + * Constructs an unselected toggle button with the supplied text + * and icon. + * + * @param text the text to use. + * @param icon the icon to use. + */ + public JToggleButton(String text, Icon icon) + { + this(text, icon, false); + } + + /** + * Constructs a toggle button with the supplied text, icon and state. + * + * @param text the text to use. + * @param icon the icon to use. + * @param selected if true, the toggle button is initially in the + * selected state. Otherwise, the button is unselected. + */ + public JToggleButton (String text, Icon icon, boolean selected) + { + super(); + init(text, icon); + + setModel(new ToggleButtonModel()); + model.setSelected(selected); + } + + /** + * Gets the AccessibleContext associated with this JToggleButton. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + { + /* Create the context */ + accessibleContext = new AccessibleJToggleButton(); + } + return accessibleContext; + } + + /** + * Returns a string that specifies the name of the Look and Feel + * class that renders this component. + * + * @return The Look and Feel UI class in String form. + */ + public String getUIClassID() + { + return "ToggleButtonUI"; + } + + /** + * Returns a textual representation of this component for debugging. + * Users should not depend on anything as regards the content or formatting + * of this string, except for the fact that the returned string may never be + * null (only empty). + * + * @return the component in String form for debugging. + */ + protected String paramString() + { + return super.paramString(); + } + + /** + * This method resets the toggle button's UI delegate to the default UI for + * the current look and feel. + */ + public void updateUI() + { + setUI((ButtonUI)UIManager.getUI(this)); + } + +} + + + diff --git a/libjava/classpath/javax/swing/JToolBar.java b/libjava/classpath/javax/swing/JToolBar.java new file mode 100644 index 0000000..649919e --- /dev/null +++ b/libjava/classpath/javax/swing/JToolBar.java @@ -0,0 +1,779 @@ +/* JToolBar.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +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.beans.PropertyChangeListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.swing.JButton; +import javax.swing.plaf.ToolBarUI; + +/** + * JToolBar is a component that provides a toolbar to Swing programs. Users + * can add buttons (or actions that will be represented by JButtons) as well + * as other components to the JToolBar. JToolBars can be dragged in and out + * of their parent components. If the JToolBar is dragged out of the parent, + * then it will be displayed in its own RootPaneContainer. For dragging to + * work properly, JToolBars need to be placed in a Container that has a + * BorderLayout. That parent Container cannot have components in the NORTH, + * EAST, SOUTH, or WEST components (that is not the JToolBar). + */ +public class JToolBar extends JComponent implements SwingConstants, Accessible +{ + /** + * AccessibleJToolBar + */ + protected class AccessibleJToolBar extends AccessibleJComponent + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = -5516888265903814215L; + + /** + * Constructor AccessibleJToolBar + */ + protected AccessibleJToolBar() + { + } + + /** + * getAccessibleStateSet + * + * @return AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; // TODO + } + + /** + * getAccessibleRole + * + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.TOOL_BAR; + } + } + + /** + * This is the private JToolBar layout manager. + */ + private class DefaultToolBarLayout implements LayoutManager + { + /** + * This method is called when a new component is added to the container. + * + * @param name The name of the component added. + * @param comp The component that was added. + */ + public void addLayoutComponent(String name, Component comp) + { + // Do nothing. + } + + /** + * This method is called to lay out the given container to position and + * size the child components. + * + * @param c The container to lay out. + * + * @throws Error DOCUMENT ME! + */ + public void layoutContainer(Container c) + { + if (! (c instanceof JToolBar)) + throw new Error("DefaultToolBarLayout can only be used on JToolBars."); + Insets insets = getInsets(); + Insets margin = getMargin(); + int middle; + if (margin != null) + { + insets.left += margin.left; + insets.top += margin.top; + insets.bottom += margin.bottom; + insets.right += margin.right; + } + Component[] components = c.getComponents(); + Dimension tdims = c.getSize(); + int start = 0; + Dimension pref; + + if (getOrientation() == SwingUtilities.HORIZONTAL) + { + start += insets.left; + for (int i = 0; i < components.length; i++) + { + if (components[i] != null && components[i].isVisible()) + { + pref = components[i].getPreferredSize(); + if (pref != null) + { + middle = (tdims.height - pref.height) / 2; + components[i].setBounds(start, middle, pref.width, + pref.height); + start += pref.width; + } + } + } + } + else + { + start += insets.top; + for (int i = 0; i < components.length; i++) + { + if (components[i] != null && components[i].isVisible()) + { + pref = components[i].getPreferredSize(); + if (pref != null) + { + middle = (tdims.width - pref.width) / 2; + components[i].setBounds(middle, start, pref.width, + pref.height); + start += pref.height; + } + } + } + } + } + + /** + * This method returns the minimum size of the given container given the + * child components. + * + * @param parent The container to measure. + * + * @return The minimum size of the given container. + */ + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + /** + * This method returns the preferred size of the given container given the + * child components. + * + * @param parent The container to measure. + * + * @return The preferred size of the given container. + */ + public Dimension preferredLayoutSize(Container parent) + { + int orientation = getOrientation(); + Component[] components = getComponents(); + + int limit = 0; + int total = 0; + Dimension dims; + + int w = 0; + int h = 0; + + if (orientation == SwingConstants.HORIZONTAL) + { + for (int i = 0; i < components.length; i++) + { + dims = components[i].getPreferredSize(); + if (dims != null) + { + if (dims.height > limit) + limit = dims.height; + total += dims.width; + } + } + w = total; + h = limit; + } + else + { + for (int i = 0; i < components.length; i++) + { + dims = components[i].getPreferredSize(); + if (dims != null) + { + if (dims.width > limit) + limit = dims.width; + total += dims.height; + } + } + w = limit; + h = total; + } + + Insets insets = getInsets(); + w += insets.left + insets.right; + h += insets.top + insets.bottom; + + Insets margin = getMargin(); + if (margin != null) + { + w += margin.left + margin.right; + h += margin.top + margin.bottom; + } + + return new Dimension(w, h); + } + + /** + * This method is called when the given component is removed from the + * container. + * + * @param comp The component removed. + */ + public void removeLayoutComponent(Component comp) + { + // Do nothing. + } + } + + /** + * This is an extension of JSeparator used in toolbars. Unlike JSeparator, + * nothing is painted for this Separator, it is only blank space that + * separates components. + */ + public static class Separator extends JSeparator + { + /** DOCUMENT ME! */ + private static final long serialVersionUID = -1656745644823105219L; + + /** + * Creates a new Separator object. + */ + public Separator() + { + super(); + } // Separator() + + /** + * Creates a new Separator object with the given size. + * + * @param size The size of the separator. + */ + public Separator(Dimension size) + { + setPreferredSize(size); + } // Separator() + + /** + * This method returns the String ID of the UI class of Separator. + * + * @return The UI class' String ID. + */ + public String getUIClassID() + { + return "ToolBarSeparatorUI"; + } // getUIClassID() + + /** + * This method returns the preferred size of the Separator. + * + * @return The preferred size of the Separator. + */ + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } // getPreferredSize() + + /** + * This method returns the maximum size of the Separator. + * + * @return The maximum size of the Separator. + */ + public Dimension getMaximumSize() + { + return super.getPreferredSize(); + } // getMaximumSize() + + /** + * This method returns the minimum size of the Separator. + * + * @return The minimum size of the Separator. + */ + public Dimension getMinimumSize() + { + return super.getPreferredSize(); + } // getMinimumSize() + + /** + * This method returns the size of the Separator. + * + * @return The size of the Separator. + */ + public Dimension getSeparatorSize() + { + return super.getPreferredSize(); + } // getSeparatorSize() + + /** + * This method sets the size of the Separator. + * + * @param size The new size of the Separator. + */ + public void setSeparatorSize(Dimension size) + { + setPreferredSize(size); + } // setSeparatorSize() + } // Separator + + /** DOCUMENT ME! */ + private static final long serialVersionUID = -1269915519555129643L; + + /** Whether the JToolBar paints its border. */ + private transient boolean paintBorder = true; + + /** The extra insets around the JToolBar. */ + private transient Insets margin; + + /** Whether the JToolBar can float (and be dragged around). */ + private transient boolean floatable = true; + + /** Whether the buttons will have rollover borders. */ + private transient boolean rollover; + + /** The orientation of the JToolBar. */ + private int orientation = HORIZONTAL; + + /** + * This method creates a new JToolBar object with horizontal orientation + * and no name. + */ + public JToolBar() + { + this(null, HORIZONTAL); + } // JToolBar() + + /** + * This method creates a new JToolBar with the given orientation and no + * name. + * + * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) + */ + public JToolBar(int orientation) + { + this(null, orientation); + } // JToolBar() + + /** + * This method creates a new JToolBar object with the given name and + * horizontal orientation. + * + * @param name Name assigned to undocked tool bar. + */ + public JToolBar(String name) + { + this(name, HORIZONTAL); + } // JToolBar() + + /** + * This method creates a new JToolBar object with the given name and + * orientation. + * + * @param name Name assigned to undocked tool bar. + * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) + */ + public JToolBar(String name, int orientation) + { + setName(name); + setOrientation(orientation); + setLayout(new DefaultToolBarLayout()); + revalidate(); + updateUI(); + } // JToolBar() + + /** + * This method adds a new JButton that performs the given Action to the + * JToolBar. + * + * @param action The Action to add to the JToolBar. + * + * @return The JButton that wraps the Action. + */ + public JButton add(Action action) + { + JButton b = createActionComponent(action); + add(b); + return b; + } // add() + + /** + * This method paints the border if the borderPainted property is true. + * + * @param graphics The graphics object to paint with. + */ + protected void paintBorder(Graphics graphics) + { + if (paintBorder && isFloatable()) + super.paintBorder(graphics); + } // paintBorder() + + /** + * This method returns the UI class used to paint this JToolBar. + * + * @return The UI class for this JToolBar. + */ + public ToolBarUI getUI() + { + return (ToolBarUI) ui; + } // getUI() + + /** + * This method sets the UI used with the JToolBar. + * + * @param ui The UI used with the JToolBar. + */ + public void setUI(ToolBarUI ui) + { + super.setUI(ui); + } // setUI() + + /** + * This method resets the UI used to the Look and Feel defaults. + */ + public void updateUI() + { + setUI((ToolBarUI) UIManager.getUI(this)); + revalidate(); + repaint(); + } // updateUI() + + /** + * This method returns the String identifier for the UI class to the used + * with the JToolBar. + * + * @return The String identifier for the UI class. + */ + public String getUIClassID() + { + return "ToolBarUI"; + } // getUIClassID() + + /** + * This method sets the rollover property for the JToolBar. In rollover + * mode, JButtons inside the JToolBar will only display their borders when + * the mouse is moving over them. + * + * @param b The new rollover property. + */ + public void setRollover(boolean b) + { + if (b != rollover) + { + rollover = b; + firePropertyChange("rollover", ! rollover, rollover); + revalidate(); + repaint(); + } + } + + /** + * This method returns the rollover property. + * + * @return The rollover property. + */ + public boolean isRollover() + { + return rollover; + } + + /** + * This method returns the index of the given component. + * + * @param component The component to find. + * + * @return The index of the given component. + */ + public int getComponentIndex(Component component) + { + Component[] components = getComponents(); + if (components == null) + return -1; + + for (int i = 0; i < components.length; i++) + if (components[i] == component) + return i; + + return -1; + } // getComponentIndex() + + /** + * This method returns the component at the given index. + * + * @param index The index of the component. + * + * @return The component at the given index. + */ + public Component getComponentAtIndex(int index) + { + return getComponent(index); + } // getComponentAtIndex() + + /** + * This method returns the margin property. + * + * @return The margin property. + */ + public Insets getMargin() + { + return margin; + } // getMargin() + + /** + * This method sets the margin property. The margin property determines the + * extra space between the children components of the JToolBar and the + * border. + * + * @param margin The margin property. + */ + public void setMargin(Insets margin) + { + if ((this.margin != null && margin == null) + || (this.margin == null && margin != null) + || (margin != null && this.margin != null + && (margin.left != this.margin.left + || margin.right != this.margin.right || margin.top != this.margin.top + || margin.bottom != this.margin.bottom))) + { + Insets oldMargin = this.margin; + this.margin = margin; + firePropertyChange("margin", oldMargin, this.margin); + revalidate(); + repaint(); + } + } // setMargin() + + /** + * This method returns the borderPainted property. + * + * @return The borderPainted property. + */ + public boolean isBorderPainted() + { + return paintBorder; + } // isBorderPainted() + + /** + * This method sets the borderPainted property. If set to false, the border + * will not be painted. + * + * @param painted Whether the border will be painted. + */ + public void setBorderPainted(boolean painted) + { + if (painted != paintBorder) + { + paintBorder = painted; + firePropertyChange("borderPainted", ! paintBorder, + paintBorder); + repaint(); + } + } // setBorderPainted() + + /** + * This method returns the floatable property. + * + * @return The floatable property. + */ + public boolean isFloatable() + { + return floatable; + } // isFloatable() + + /** + * This method sets the floatable property. If set to false, the JToolBar + * cannot be dragged. + * + * @param floatable Whether the JToolBar can be dragged. + */ + public void setFloatable(boolean floatable) + { + if (floatable != this.floatable) + { + this.floatable = floatable; + firePropertyChange("floatable", ! floatable, floatable); + } + } // setFloatable() + + /** + * This method returns the orientation of the JToolBar. + * + * @return The orientation of the JToolBar. + */ + public int getOrientation() + { + return orientation; + } // getOrientation() + + /** + * This method sets the layout manager to be used with the JToolBar. + * + * @param mgr The Layout Manager used with the JToolBar. + */ + public void setLayout(LayoutManager mgr) + { + super.setLayout(mgr); + revalidate(); + repaint(); + } // setLayout() + + /** + * This method sets the orientation property for JToolBar. + * + * @param orientation The new orientation for JToolBar. + * + * @throws IllegalArgumentException If the orientation is not HORIZONTAL or + * VERTICAL. + */ + public void setOrientation(int orientation) + { + if (orientation != HORIZONTAL && orientation != VERTICAL) + throw new IllegalArgumentException(orientation + + " is not a legal orientation"); + if (orientation != this.orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange("orientation", oldOrientation, this.orientation); + revalidate(); + repaint(); + } + } // setOrientation() + + /** + * This method adds a Separator of default size to the JToolBar. + */ + public void addSeparator() + { + add(new Separator()); + } // addSeparator() + + /** + * This method adds a Separator with the given size to the JToolBar. + * + * @param size The size of the Separator. + */ + public void addSeparator(Dimension size) + { + add(new Separator(size)); + } // addSeparator() + + /** + * This method is used to create JButtons which can be added to the JToolBar + * for the given action. + * + * @param action The action to create a JButton for. + * + * @return The JButton created from the action. + */ + protected JButton createActionComponent(Action action) + { + return new JButton(action); + } // createActionComponent() + + /** + * This method creates a pre-configured PropertyChangeListener which updates + * the control as changes are made to the Action. However, this is no + * longer the recommended way of adding Actions to Containers. As such, + * this method returns null. + * + * @param button The JButton to configure a PropertyChangeListener for. + * + * @return null. + */ + protected PropertyChangeListener createActionChangeListener(JButton button) + { + // XXX: As specified, this returns null. But seems kind of strange, usually deprecated methods don't just return null, verify! + return null; + } // createActionChangeListener() + + /** + * This method overrides Container's addImpl method. If a JButton is added, + * it is disabled. + * + * @param component The Component to add. + * @param constraints The Constraints placed on the component. + * @param index The index to place the Component at. + */ + protected void addImpl(Component component, Object constraints, int index) + { + // XXX: Sun says disable button but test cases show otherwise. + super.addImpl(component, constraints, index); + + // if we added a Swing Button then adjust this a little + if (component instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) component; + b.setRolloverEnabled(rollover); + b.updateUI(); + } + + } // addImpl() + + /** + * This method returns a String description of the JToolBar. + * + * @return A String description of the JToolBar. + */ + protected String paramString() + { + return "JToolBar"; + } // paramString() + + /** + * getAccessibleContext + * + * @return AccessibleContext + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJToolBar(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/javax/swing/JToolTip.java b/libjava/classpath/javax/swing/JToolTip.java new file mode 100644 index 0000000..8d77478 --- /dev/null +++ b/libjava/classpath/javax/swing/JToolTip.java @@ -0,0 +1,197 @@ +/* JToolTip.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTEvent; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.plaf.ToolTipUI; + +/** + * This class is used to display ToolTips. ToolTips are small floating windows + * that display text when the mouse comes to rest over a Component. ToolTips + * are set for JComponents using JComponent.setToolTipText(String). + */ +public class JToolTip extends JComponent implements Accessible +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -1138929898906751643L; + + /** + * DOCUMENT ME! + */ + protected class AccessibleJToolTip extends AccessibleJComponent + { + private static final long serialVersionUID = -6222548177795408476L; + + /** + * Creates a new AccessibleJToolTip object. + */ + protected AccessibleJToolTip() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getAccessibleDescription() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + } + + /** The text to display in the JToolTip. */ + String text; + + /** The JComponent this JToolTip is used for. */ + JComponent component; + + /** + * Creates a new JToolTip object. + */ + public JToolTip() + { + disableEvents(AWTEvent.MOUSE_EVENT_MASK); + updateUI(); + } + + /** + * This method returns the text this JToolTip displays. + * + * @return The text that this JToolTip displays. + */ + public String getTipText() + { + return text; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * This method returns the JComponent this JToolTip displays for. + * + * @return The JComponent this JToolTip displays for. + */ + public JComponent getComponent() + { + return component; + } + + /** + * This method returns the UI responsible for displaying this JToolTip. + * + * @return The UI responsible for displaying this JToolTip. + */ + public ToolTipUI getUI() + { + return (ToolTipUI) ui; + } + + /** + * This method returns the String identifier for the UI class. + * + * @return The String identifier for the UI class. + */ + public String getUIClassID() + { + return "ToolTipUI"; + } + + /** + * This method returns a debugging String describing the JToolTip. + * + * @return A debugging String describing the JToolTip. + */ + protected String paramString() + { + return "JToolTip"; + } + + /** + * This method sets the JComponent that the JToolTip displays for. + * + * @param c The JComponent that the JToolTip displays for. + */ + public void setComponent(JComponent c) + { + component = c; + } + + /** + * This method sets the text that the JToolTip displays. + * + * @param tipText The text that the JToolTip displays. + */ + public void setTipText(String tipText) + { + text = tipText; + } + + /** + * This method resets the UI used to the Look and Feel default. + */ + public void updateUI() + { + setUI((ToolTipUI) UIManager.getUI(this)); + revalidate(); + repaint(); + } +} diff --git a/libjava/classpath/javax/swing/JTree.java b/libjava/classpath/javax/swing/JTree.java new file mode 100644 index 0000000..bccd983 --- /dev/null +++ b/libjava/classpath/javax/swing/JTree.java @@ -0,0 +1,1829 @@ +/* JTree.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Dimension; +import java.awt.Rectangle; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +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; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +public class JTree + extends JComponent + implements Scrollable, Accessible +{ + /** + * Listens to the model of the JTree and updates the property + * expandedState 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. + */ + 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"; + + /** @since 1.3 */ + public static final String ANCHOR_SELECTION_PATH_PROPERTY = "anchorSelectionPath"; + + /** @since 1.3 */ + public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath"; + + /** @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; + + /** + * Redirects TreeSelectionEvents so that the source is this JTree. + */ + protected TreeSelectionRedirector selectionRedirector = + new TreeSelectionRedirector(); + + /** + * Creates a new JTree object. + */ + public JTree() + { + this(createTreeModel(null)); + } + + /** + * Creates a new JTree object. + * + * @param value the initial nodes in the tree + */ + public JTree(Hashtable value) + { + this(createTreeModel(value)); + } + + /** + * Creates a new JTree object. + * + * @param value the initial nodes in the tree + */ + public JTree(Object[] value) + { + this(createTreeModel(value)); + } + + /** + * Creates a new JTree object. + * + * @param model the model to use + */ + public JTree(TreeModel model) + { + setModel(model); + setSelectionModel(EmptySelectionModel.sharedInstance()); + selectionModel.addTreeSelectionListener(selectionRedirector); + setCellRenderer(new DefaultTreeCellRenderer()); + updateUI(); + } + + /** + * Creates a new JTree object. + * + * @param root the root node + */ + public JTree(TreeNode root) + { + this(root, false); + } + + /** + * Creates a new JTree 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 JTree 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 pos. 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 TreeModel 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 JTree object. + * + * @return the associated TreeUI object + */ + public TreeUI getUI() + { + return (TreeUI) ui; + } + + /** + * Sets the UI associated with this JTree object. + * + * @param ui the TreeUI 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)); + 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 + * JToggleButton. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * Returns the preferred viewport size.. + * + * @return the preferred size + */ + public Dimension getPreferredScrollableViewportSize() + { + return null; + } + + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, int direction) + { + return 1; + } + + public int getScrollableBlockIncrement(Rectangle visibleRect, + int orientation, int direction) + { + return 1; + } + + public boolean getScrollableTracksViewportWidth() + { + return false; + } + + public boolean getScrollableTracksViewportHeight() + { + return false; + } + + /** + * Adds a TreeExpansionListener object to the tree. + * + * @param listener the listener to add + */ + public void addTreeExpansionListener(TreeExpansionListener listener) + { + listenerList.add(TreeExpansionListener.class, listener); + } + + /** + * Removes a TreeExpansionListener object from the tree. + * + * @param listener the listener to remove + */ + public void removeTreeExpansionListener(TreeExpansionListener listener) + { + listenerList.remove(TreeExpansionListener.class, listener); + } + + /** + * Returns all added TreeExpansionListener 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 TreeSelctionListener object to the tree. + * + * @param listener the listener to add + */ + public void addTreeSelectionListener(TreeSelectionListener listener) + { + listenerList.add(TreeSelectionListener.class, listener); + } + + /** + * Removes a TreeSelectionListener object from the tree. + * + * @param listener the listener to remove + */ + public void removeTreeSelectionListener(TreeSelectionListener listener) + { + listenerList.remove(TreeSelectionListener.class, listener); + } + + /** + * Returns all added TreeSelectionListener 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 TreeWillExpandListener object to the tree. + * + * @param listener the listener to add + */ + public void addTreeWillExpandListener(TreeWillExpandListener listener) + { + listenerList.add(TreeWillExpandListener.class, listener); + } + + /** + * Removes a TreeWillExpandListener object from the tree. + * + * @param listener the listener to remove + */ + public void removeTreeWillExpandListener(TreeWillExpandListener listener) + { + listenerList.remove(TreeWillExpandListener.class, listener); + } + + /** + * Returns all added TreeWillExpandListener 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 JTree object. + * + * @return the associated TreeModel + */ + public TreeModel getModel() + { + return treeModel; + } + + /** + * Sets the model to use in JTree. + * + * @param model the TreeModel to use + */ + public void setModel(TreeModel model) + { + if (treeModel == model) + return; + + TreeModel oldValue = treeModel; + treeModel = model; + + firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model); + + // add treeModelListener to the new model + if (treeModelListener == null) + treeModelListener = createTreeModelListener(); + model.addTreeModelListener(treeModelListener); + } + + /** + * Checks if this JTree object is editable. + * + * @return true if this tree object is editable, + * false otherwise + */ + public boolean isEditable() + { + return editable; + } + + /** + * Sets the editable property. + * + * @param flag true to make this tree object editable, + * false 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 true if the root element is visible, + * false 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; + } + + /** + * @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; + + Rectangle rect = getPathBounds(path); + + if (rect == null) + return; + + scrollRectToVisible(rect); + } + + 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]; + + for (int i = rows.length - 1; i >= 0; --i) + paths[i] = getPathForRow(rows[i]); + + addSelectionPaths(paths); + } + + 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); + } + + public void removeSelectionRow(int row) + { + TreePath path = getPathForRow(row); + + if (path != null) + selectionModel.removeSelectionPath(path); + } + + public void removeSelectionRows(int[] rows) + { + 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]); + + removeSelectionPaths(paths); + } + + public void removeSelectionInterval(int index0, int index1) + { + TreePath[] paths = getPathBetweenRows(index0, index1); + + if (paths != null) + removeSelectionPaths(paths); + } + + public void clearSelection() + { + selectionModel.clearSelection(); + setLeadSelectionPath(null); + } + + public TreePath getLeadSelectionPath() + { + return leadSelectionPath; + } + + /** + * @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; + } + + /** + * @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 dragEnabled property. + * + * @return the value + * + * @since 1.4 + */ + public boolean getDragEnabled() + { + return dragEnabled; + } + + /** + * Set the dragEnabled property. + * + * @param enabled new value + * + * @since 1.4 + */ + public void setDragEnabled(boolean enabled) + { + + dragEnabled = enabled; + } + + public int getRowCount() + { + TreeUI ui = getUI(); + + if (ui != null) + return ui.getRowCount(this); + + return 0; + } + + public void collapsePath(TreePath path) + { + setExpandedState(path, false); + } + + public void collapseRow(int row) + { + if (row < 0 || row >= getRowCount()) + return; + + TreePath path = getPathForRow(row); + + if (path != null) + collapsePath(path); + } + + public void expandPath(TreePath path) + { + // Don't expand if last path component is a leaf node. + if ((path == null) || (treeModel.isLeaf(path.getLastPathComponent()))) + return; + + setExpandedState(path, true); + } + + public void expandRow(int row) + { + if (row < 0 || row >= getRowCount()) + return; + + TreePath path = getPathForRow(row); + + if (path != null) + expandPath(path); + } + + public boolean isCollapsed(TreePath path) + { + return !isExpanded(path); + } + + public boolean isCollapsed(int row) + { + if (row < 0 || row >= getRowCount()) + return false; + + 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 checkExpandParents(TreePath path) throws ExpandVetoException + { + + TreePath parent = path.getParentPath(); + + if (parent != null) + checkExpandParents(parent); + + fireTreeWillExpand(path); + } + + private void doExpandParents(TreePath path, boolean state) + { + TreePath parent = path.getParentPath(); + + if (isExpanded(parent)) + { + nodeStates.put(path, state ? EXPANDED : COLLAPSED); + return; + } + + if (parent != null) + doExpandParents(parent, false); + + nodeStates.put(path, state ? EXPANDED : COLLAPSED); + } + + protected void setExpandedState(TreePath path, boolean state) + { + if (path == null) + return; + + TreePath parent = path.getParentPath(); + + try + { + if (parent != null) + checkExpandParents(parent); + } + catch (ExpandVetoException e) + { + // Expansion vetoed. + 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}. + * + * @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 value.toString() 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 + * null. + * + * @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 + * startingRow that starts with prefix. + * Searching is done in the direction specified by bias. + * + * @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 null 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 path. If includePath is set + * to true and path itself is selected, then + * it will be removed too. + * + * @param path the path from which selected descendants are to be removed + * @param includePath if true then path itself + * will also be remove if it's selected + * + * @return true if something has been removed, + * false 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; + } +} diff --git a/libjava/classpath/javax/swing/JViewport.java b/libjava/classpath/javax/swing/JViewport.java new file mode 100644 index 0000000..397cb31 --- /dev/null +++ b/libjava/classpath/javax/swing/JViewport.java @@ -0,0 +1,490 @@ +/* JViewport.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.io.Serializable; + +import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ViewportUI; + +/** + * + *

+ *                                                     _
+ *   +-------------------------------+    ...........Y1 \
+ *   |  view                         |                .  \
+ *   |  (this component's child)     |                .   > VY
+ *   |                               |                .  / = Y2-Y1
+ *   |         +------------------------------+  ....Y2_/
+ *   |         | viewport            |        |       .
+ *   |         | (this component)    |        |       .
+ *   |         |                     |        |       .
+ *   |         |                     |        |       .
+ *   |         |                     |        |       .
+ *   |         |                     |        |       .
+ *   |         +------------------------------+  ....Y3
+ *   |                               |                .
+ *   |         .                     |        .       .
+ *   |         .                     |        .       .
+ *   +---------.---------------------+    ...........Y4
+ *   .         .                     .        .
+ *   .         .                     .        .
+ *   .         .                     .        .
+ *   X1.......X2.....................X3.......X4
+ *   \____  ___/
+ *        \/
+ *        VX = X2-X1
+ *
+ * + *

A viewport is, like all swing components, located at some position in + * the swing component tree; that location is exactly the same as any other + * components: the viewport's "bounds".

+ * + *

But in terms of drawing its child, the viewport thinks of itself as + * covering a particular position of the view's coordinate space. + * For example, the {@link javax.JViewPort.getViewPosition} method returns + * the position (VX,VY) shown above, which is an position in + * "view space", even though this is implemented by positioning + * the underlying child at position (-VX,-VY)

+ * + */ +public class JViewport extends JComponent +{ + + /** + * 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. + */ + protected class ViewListener + extends ComponentAdapter + implements Serializable + { + private static final long serialVersionUID = -2812489404285958070L; + + /** + * Creates a new instance of ViewListener. + */ + protected ViewListener() + { + } + + /** + * Receives notification when a component (in this case: the view + * component) changes it's size. + * + * @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); + } + } + + 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; + + 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 + * of the viewport's bounds, unless the viewport transforms units of + * width and height, which it may do, for example if it magnifies or + * rotates its view. + * + * @see #toViewCoordinates + */ + Dimension extentSize; + + /** + * The width and height of the view in its own coordinate space. + */ + + Dimension viewSize; + + Point lastPaintPosition; + + /** + * The ViewListener instance. + */ + ViewListener viewListener; + + public JViewport() + { + setOpaque(true); + setScrollMode(BLIT_SCROLL_MODE); + setLayout(createLayoutManager()); + updateUI(); + } + + public Dimension getExtentSize() + { + if (extentSize == null) + return toViewCoordinates(getSize()); + else + return extentSize; + } + + public Dimension toViewCoordinates(Dimension size) + { + return size; + } + + public Point toViewCoordinates(Point p) + { + Point pos = getViewPosition(); + return new Point(p.x + pos.x, + p.y + pos.y); + } + + public void setExtentSize(Dimension newSize) + { + extentSize = newSize; + fireStateChanged(); + } + + /** + * Returns the viewSize when set, or the preferred size of the set + * Component view. If no viewSize and no Component view is set an + * empty Dimension is returned. + */ + public Dimension getViewSize() + { + if (isViewSizeSet) + return viewSize; + else + { + Component view = getView(); + if (view != null) + return view.getPreferredSize(); + else + return new Dimension(); + } + } + + + public void setViewSize(Dimension newSize) + { + viewSize = newSize; + Component view = getView(); + if (view != null) + view.setSize(viewSize); + isViewSizeSet = true; + fireStateChanged(); + } + + /** + * Get the viewport's position in view space. Despite confusing name, + * this really does return the viewport's (0,0) position in view space, + * not the view's position. + */ + + public Point getViewPosition() + { + Component view = getView(); + if (view == null) + return new Point(0,0); + else + { + Point p = view.getLocation(); + p.x = -p.x; + p.y = -p.y; + return p; + } + } + + public void setViewPosition(Point p) + { + Component view = getView(); + if (view != null) + { + Point q = new Point(-p.x, -p.y); + view.setLocation(q); + fireStateChanged(); + } + } + + public Rectangle getViewRect() + { + return new Rectangle(getViewPosition(), + getExtentSize()); + } + + /** + * @deprecated 1.4 + */ + public boolean isBackingStoreEnabled() + { + return scrollMode == BACKINGSTORE_SCROLL_MODE; + } + + /** + * @deprecated 1.4 + */ + public void setBackingStoreEnabled(boolean b) + { + if (b && scrollMode != BACKINGSTORE_SCROLL_MODE) + { + scrollMode = BACKINGSTORE_SCROLL_MODE; + fireStateChanged(); + } + } + + public void setScrollMode(int mode) + { + scrollMode = mode; + fireStateChanged(); + } + + public int getScrollMode() + { + return scrollMode; + } + + public Component getView() + { + if (getComponentCount() == 0) + return null; + + return getComponents()[0]; + } + + public void setView(Component v) + { + while (getComponentCount() > 0) + { + if (viewListener != null) + getView().removeComponentListener(viewListener); + remove(0); + } + + if (v != null) + { + if (viewListener == null) + viewListener = createViewListener(); + v.addComponentListener(viewListener); + add(v); + fireStateChanged(); + } + } + + public void revalidate() + { + fireStateChanged(); + super.revalidate(); + } + + public void reshape(int x, int y, int w, int h) + { + boolean changed = + (x != getX()) + || (y != getY()) + || (w != getWidth()) + || (h != getHeight()); + super.reshape(x, y, w, h); + if (changed) + fireStateChanged(); + } + + protected void addImpl(Component comp, Object constraints, int index) + { + if (getComponentCount() > 0) + remove(getComponents()[0]); + + super.addImpl(comp, constraints, index); + } + + public final Insets getInsets() + { + return new Insets(0,0,0,0); + } + + public final Insets getInsets(Insets insets) + { + if (insets == null) + return getInsets(); + insets.top = 0; + insets.bottom = 0; + insets.left = 0; + insets.right = 0; + return insets; + } + + public boolean isOptimizedDrawingEnabled() + { + return false; + } + + public void paint(Graphics g) + { + paintComponent(g); + } + + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + public ChangeListener[] getChangeListeners() + { + 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. + * + * @return The UI class' String ID. + */ + public String getUIClassID() + { + return "ViewportUI"; + } + + /** + * This method resets the UI used to the Look and Feel defaults.. + */ + public void updateUI() + { + setUI((ViewportUI) UIManager.getUI(this)); + } + + /** + * This method returns the viewport's UI delegate. + * + * @return The viewport's UI delegate. + */ + public ViewportUI getUI() + { + return (ViewportUI) ui; + } + + /** + * This method sets the viewport's UI delegate. + * + * @param ui The viewport's UI delegate. + */ + public void setUI(ViewportUI ui) + { + super.setUI(ui); + } + + public final void setBorder(Border border) + { + if (border != null) + throw new IllegalArgumentException(); + } + + /** + * Creates a {@link ViewListener} that is supposed to listen for + * size changes on the view component. + * + * @return a ViewListener instance + */ + protected ViewListener createViewListener() + { + return new ViewListener(); + } + + /** + * Creates the LayoutManager that is used for this viewport. Override + * this method if you want to use a custom LayoutManager. + * + * @return a LayoutManager to use for this viewport + */ + protected LayoutManager createLayoutManager() + { + return new ViewportLayout(); + } +} diff --git a/libjava/classpath/javax/swing/JWindow.java b/libjava/classpath/javax/swing/JWindow.java new file mode 100644 index 0000000..4499003 --- /dev/null +++ b/libjava/classpath/javax/swing/JWindow.java @@ -0,0 +1,245 @@ +/* JWindow.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.LayoutManager; +import java.awt.Window; +import java.awt.event.KeyEvent; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; + +/** + * Unlike JComponent derivatives, JWindow inherits from + * java.awt.Window. But also lets a look-and-feel component to its work. + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class JWindow extends Window implements Accessible, RootPaneContainer +{ + private static final long serialVersionUID = 5420698392125238833L; + + protected JRootPane rootPane; + + /** + * @specnote rootPaneCheckingEnabled is false to comply with J2SE 5.0 + */ + protected boolean rootPaneCheckingEnabled = false; + + 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()); + windowInit(); + } + + public JWindow(GraphicsConfiguration gc) + { + super(SwingUtilities.getOwnerFrame(), gc); + windowInit(); + } + + public JWindow(Frame owner) + { + super(owner); + windowInit(); + } + + public JWindow(Window owner) + { + super(owner); + windowInit(); + } + + public JWindow(Window owner, GraphicsConfiguration gc) + { + super(owner, gc); + windowInit(); + } + + protected void windowInit() + { + 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; + } + + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + public void setLayout(LayoutManager manager) + { + // 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); + } + else + super.setLayout(manager); + } + + public void setLayeredPane(JLayeredPane layeredPane) + { + getRootPane().setLayeredPane(layeredPane); + } + + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } + + public JRootPane getRootPane() + { + if (rootPane == null) + setRootPane(createRootPane()); + return rootPane; + } + + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); + + rootPane = root; + add(rootPane, BorderLayout.CENTER); + } + + protected JRootPane createRootPane() + { + return new JRootPane(); + } + + public Container getContentPane() + { + return getRootPane().getContentPane(); + } + + public void setContentPane(Container contentPane) + { + getRootPane().setContentPane(contentPane); + } + + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + public void setGlassPane(Component glassPane) + { + getRootPane().setGlassPane(glassPane); + } + + + protected void addImpl(Component comp, Object constraints, int index) + { + // 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); + else + { + if (isRootPaneCheckingEnabled()) + throw new Error("Do not use add() on JWindow directly. Use " + + "getContentPane().add() instead"); + getContentPane().add(comp, constraints, index); + } + } + + public void remove(Component comp) + { + // If we're removing the root pane, use super.remove. Otherwise + // pass it on to the content pane instead. + if (comp == rootPane) + super.remove(rootPane); + else + getContentPane().remove(comp); + } + + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + public void update(Graphics g) + { + paint(g); + } + + protected void processKeyEvent(KeyEvent e) + { + super.processKeyEvent(e); + } + + public AccessibleContext getAccessibleContext() + { + return null; + } + + protected String paramString() + { + return "JWindow"; + } +} diff --git a/libjava/classpath/javax/swing/KeyStroke.java b/libjava/classpath/javax/swing/KeyStroke.java new file mode 100644 index 0000000..12a280c --- /dev/null +++ b/libjava/classpath/javax/swing/KeyStroke.java @@ -0,0 +1,122 @@ +/* KeyStroke.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.AWTKeyStroke; +import java.awt.event.KeyEvent; +import java.io.Serializable; + +public class KeyStroke + extends AWTKeyStroke + implements Serializable +{ + private static final long serialVersionUID = -9060180771037902530L; + + // Called by java.awt.AWTKeyStroke.registerSubclass via reflection. + private KeyStroke() + { + } + + private KeyStroke(char keyChar, int keyCode, int modifiers, + boolean onKeyRelease) + { + super(keyChar, keyCode, modifiers, onKeyRelease); + } + + static + { + AWTKeyStroke.registerSubclass(KeyStroke.class); + } + + public static KeyStroke getKeyStroke(char keyChar) + { + return (KeyStroke) getAWTKeyStroke(keyChar); + } + + /** + * @deprecated Use {@link #getKeyStroke(char)} + * + * This method, unlike all the other factory methods on this object, + * returns a non-cached, non-shared object. New code should not use it. + */ + public static KeyStroke getKeyStroke(char keyChar, boolean onKeyRelease) + { + return new KeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, onKeyRelease); + } + + public static KeyStroke getKeyStroke(Character keyChar, int modifiers) + { + return (KeyStroke) getAWTKeyStroke(keyChar, modifiers); + } + + public static KeyStroke getKeyStroke(int keyCode, int modifiers, + boolean onKeyRelease) + { + return (KeyStroke) getAWTKeyStroke(keyCode, modifiers, onKeyRelease); + } + + public static KeyStroke getKeyStroke(int keyCode, int modifiers) + { + return (KeyStroke) getAWTKeyStroke(keyCode, modifiers); + } + + /** + * Returns the KeyStroke according to getAWTKeyStroke(). + * But it returns null instead of throwing + * IllegalArugmentException when + * the keystoke sequence cannot be parsed from the given string. + */ + public static KeyStroke getKeyStroke(String str) + { + try + { + return (KeyStroke) getAWTKeyStroke(str); + } + catch (IllegalArgumentException iae) + { + return null; + } + } + + public static KeyStroke getKeyStrokeForEvent(KeyEvent event) + { + return (KeyStroke) getAWTKeyStrokeForEvent(event); + } + +} diff --git a/libjava/classpath/javax/swing/LayoutFocusTraversalPolicy.java b/libjava/classpath/javax/swing/LayoutFocusTraversalPolicy.java new file mode 100644 index 0000000..2d13515 --- /dev/null +++ b/libjava/classpath/javax/swing/LayoutFocusTraversalPolicy.java @@ -0,0 +1,89 @@ +/* LayoutFocusTraversalPolicy.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.awt.Component; +import java.io.Serializable; +import java.util.Comparator; + +/** + * @author Graydon Hoare + * @author Michael Koch + * + * @since 1.4 + */ +public class LayoutFocusTraversalPolicy + extends SortingFocusTraversalPolicy + implements Serializable +{ + private static class LayoutComparator + implements Comparator + { + public LayoutComparator() + { + // Do nothing here. + } + + public int compare(Object o1, Object o2) + { + Component comp1 = (Component) o1; + Component comp2 = (Component) o2; + + int x1 = comp1.getX(); + int y1 = comp1.getY(); + int x2 = comp2.getX(); + int y2 = comp2.getY(); + + if (x1 == x2 && y1 == y2) + return 0; + + if ((y1 < y2) || ((y1 == y2) && (x1 < x2))) + return -1; + + return 1; + } + } + + private static final long serialVersionUID = 4312146927238881442L; + + public LayoutFocusTraversalPolicy() + { + super(new LayoutComparator()); + } +} diff --git a/libjava/classpath/javax/swing/ListCellRenderer.java b/libjava/classpath/javax/swing/ListCellRenderer.java new file mode 100644 index 0000000..6ce115e --- /dev/null +++ b/libjava/classpath/javax/swing/ListCellRenderer.java @@ -0,0 +1,52 @@ +/* ListCellRenderer.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; + +/** + * Renders the cells of a {@link JList}. + */ +public interface ListCellRenderer +{ + Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus); +} diff --git a/libjava/classpath/javax/swing/ListModel.java b/libjava/classpath/javax/swing/ListModel.java new file mode 100644 index 0000000..736627e --- /dev/null +++ b/libjava/classpath/javax/swing/ListModel.java @@ -0,0 +1,80 @@ +/* ListModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import javax.swing.event.ListDataListener; + +/** + * The data model that is typically used in {@link JList}. + * + * @author Graydon Hoare (graydon@redhat.com) + */ +public interface ListModel +{ + /** + * Return the number of data elements in the list. + * + * @return The number of data elements in the list + */ + int getSize(); + + /** + * Retrieves a data element at a specified index. + * + * @param index The index of the element to retrieve + * + * @return The data element at the specified index + */ + Object getElementAt(int index); + + /** + * Add a listener object to this model. The listener will be called + * any time the set of elements in the model is changed. + * + * @param l The listener to add + */ + void addListDataListener(ListDataListener l); + + /** + * Add a listener object to this model. The listener will no longer be + * called when the set of elements in the model is changed. + * + * @param l The listener to remove + */ + void removeListDataListener(ListDataListener l); +} diff --git a/libjava/classpath/javax/swing/ListSelectionModel.java b/libjava/classpath/javax/swing/ListSelectionModel.java new file mode 100644 index 0000000..f4680d7 --- /dev/null +++ b/libjava/classpath/javax/swing/ListSelectionModel.java @@ -0,0 +1,86 @@ +/* ListSelectionModel.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import javax.swing.event.ListSelectionListener; + +/** + * The model that is used in {@link JList} to define the selected/not-selected + * cells of that list. + */ +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); + + 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); + +} diff --git a/libjava/classpath/javax/swing/LookAndFeel.java b/libjava/classpath/javax/swing/LookAndFeel.java new file mode 100644 index 0000000..8858742 --- /dev/null +++ b/libjava/classpath/javax/swing/LookAndFeel.java @@ -0,0 +1,236 @@ +/* LookAndFeel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Toolkit; + +import javax.swing.text.JTextComponent; + +public abstract class LookAndFeel +{ + /** + * This method is called once by UIManager.setLookAndFeel to create + * the look and feel specific defaults table. + * + * @return the UI defaults + */ + public UIDefaults getDefaults() + { + return null; + } + + /** + * Returns a description of the look and feel. + * + * @return A description of the look and feel. + */ + public abstract String getDescription(); + + public static Object getDesktopPropertyValue(String systemPropertyName, + Object fallbackValue) + { + Object value = Toolkit.getDefaultToolkit().getDesktopProperty(systemPropertyName); + return value != null ? value : fallbackValue; + } + + /** + * Returns an identifier for the look and feel. + * + * @return An identifier for the look and feel. + */ + public abstract String getID(); + + /** + * Returns the name for the look and feel. + * + * @return The name for the look and feel. + */ + public abstract String getName(); + + /** + * Returns true when the Look and Feel supports window decorations, + * false others. This method returns always false and needs to be overwritten + * when the derived Look and Feel supports this. + * + * @return false + * + * @since 1.4 + */ + public boolean getSupportsWindowDecorations() + { + return false; + } + + /** + * UIManager.setLookAndFeel calls this method before the first call + * (and typically the only call) to getDefaults(). + */ + public void initialize() + { + } + + /** + * Convenience method for installing a component's default Border object + * on the specified component if either the border is currently null + * or already an instance of UIResource. + */ + public static void installBorder(JComponent c, String 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) + { + } + + /** + * Convenience method for initializing a components foreground background + * and font properties with values from the current defaults table. + */ + public static void installColorsAndFont(JComponent component, + String defaultBgName, + String defaultFgName, + String defaultFontName) + { + } + + /** + * Returns true if the look and feel is the "native" look and + * feel for the current platform, and false otherwise. + * + * @return A flag indicating whether or not this is the native look and feel + * for the current platform. + */ + public abstract boolean isNativeLookAndFeel(); + + /** + * Returns true if the look and feel is supported on the + * current operating system, and false otherwise. This + * mechanism is provided so that it is possible to prevent a look and feel + * from being used on some operating systems (usually for legal, not + * technical, reasons). + * + * @return A flag indicating whether or not the look and feel is supported + * on the current platform. + */ + public abstract boolean isSupportedLookAndFeel(); + + /** + * Loads the bindings in keys into retMap. + */ + public static void loadKeyBindings(InputMap retMap, Object[] keys) + { + } + + /** + * Creates a ComponentInputMap from keys. + */ + public static ComponentInputMap makeComponentInputMap(JComponent c, + Object[] keys) + { + return null; + } + + /** + * Utility method that creates a UIDefaults.LazyValue that creates an + * ImageIcon UIResource for the specified gifFile filename. + */ + public static Object makeIcon(Class baseClass, String gifFile) + { + return null; + } + + /** + * Creates a InputMap from keys. + */ + public static InputMap makeInputMap(Object[] keys) + { + return null; + } + + /** + * Convenience method for building lists of KeyBindings. + */ + public static JTextComponent.KeyBinding[] makeKeyBindings(Object[] keyBindingList) + { + return null; + } + + /** + * Invoked when the user attempts an invalid operation. The default implement + * just beeps. Subclasses that wish to change this need to override this + * method. + * + * @param component the component the error occured in + */ + public void provideErrorFeedback(Component component) + { + Toolkit.getDefaultToolkit().beep(); + } + + /** + * Returns a string that displays and identifies this object's properties. + * + * @return the string "LookAndFeel" + */ + public String toString() + { + return "LookAndFeel"; + } + + /** + * UIManager.setLookAndFeel calls this method just before we're replaced by + * a new default look and feel. + */ + public void uninitialize() + { + } + + /** + * Convenience method for un-installing a component's default border on the + * specified component if the border is currently an instance of UIResource. + */ + public static void uninstallBorder(JComponent c) + { + } +} diff --git a/libjava/classpath/javax/swing/MenuElement.java b/libjava/classpath/javax/swing/MenuElement.java new file mode 100644 index 0000000..46eb8c2 --- /dev/null +++ b/libjava/classpath/javax/swing/MenuElement.java @@ -0,0 +1,93 @@ +/* MenuElement.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +/** + * Defines the methods that any menu element in a {@link JMenu} must + * implement. + * + * @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 diff --git a/libjava/classpath/javax/swing/MenuSelectionManager.java b/libjava/classpath/javax/swing/MenuSelectionManager.java new file mode 100644 index 0000000..acaee97 --- /dev/null +++ b/libjava/classpath/javax/swing/MenuSelectionManager.java @@ -0,0 +1,387 @@ +/* MenuSelectionManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Vector; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * This class manages current menu selectection. It provides + * methods to clear and set current selected menu path. + * It also fires StateChange event to its registered + * listeners whenever selected path of the current menu hierarchy + * changes. + * + */ +public class MenuSelectionManager +{ + /** ChangeEvent fired when selected path changes*/ + protected ChangeEvent changeEvent = new ChangeEvent(this); + + /** List of listeners for this MenuSelectionManager */ + protected EventListenerList listenerList = new EventListenerList(); + + /** Default manager for the current menu hierarchy*/ + private static final MenuSelectionManager manager = new MenuSelectionManager(); + + /** Path to the currently selected menu */ + private Vector selectedPath = new Vector(); + + /** + * Fires StateChange event to registered listeners + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].stateChanged(changeEvent); + } + + /** + * Adds ChangeListener to this MenuSelectionManager + * + * @param listener ChangeListener to add + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * Removes ChangeListener from the list of registered listeners + * for this MenuSelectionManager. + * + * @param listener ChangeListner to remove + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * Returns list of registered listeners with MenuSelectionManager + * + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Unselects all the menu elements on the selection path + */ + public void clearSelectedPath() + { + // Send events from the bottom most item in the menu - hierarchy to the + // top most + for (int i = selectedPath.size() - 1; i >= 0; i--) + ((MenuElement) selectedPath.get(i)).menuSelectionChanged(false); + + // clear selected path + selectedPath.clear(); + + // notify all listeners that the selected path was changed + fireStateChanged(); + } + + /** + * This method returns menu element on the selected path that contains + * given source point. If no menu element on the selected path contains this + * point, then null is returned. + * + * @param source Component relative to which sourcePoint is given + * @param sourcePoint point for which we want to find menu element that contains it + * + * @return Returns menu element that contains given source point and belongs + * to the currently selected path. Null is return if no such menu element found. + */ + public Component componentForPoint(Component source, Point sourcePoint) + { + // Convert sourcePoint to screen coordinates. + Point sourcePointOnScreen = sourcePoint; + SwingUtilities.convertPointToScreen(sourcePointOnScreen, source); + + Point compPointOnScreen; + Component resultComp = null; + + // For each menu element on the selected path, express its location + // in terms of screen coordinates and check if there is any + // menu element on the selected path that contains given source point. + for (int i = 0; i < selectedPath.size(); i++) + { + Component comp = ((Component) selectedPath.get(i)); + Dimension size = comp.getSize(); + + // convert location of this menu item to screen coordinates + compPointOnScreen = comp.getLocationOnScreen(); + + if (compPointOnScreen.x <= sourcePointOnScreen.x + && sourcePointOnScreen.x < compPointOnScreen.x + size.width + && compPointOnScreen.y <= sourcePointOnScreen.y + && sourcePointOnScreen.y < compPointOnScreen.y + size.height) + { + Point p = sourcePointOnScreen; + SwingUtilities.convertPointFromScreen(p, comp); + resultComp = SwingUtilities.getDeepestComponentAt(comp, p.x, p.y); + break; + } + } + return resultComp; + } + + /** + * Returns shared instance of MenuSelection Manager + * + * @return default Manager + */ + public static MenuSelectionManager defaultManager() + { + return manager; + } + + /** + * Returns path representing current menu selection + * + * @return Current selection path + */ + public MenuElement[] getSelectedPath() + { + MenuElement[] path = new MenuElement[selectedPath.size()]; + + for (int i = 0; i < path.length; i++) + path[i] = (MenuElement) selectedPath.get(i); + + return path; + } + + /** + * Returns true if specified component is part of current menu + * heirarchy and false otherwise + * + * @param c Component for which to check + * @return True if specified component is part of current menu + */ + public boolean isComponentPartOfCurrentMenu(Component c) + { + MenuElement[] subElements; + for (int i = 0; i < selectedPath.size(); i++) + { + subElements = ((MenuElement) selectedPath.get(i)).getSubElements(); + for (int j = 0; j < subElements.length; j++) + { + if ((subElements[j].getComponent()).equals(c)) + return true; + } + } + + return false; + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void processKeyEvent(KeyEvent e) + { + throw new UnsupportedOperationException("not implemented"); + } + + /** + * Forwards given mouse event to all of the source subcomponents. + * + * @param event Mouse event + */ + public void processMouseEvent(MouseEvent event) + { + Component source = ((Component) event.getSource()); + + // In the case of drag event, event.getSource() returns component + // where drag event originated. However menu element processing this + // event should be the one over which mouse is currently located, + // which is not necessary the source of the drag event. + Component mouseOverMenuComp; + + // find over which menu element the mouse is currently located + if (event.getID() == MouseEvent.MOUSE_DRAGGED + || event.getID() == MouseEvent.MOUSE_RELEASED) + mouseOverMenuComp = componentForPoint(source, event.getPoint()); + else + mouseOverMenuComp = source; + + // Process this event only if mouse is located over some menu element + if (mouseOverMenuComp != null && (mouseOverMenuComp instanceof MenuElement)) + { + MenuElement[] path = getPath(mouseOverMenuComp); + ((MenuElement) mouseOverMenuComp).processMouseEvent(event, path, + manager); + + // FIXME: Java specification says that mouse events should be + // forwarded to subcomponents. The code below does it, but + // menu's work fine without it. This code is commented for now. + + /* + MenuElement[] subComponents = ((MenuElement) mouseOverMenuComp) + .getSubElements(); + + for (int i = 0; i < subComponents.length; i++) + { + subComponents[i].processMouseEvent(event, path, manager); + } + */ + } + else + { + if (event.getID() == MouseEvent.MOUSE_RELEASED) + clearSelectedPath(); + } + } + + /** + * Sets menu selection to the specified path + * + * @param path new selection path + */ + public void setSelectedPath(MenuElement[] path) + { + if (path == null) + { + clearSelectedPath(); + return; + } + + int i; + int minSize = path.length; // size of the smaller path. + + if (path.length > selectedPath.size()) + { + minSize = selectedPath.size(); + + // if new selected path contains more elements then current + // selection then first add all elements at + // the indexes > selectedPath.size + for (i = selectedPath.size(); i < path.length; i++) + { + selectedPath.add(path[i]); + path[i].menuSelectionChanged(true); + } + } + + else if (path.length < selectedPath.size()) + { + // if new selected path contains less elements then current + // selection then first remove all elements from the selection + // at the indexes > path.length + for (i = selectedPath.size() - 1; i >= path.length; i--) + { + ((MenuElement) selectedPath.get(i)).menuSelectionChanged(false); + selectedPath.remove(i); + } + + minSize = path.length; + } + + // Now compare elements in new and current selection path at the + // same location and adjust selection until + // same menu elements will be encountered at the + // same index in both current and new selection path. + MenuElement oldSelectedItem; + + for (i = minSize - 1; i >= 0; i--) + { + oldSelectedItem = (MenuElement) selectedPath.get(i); + + if (path[i].equals(oldSelectedItem)) + break; + + oldSelectedItem.menuSelectionChanged(false); + path[i].menuSelectionChanged(true); + selectedPath.setElementAt(path[i], i); + } + + fireStateChanged(); + } + + /** + * Returns path to the specified component + * + * @param c component for which to find path for + * + * @return path to the specified component + */ + private MenuElement[] getPath(Component c) + { + // FIXME: There is the same method in BasicMenuItemUI. However I + // cannot use it here instead of this method, since I cannot assume that + // all the menu elements on the selected path are JMenuItem or JMenu. + // For now I've just duplicated it here. Please + // fix me or delete me if another better approach will be found, and + // this method will not be necessary. + ArrayList path = new ArrayList(); + + // if given component is JMenu, we also need to include + // it's popup menu in the path + if (c instanceof JMenu) + path.add(((JMenu) c).getPopupMenu()); + while (c instanceof MenuElement) + { + path.add(0, (MenuElement) c); + + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); + } + + MenuElement[] pathArray = new MenuElement[path.size()]; + path.toArray(pathArray); + return pathArray; + } +} diff --git a/libjava/classpath/javax/swing/MutableComboBoxModel.java b/libjava/classpath/javax/swing/MutableComboBoxModel.java new file mode 100644 index 0000000..ee79dac --- /dev/null +++ b/libjava/classpath/javax/swing/MutableComboBoxModel.java @@ -0,0 +1,82 @@ +/* MutableComboBoxModel.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * A data model used in {@link JComboBox}es that keeps track of the + * components data and provides methods to insert and remove elements from + * it. The classes implementing this interface should + * fire appropriate events indicating the undergoing change in the data model. + * + * @author Andrew Selkirk + * @author Olga Rodimina + */ +public interface MutableComboBoxModel extends ComboBoxModel +{ + /** + * This method adds given object to its data model. + * + * @param object element to add to the data model. + */ + void addElement(Object object); + + /** + * This method removes elements located at the given index in the data + * model. + * + * @param index index specifying location of the element to remove. + */ + void removeElementAt(int index); + + /** + * This method inserts givent element to the data model, at the specified + * index. + * + * @param object element to insert + * @param index index specifying the position in the data model where the + * given element should be inserted. + */ + void insertElementAt(Object object, int index); + + /** + * This method removes given element from the data model + * + * @param element to remove. + */ + void removeElement(Object object); +} // MutableComboBoxModel diff --git a/libjava/classpath/javax/swing/OverlayLayout.java b/libjava/classpath/javax/swing/OverlayLayout.java new file mode 100644 index 0000000..e8aef98 --- /dev/null +++ b/libjava/classpath/javax/swing/OverlayLayout.java @@ -0,0 +1,191 @@ +/* OverlayLayout.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager2; +import java.io.Serializable; + +/** + * OverlayLayout + * @author Andrew Selkirk + * @version 1.0 + */ +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 diff --git a/libjava/classpath/javax/swing/Popup.java b/libjava/classpath/javax/swing/Popup.java new file mode 100644 index 0000000..69e1f51 --- /dev/null +++ b/libjava/classpath/javax/swing/Popup.java @@ -0,0 +1,189 @@ +/* Popup.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; + + +/** + * Manages a popup window that displays a Component on top of + * everything else. + * + *

To obtain an instance of Popup, use the + * {@link javax.swing.PopupFactory}. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class Popup +{ + /** + * Constructs a new Popup given its owner, + * contents and the screen position where the popup + * will appear. + * + * @param owner the Component to which x and + * y are relative, or null for + * placing the popup relative to the origin of the screen. + * + * @param contents the contents that will be displayed inside + * the Popup. + * + * @param x the horizontal position where the Popup will appear. + * + * @param y the vertical position where the Popup will appear. + * + * @throws IllegalArgumentException if contents + * is null. + */ + protected Popup(Component owner, Component contents, + int x, int y) + { + if (contents == null) + throw new IllegalArgumentException(); + + // The real stuff happens in the implementation of subclasses, + // for instance JWindowPopup. + } + + + /** + * Constructs a new Popup. + */ + protected Popup() + { + } + + + /** + * Displays the Popup on the screen. Nothing happens + * if it is currently shown. + */ + public void show() + { + // Implemented by subclasses, for instance JWindowPopup. + } + + + /** + * Removes the Popup from the screen. Nothing happens + * if it is currently hidden. + */ + public void hide() + { + // Implemented by subclasses, for instance JWindowPopup. + } + + + /** + * A Popup that uses a JWindow for + * displaying its contents. + * + * @see PopupFactory#getPopup + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + static class JWindowPopup + extends Popup + { + /** + * The JWindow used for displaying the contents + * of the popup. + */ + JWindow window; + + + /** + * Constructs a new JWindowPopup given its owner, + * contents and the screen position where the popup + * will appear. + * + * @param owner the Component to which x and + * y are relative, or null for + * placing the popup relative to the origin of the screen. + * + * @param contents the contents that will be displayed inside + * the Popup. + * + * @param x the horizontal position where the Popup will appear. + * + * @param y the vertical position where the Popup will appear. + * + * @throws IllegalArgumentException if contents + * is null. + */ + public JWindowPopup(Component owner, Component contents, + int x, int y) + { + /* Checks whether contents is null. */ + super(owner, contents, x, y); + + window = new JWindow(); + window.getRootPane().add(contents); + window.setLocation(x, y); + window.pack(); + } + + + /** + * Displays the popup's JWindow on the screen. + * Nothing happens if it is already visible. + */ + public void show() + { + window.show(); + } + + + /** + * Removes the popup's JWindow from the + * screen. Nothing happens if it is currently not visible. + */ + public void hide() + { + /* Calling dispose() instead of hide() will conserve native + * system resources, for example memory in an X11 server. + * They will automatically be re-allocated by a call to + * show(). + */ + window.dispose(); + } + } +} diff --git a/libjava/classpath/javax/swing/PopupFactory.java b/libjava/classpath/javax/swing/PopupFactory.java new file mode 100644 index 0000000..29cf86d --- /dev/null +++ b/libjava/classpath/javax/swing/PopupFactory.java @@ -0,0 +1,139 @@ +/* PopupFactory.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; + + +/** + * A factory for Popup objects. These are used to + * managed little windows that float over everything else, + * typically containing a popup menu. + * + * @since 1.4 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class PopupFactory +{ + /** + * The shared factory object. + * + * @see #getSharedFactory + * @see #setSharedFactory + */ + private static PopupFactory sharedFactory; + + + /** + * Constructs a new PopupFactory. Usually, a single + * PopupFactory is shared among multiple consumers + * of Popup. Use {@link #getSharedInstance} to retrieve + * the current factory. + */ + public PopupFactory() + { + } + + + /** + * Sets the shared factory. + * + * @param factory the PopupFactory that future invocations of + * {@link #getSharedInstance} will return. + * + * @throws IllegalArgumentException if factory + * is null. + */ + public static void setSharedInstance(PopupFactory factory) + { + if (factory == null) + throw new IllegalArgumentException(); + + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + sharedFactory = factory; + } + + + /** + * Retrieves the shared factory, creating a new factory if + * necessary. + * + * @return a PopupFactory that can be used + * to create Popup objects. + */ + public static PopupFactory getSharedInstance() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (sharedFactory == null) + sharedFactory = new PopupFactory(); + + return sharedFactory; + } + + + /** + * Creates a new Popup given its owner, + * contents and the screen position where the popup + * will appear. + * + * @param owner the Component to which x and + * y are relative, or null for + * placing the popup relative to the origin of the screen. + * + * @param contents the contents that will be displayed inside + * the Popup. + * + * @param x the horizontal position where the Popup will appear. + * + * @param y the vertical position where the Popup will appear. + * + * @throws IllegalArgumentException if contents + * is null. + */ + public Popup getPopup(Component owner, Component contents, + int x, int y) + { + return new Popup.JWindowPopup(owner, contents, x, y); + } +} diff --git a/libjava/classpath/javax/swing/ProgressMonitor.java b/libjava/classpath/javax/swing/ProgressMonitor.java new file mode 100644 index 0000000..844258f --- /dev/null +++ b/libjava/classpath/javax/swing/ProgressMonitor.java @@ -0,0 +1,228 @@ +/* ProgressMonitor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; + +/** + * ProgressMonitor + * @author Andrew Selkirk + * @version 1.0 + */ +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 diff --git a/libjava/classpath/javax/swing/ProgressMonitorInputStream.java b/libjava/classpath/javax/swing/ProgressMonitorInputStream.java new file mode 100644 index 0000000..2022a1c --- /dev/null +++ b/libjava/classpath/javax/swing/ProgressMonitorInputStream.java @@ -0,0 +1,160 @@ +/* ProgressMonitorInputStream.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * ProgressMonitorInputStream + * @author Andrew Selkirk + * @version 1.0 + */ +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 diff --git a/libjava/classpath/javax/swing/Renderer.java b/libjava/classpath/javax/swing/Renderer.java new file mode 100644 index 0000000..c803e38 --- /dev/null +++ b/libjava/classpath/javax/swing/Renderer.java @@ -0,0 +1,72 @@ +/* Renderer.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; + +/** + * This interface is not used and exists only for compatibility. + * It probably has been replaced by {@link ListCellRenderer}, {@link + * javax.swing.table.TableCellRenderer} and {@link + * javax.swing.tree.TreeCellRenderer}. + * + * @specnote This interface is not used and exists only for compatibility. + * + * @author Andrew Selkirk + */ +public interface Renderer { + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * 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 new file mode 100644 index 0000000..8c4c323 --- /dev/null +++ b/libjava/classpath/javax/swing/RepaintManager.java @@ -0,0 +1,568 @@ +/* RepaintManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Rectangle; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +/** + *

The repaint manager holds a set of dirty regions, invalid components, + * and a double buffer surface. The dirty regions and invalid components + * are used to coalesce multiple revalidate() and repaint() calls in the + * component tree into larger groups to be refreshed "all at once"; the + * double buffer surface is used by root components to paint + * themselves.

+ * + *

In general, painting is very confusing in swing. see this + * document for more details.

+ * + * @author Graydon Hoare (graydon@redhat.com) + */ +public class RepaintManager +{ + + /** + *

A helper class which is placed into the system event queue at + * various times in order to facilitate repainting and layout. There is + * typically only one of these objects active at any time. When the + * {@link RepaintManager} is told to queue a repaint, it checks to see if + * a {@link RepaintWorker} is "live" in the system event queue, and if + * not it inserts one using {@link SwingUtilities.invokeLater}.

+ * + *

When the {@link RepaintWorker} comes to the head of the system + * event queue, its {@link RepaintWorker#run} method is executed by the + * swing paint thread, which revalidates all invalid components and + * repaints any damage in the swing scene.

+ */ + + protected class RepaintWorker + implements Runnable + { + boolean live; + public RepaintWorker() + { + live = false; + } + public synchronized void setLive(boolean b) + { + live = b; + } + public synchronized boolean isLive() + { + return live; + } + public void run() + { + RepaintManager rm = RepaintManager.globalManager; + setLive(false); + rm.validateInvalidComponents(); + rm.paintDirtyRegions(); + } + } + + + /** + * A table storing the dirty regions of components. The keys of this + * table are components, the values are rectangles. Each component maps + * to exactly one rectangle. When more regions are marked as dirty on a + * component, they are union'ed with the existing rectangle. + * + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + Hashtable dirtyComponents; + + /** + * A single, shared instance of the helper class. Any methods which mark + * components as invalid or dirty eventually activate this instance. It + * is added to the event queue if it is not already active, otherwise + * reused. + * + * @see #addDirtyRegion + * @see #addInvalidComponent + */ + RepaintWorker repaintWorker; + + /** + * The set of components which need revalidation, in the "layout" sense. + * There is no additional information about "what kind of layout" they + * need (as there is with dirty regions), so it is just a vector rather + * than a table. + * + * @see #addInvalidComponent + * @see #removeInvalidComponent + * @see #validateInvalidComponents + */ + Vector invalidComponents; + + /** + * Whether or not double buffering is enabled on this repaint + * manager. This is merely a hint to clients; the RepaintManager will + * always return an offscreen buffer when one is requested. + * + * @see #getDoubleBufferingEnabled + * @see #setDoubleBufferingEnabled + */ + boolean doubleBufferingEnabled; + + /** + * The current offscreen buffer. This is reused for all requests for + * offscreen drawing buffers. It grows as necessary, up to {@link + * #doubleBufferMaximumSize}, but there is only one shared instance. + * + * @see #getOffscreenBuffer + * @see #doubleBufferMaximumSize + */ + Image doubleBuffer; + + /** + * The maximum width and height to allocate as a double buffer. Requests + * beyond this size are ignored. + * + * @see #paintDirtyRegions + * @see #getDoubleBufferMaximumSize + * @see #setDoubleBufferMaximumSize + */ + Dimension doubleBufferMaximumSize; + + + /** + * The global, shared RepaintManager instance. This is reused for all + * components in all windows. 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(); + repaintWorker = new RepaintWorker(); + doubleBufferMaximumSize = new Dimension(2000,2000); + doubleBufferingEnabled = true; + } + + /** + * Get the value of the shared {@link #globalManager} instance, possibly + * returning a special manager associated with the specified + * component. The default implementaiton ignores the component parameter. + * + * @param component A component to look up the manager of + * + * @return The current repaint manager + * + * @see #setCurrentManager + */ + public static RepaintManager currentManager(Component component) + { + if (globalManager == null) + globalManager = new RepaintManager(); + return globalManager; + } + + /** + * Get the value of the shared {@link #globalManager} instance, possibly + * returning a special manager associated with the specified + * component. The default implementaiton ignores the component parameter. + * + * @param component A component to look up the manager of + * + * @return The current repaint manager + * + * @see #setCurrentManager + */ + public static RepaintManager currentManager(JComponent component) + { + return currentManager((Component)component); + } + + /** + * Set the value of the shared {@link #globalManager} instance. + * + * @param manager The new value of the shared instance + * + * @see #currentManager + */ + public static void setCurrentManager(RepaintManager manager) + { + globalManager = manager; + } + + /** + * Add a component to the {@link #invalidComponents} vector. If the + * {@link #repaintWorker} class is not active, insert it in the system + * event queue. + * + * @param component The component to add + * + * @see #removeInvalidComponent + */ + public synchronized void addInvalidComponent(JComponent component) + { + Component ancestor = component.getParent(); + + while (ancestor != null + && (! (ancestor instanceof JComponent) + || ! ((JComponent) ancestor).isValidateRoot() )) + ancestor = ancestor.getParent(); + + if (ancestor != null + && ancestor instanceof JComponent + && ((JComponent) ancestor).isValidateRoot()) + component = (JComponent) ancestor; + + if (invalidComponents.contains(component)) + return; + + invalidComponents.add(component); + + if (! repaintWorker.isLive()) + { + repaintWorker.setLive(true); + SwingUtilities.invokeLater(repaintWorker); + } + } + + /** + * Remove a component from the {@link #invalidComponents} vector. + * + * @param component The component to remove + * + * @see #addInvalidComponent + */ + public synchronized void removeInvalidComponent(JComponent component) + { + invalidComponents.removeElement(component); + } + + /** + * Add a region to the set of dirty regions for a specified component. + * This involves union'ing the new region with any existing dirty region + * associated with the component. If the {@link #repaintWorker} class + * is not active, insert it in the system event queue. + * + * @param component The component to add a dirty region for + * @param x The left x coordinate of the new dirty region + * @param y The top y coordinate of the new dirty region + * @param w The width of the new dirty region + * @param h The height of the new dirty region + * + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + public synchronized void addDirtyRegion(JComponent component, int x, int y, + int w, int h) + { + if (w == 0 || h == 0) + return; + + Rectangle r = new Rectangle(x, y, w, h); + if (dirtyComponents.containsKey(component)) + r = r.union((Rectangle)dirtyComponents.get(component)); + dirtyComponents.put(component, r); + if (! repaintWorker.isLive()) + { + repaintWorker.setLive(true); + SwingUtilities.invokeLater(repaintWorker); + } + } + + /** + * Get the dirty region associated with a component, or null + * if the component has no dirty region. + * + * @param component The component to get the dirty region of + * + * @return The dirty region of the component + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + public Rectangle getDirtyRegion(JComponent component) + { + return (Rectangle) dirtyComponents.get(component); + } + + /** + * Mark a component as dirty over its entire bounds. + * + * @param component The component to mark as dirty + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + */ + public void markCompletelyDirty(JComponent component) + { + Rectangle r = component.getBounds(); + addDirtyRegion(component, r.x, r.y, r.width, r.height); + } + + /** + * Remove all dirty regions for a specified component + * + * @param component The component to mark as clean + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyDirty + */ + public void markCompletelyClean(JComponent component) + { + dirtyComponents.remove(component); + } + + /** + * Return true if the specified component is completely + * contained within its dirty region, otherwise false + * + * @param component The component to check for complete dirtyness + * + * @return Whether the component is completely dirty + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + */ + public boolean isCompletelyDirty(JComponent component) + { + Rectangle dirty = (Rectangle) dirtyComponents.get(component); + if (dirty == null) + return false; + Rectangle r = component.getBounds(); + if (r == null) + return true; + return dirty.contains(r); + } + + /** + * Validate all components which have been marked invalid in the {@link + * #invalidComponents} vector. + */ + public void validateInvalidComponents() + { + for (Enumeration e = invalidComponents.elements(); e.hasMoreElements(); ) + { + JComponent comp = (JComponent) e.nextElement(); + if (! (comp.isVisible() && comp.isShowing())) + continue; + comp.validate(); + } + invalidComponents.clear(); + } + + /** + * Repaint all regions of all components which have been marked dirty in + * the {@link #dirtyComponents} table. + */ + public void paintDirtyRegions() + { + // step 1: pull out roots and calculate spanning damage + + HashMap roots = new HashMap(); + for (Enumeration e = dirtyComponents.keys(); e.hasMoreElements(); ) + { + JComponent comp = (JComponent) e.nextElement(); + if (! (comp.isVisible() && comp.isShowing())) + continue; + Rectangle damaged = getDirtyRegion(comp); + if (damaged.width == 0 || damaged.height == 0) + continue; + JRootPane root = comp.getRootPane(); + // 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); + } + } + + /** + * Get an offscreen buffer for painting a component's image. This image + * may be smaller than the proposed dimensions, depending on the value of + * the {@link #doubleBufferMaximumSize} property. + * + * @param component The component to return an offscreen buffer for + * @param proposedWidth The proposed width of the offscreen buffer + * @param proposedHeight The proposed height of the offscreen buffer + * + * @return A shared offscreen buffer for painting + * + * @see #doubleBuffer + */ + public Image getOffscreenBuffer(Component component, int proposedWidth, + int proposedHeight) + { + if (doubleBuffer == null + || (((doubleBuffer.getWidth(null) < proposedWidth) + || (doubleBuffer.getHeight(null) < proposedHeight)) + && (proposedWidth < doubleBufferMaximumSize.width) + && (proposedHeight < doubleBufferMaximumSize.height))) + { + doubleBuffer = component.createImage(proposedWidth, proposedHeight); + } + return doubleBuffer; + } + + /** + * Creates and returns a volatile offscreen buffer for the specified + * component that can be used as a double buffer. The returned image + * is a {@link VolatileImage}. Its size will be (proposedWidth, + * proposedHeight) except when the maximum double buffer size + * has been set in this RepaintManager. + * + * @param comp the Component for which to create a volatile buffer + * @param proposedWidth the proposed width of the buffer + * @param proposedHeight the proposed height of the buffer + * + * @since 1.4 + * + * @see {@link VolatileImage} + */ + public Image getVolatileOffscreenBuffer(Component comp, int proposedWidth, + int proposedHeight) + { + int maxWidth = doubleBufferMaximumSize.width; + int maxHeight = doubleBufferMaximumSize.height; + return comp.createVolatileImage(Math.min(maxWidth, proposedWidth), + Math.min(maxHeight, proposedHeight)); + } + + + /** + * Get the value of the {@link #doubleBufferMaximumSize} property. + * + * @return The current value of the property + * + * @see #setDoubleBufferMaximumSize + */ + public Dimension getDoubleBufferMaximumSize() + { + return doubleBufferMaximumSize; + } + + /** + * Set the value of the {@link #doubleBufferMaximumSize} property. + * + * @param size The new value of the property + * + * @see #getDoubleBufferMaximumSize + */ + public void setDoubleBufferMaximumSize(Dimension size) + { + doubleBufferMaximumSize = size; + } + + /** + * Set the value of the {@link #doubleBufferingEnabled} property. + * + * @param buffer The new value of the property + * + * @see #getDoubleBufferingEnabled + */ + public void setDoubleBufferingEnabled(boolean buffer) + { + doubleBufferingEnabled = buffer; + } + + /** + * Get the value of the {@link #doubleBufferingEnabled} property. + * + * @return The current value of the property + * + * @see #setDoubleBufferingEnabled + */ + public boolean isDoubleBufferingEnabled() + { + return doubleBufferingEnabled; + } + + public String toString() + { + return "RepaintManager"; + } +} diff --git a/libjava/classpath/javax/swing/RootPaneContainer.java b/libjava/classpath/javax/swing/RootPaneContainer.java new file mode 100644 index 0000000..b121f95 --- /dev/null +++ b/libjava/classpath/javax/swing/RootPaneContainer.java @@ -0,0 +1,100 @@ +/* RootPaneContainer.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; + +/** + * Components that contain a single {@link JRootPane} as only child + * implement this interface, typically this is implemented by the + * Swing top-level containers. + * + * @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 diff --git a/libjava/classpath/javax/swing/ScrollPaneConstants.java b/libjava/classpath/javax/swing/ScrollPaneConstants.java new file mode 100644 index 0000000..b586060 --- /dev/null +++ b/libjava/classpath/javax/swing/ScrollPaneConstants.java @@ -0,0 +1,152 @@ +/* ScrollPaneConstants.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * Defines some constants that are used in {@link JScrollPane} and related + * components. + * + * @author Andrew Selkirk + */ +public interface ScrollPaneConstants +{ + /** + * VIEWPORT + */ + String VIEWPORT = "VIEWPORT"; + + /** + * VERTICAL_SCROLLBAR + */ + String VERTICAL_SCROLLBAR = "VERTICAL_SCROLLBAR"; + + /** + * HORIZONTAL_SCROLLBAR + */ + String HORIZONTAL_SCROLLBAR = "HORIZONTAL_SCROLLBAR"; + + /** + * ROW_HEADER + */ + String ROW_HEADER = "ROW_HEADER"; + + /** + * COLUMN_HEADER + */ + String COLUMN_HEADER = "COLUMN_HEADER"; + + /** + * LOWER_LEFT_CORNER + */ + String LOWER_LEFT_CORNER = "LOWER_LEFT_CORNER"; + + /** + * LOWER_RIGHT_CORNER + */ + String LOWER_RIGHT_CORNER = "LOWER_RIGHT_CORNER"; + + /** + * UPPER_LEFT_CORNER + */ + String UPPER_LEFT_CORNER = "UPPER_LEFT_CORNER"; + + /** + * UPPER_RIGHT_CORNER + */ + String UPPER_RIGHT_CORNER = "UPPER_RIGHT_CORNER"; + + /** + * LOWER_LEADING_CORNER + */ + String LOWER_LEADING_CORNER = "LOWER_LEADING_CORNER"; + + /** + * LOWER_TRAILING_CORNER + */ + String LOWER_TRAILING_CORNER = "LOWER_TRAILING_CORNER"; + + /** + * UPPER_LEADING_CORNER + */ + String UPPER_LEADING_CORNER = "UPPER_LEADING_CORNER"; + + /** + * UPPER_TRAILING_CORNER + */ + String UPPER_TRAILING_CORNER = "UPPER_TRAILING_CORNER"; + + /** + * VERTICAL_SCROLLBAR_POLICY + */ + String VERTICAL_SCROLLBAR_POLICY = "VERTICAL_SCROLLBAR_POLICY"; + + /** + * HORIZONTAL_SCROLLBAR_POLICY + */ + String HORIZONTAL_SCROLLBAR_POLICY = "HORIZONTAL_SCROLLBAR_POLICY"; + + /** + * VERTICAL_SCROLLBAR_AS_NEEDED + */ + int VERTICAL_SCROLLBAR_AS_NEEDED = 20; + + /** + * VERTICAL_SCROLLBAR_NEVER + */ + int VERTICAL_SCROLLBAR_NEVER = 21; + + /** + * VERTICAL_SCROLLBAR_ALWAYS + */ + int VERTICAL_SCROLLBAR_ALWAYS = 22; + + /** + * HORIZONTAL_SCROLLBAR_AS_NEEDED + */ + int HORIZONTAL_SCROLLBAR_AS_NEEDED = 30; + + /** + * HORIZONTAL_SCROLLBAR_NEVER + */ + int HORIZONTAL_SCROLLBAR_NEVER = 31; + + /** + * HORIZONTAL_SCROLLBAR_ALWAYS + */ + int HORIZONTAL_SCROLLBAR_ALWAYS = 32; +} diff --git a/libjava/classpath/javax/swing/ScrollPaneLayout.java b/libjava/classpath/javax/swing/ScrollPaneLayout.java new file mode 100644 index 0000000..75a6f9a --- /dev/null +++ b/libjava/classpath/javax/swing/ScrollPaneLayout.java @@ -0,0 +1,484 @@ +/* ScrollPaneLayout.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +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 + * @version 1.0 + */ +public class ScrollPaneLayout + implements LayoutManager, ScrollPaneConstants, Serializable +{ + private static final long serialVersionUID = -4480022884523193743L; + + public static class UIResource extends ScrollPaneLayout + implements javax.swing.plaf.UIResource { + public UIResource() { + } + } + + protected JViewport viewport; + protected JScrollBar vsb; + protected JScrollBar hsb; + protected JViewport rowHead; + protected JViewport colHead; + protected Component lowerLeft; + protected Component lowerRight; + protected Component upperLeft; + protected Component upperRight; + protected int vsbPolicy; + protected int hsbPolicy; + + public ScrollPaneLayout() { + + } + + public void syncWithScrollPane(JScrollPane scrollPane) { + viewport = scrollPane.getViewport(); + rowHead = scrollPane.getRowHeader(); + colHead = scrollPane.getColumnHeader(); + vsb = scrollPane.getVerticalScrollBar(); + hsb = scrollPane.getHorizontalScrollBar(); + vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); + hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); + lowerLeft = scrollPane.getCorner(LOWER_LEFT_CORNER); + lowerRight = scrollPane.getCorner(LOWER_RIGHT_CORNER); + upperLeft = scrollPane.getCorner(UPPER_LEFT_CORNER); + upperRight = scrollPane.getCorner(UPPER_RIGHT_CORNER); + } + + protected Component addSingletonComponent(Component oldComponent, + Component newComponent) { + return null; + } + + public void addLayoutComponent(String key, Component component) + { + if (key == VIEWPORT) + viewport = (JViewport) component; + else if (key == VERTICAL_SCROLLBAR) + vsb = (JScrollBar) component; + else if (key == HORIZONTAL_SCROLLBAR) + hsb = (JScrollBar) component; + else if (key == ROW_HEADER) + rowHead = (JViewport) component; + else if (key == COLUMN_HEADER) + colHead = (JViewport) component; + else if (key == LOWER_RIGHT_CORNER) + lowerRight = component; + else if (key == UPPER_RIGHT_CORNER) + upperRight = component; + else if (key == LOWER_LEFT_CORNER) + lowerLeft = component; + else if (key == UPPER_LEFT_CORNER) + upperLeft = component; + } + + public void removeLayoutComponent(Component component) { + if (component == viewport) + viewport = null; + else if (component == vsb) + vsb = null; + else if (component == hsb) + hsb = null; + else if (component == rowHead) + rowHead = null; + else if (component == colHead) + colHead = null; + else if (component == lowerRight) + lowerRight = null; + else if (component == upperRight) + upperRight = null; + else if (component == lowerLeft) + lowerLeft = null; + else if (component == upperLeft) + upperLeft = null; + } + + public int getVerticalScrollBarPolicy() + { + return vsbPolicy; + } + + public void setVerticalScrollBarPolicy(int policy) + { + vsbPolicy = policy; + } + + public int getHorizontalScrollBarPolicy() + { + return hsbPolicy; + } + + public void setHorizontalScrollBarPolicy(int policy) + { + hsbPolicy = policy; + } + + public JViewport getViewport() + { + return viewport; + } + + public JScrollBar getHorizontalScrollBar() + { + return hsb; + } + + public JScrollBar getVerticalScrollBar() + { + return vsb; + } + + public JViewport getRowHeader() + { + return rowHead; + } + + public JViewport getColumnHeader() + { + return colHead; + } + + public Component getCorner(String key) + { + if (key == LOWER_RIGHT_CORNER) + return lowerRight; + else if (key == UPPER_RIGHT_CORNER) + return upperRight; + else if (key == LOWER_LEFT_CORNER) + return lowerLeft; + else if (key == UPPER_LEFT_CORNER) + return upperLeft; + 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); + } + } + + 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); + } + } + + /** + * + * +----+--------------------+----+ y1 + * | c1 | column header | c2 | + * +----+--------------------+----+ y2 + * | r | | v | + * | o | | | + * | w | | s | + * | | | r | + * | h | | o | + * | e | viewport | l | + * | a | | l | + * | d | | b | + * | e | | a | + * | r | | r | + * +----+--------------------+----+ y3 + * | c3 | h scrollbar | c4 | + * +----+--------------------+----+ y4 + * x1 x2 x3 x4 + * + */ + public void layoutContainer(Container parent) + { + if (parent instanceof JScrollPane) + { + 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)); + + } + } + } + + /** + * Returns the bounds of the border around a ScrollPane's viewport. + * + * @param scrollPane the ScrollPane for which's viewport the border + * is requested + * + * @deprecated As of Swing 1.1 replaced by + * {@link javax.swing.JScrollPane#getViewportBorderBounds}. + */ + public Rectangle getViewportBorderBounds(JScrollPane scrollPane) { + return null; + } + + +} diff --git a/libjava/classpath/javax/swing/Scrollable.java b/libjava/classpath/javax/swing/Scrollable.java new file mode 100644 index 0000000..1973219 --- /dev/null +++ b/libjava/classpath/javax/swing/Scrollable.java @@ -0,0 +1,56 @@ +/* Scrollable.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Dimension; +import java.awt.Rectangle; + +/** + * Defines the method that a component should implement to behave nicely + * in {@link JScrollPane}s. Note that this is not required for a component + * to be used in a JScrollPane, but can highly improve the + * user experience when scrolling the component. + */ +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(); +} diff --git a/libjava/classpath/javax/swing/SingleSelectionModel.java b/libjava/classpath/javax/swing/SingleSelectionModel.java new file mode 100644 index 0000000..b5380c8 --- /dev/null +++ b/libjava/classpath/javax/swing/SingleSelectionModel.java @@ -0,0 +1,91 @@ +/* SingleSelectionModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import javax.swing.event.ChangeListener; + +/** + * A data model that is used in components that support at most one + * selected element, like {@link JTabbedPane}, {@link JMenu} and + * {@link JPopupMenu}. + * + * @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 diff --git a/libjava/classpath/javax/swing/SizeRequirements.java b/libjava/classpath/javax/swing/SizeRequirements.java new file mode 100644 index 0000000..430aeed --- /dev/null +++ b/libjava/classpath/javax/swing/SizeRequirements.java @@ -0,0 +1,329 @@ +/* SizeRequirements.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.Serializable; + +/** + * This class calculates information about the size and position requirements + * of components. + * + * Two types of layout are supported: + * + * + * @author Andrew Selkirk + * @author Roman Kennke (roman@kennke.org) + */ +public class SizeRequirements implements Serializable +{ + /** + * The serialVersionUID. + */ + private static final long serialVersionUID = 9217749429906736553L; + + /** + * The minimum reasonable width or height of a component. + */ + public int minimum; + + /** + * The preferred width or height of a component. + */ + public int preferred; + + /** + * The maximum reasonable width or height of a component. + */ + public int maximum; + + /** + * The horizontal or vertical alignment of a component. + */ + public float alignment; + + /** + * Creates a SizeRequirements object with minimum, preferred and + * maximum size set to zero, and an alignment value of 0.5. + */ + public SizeRequirements() + { + this (0, 0, 0, 0.5F); + } + + /** + * Creates a SizeRequirements object with the specified minimum, + * preferred, maximum and alignment values. + * + * @param min the minimum reasonable size of the component + * @param pref the preferred size of the component + * @param max the maximum size of the component + * @param align the alignment of the component + */ + public SizeRequirements(int min, int pref, int max, float align) + { + minimum = min; + preferred = pref; + maximum = max; + alignment = align; + } + + /** + * Returns a String representation of this SizeRequirements object, + * containing information about the minimum, preferred, maximum and + * alignment value. + * + * @return a String representation of this SizeRequirements object + */ + public String toString() + { + return null; // TODO + } + + /** + * Calculates how much space is nessecary to place a set of components + * end-to-end. The size requirements of the components is specified + * in children. + * + * @param children the SizeRequirements of each of the components + * + * @return the SizeRequirements that describe how much space is needed + * to place the components end-to-end + */ + public static SizeRequirements + getTiledSizeRequirements(SizeRequirements[] children) + { + SizeRequirements result = new SizeRequirements(); + for (int i = 0; i < children.length; i++) + { + result.minimum += children[i].minimum; + result.preferred += children[i].preferred; + result.maximum += children[i].maximum; + } + return result; + } + + /** + * Calculates how much space is nessecary to place a set of components + * aligned according to their alignment value. + * The size requirements of the components is specified in + * children. + * + * @param children the SizeRequirements of each of the components + * + * @return the SizeRequirements that describe how much space is needed + * to place the components aligned + */ + public static SizeRequirements + getAlignedSizeRequirements(SizeRequirements[] children) + { + return null; // TODO + } + + /** + * Calculate the offsets and spans of the components, when they should + * be placed end-to-end. + * + * You must specify the amount of allocated space in + * allocated, the total size requirements of the set of + * components in total (this can be calculated using + * {@link #getTiledSizeRequirements} and the size requirements of the + * components in children. + * + * The calculated offset and span values for each component are then + * stored in the arrays offsets and spans. + * + * The components are placed in the forward direction, beginning with + * an offset of 0. + * + * @param allocated the amount of allocated space + * @param total the total size requirements of the components + * @param children the size requirement of each component + * @param offsets will hold the offset values for each component + * @param spans will hold the span values for each component + */ + public static void calculateTiledPositions(int allocated, + SizeRequirements total, + SizeRequirements[] children, + int[] offsets, int[] spans) + { + calculateTiledPositions(allocated, total, children, offsets, spans, true); + } + + /** + * Calculate the offsets and spans of the components, when they should + * be placed end-to-end. + * + * You must specify the amount of allocated space in + * allocated, the total size requirements of the set of + * components in total (this can be calculated using + * {@link #getTiledSizeRequirements} and the size requirements of the + * components in children. + * + * The calculated offset and span values for each component are then + * stored in the arrays offsets and spans. + * + * Depending on the value of forward the components are + * placed in the forward direction (left-right or top-bottom), where + * the offsets begin with 0, or in the reverse direction + * (right-left or bottom-top). + * + * @param allocated the amount of allocated space + * @param total the total size requirements of the components + * @param children the size requirement of each component + * @param offsets will hold the offset values for each component + * @param spans will hold the span values for each component + * @param forward whether the components should be placed in the forward + * direction (left-right or top-bottom) or reverse direction + * (right-left or bottom-top) + */ + public static void calculateTiledPositions(int allocated, + SizeRequirements total, + SizeRequirements[] children, + int[] offsets, int[] spans, + boolean forward) + { + if (forward) + { + int offset = 0; + for (int i = 0; i < children.length; i++) + { + offsets[i] = offset; + spans[i] = children[i].preferred; + offset += children[i].preferred; + } + } + else + { + int offset = allocated; + for (int i = 0; i < children.length; i++) + { + offset -= children[i].preferred; + offsets[i] = offset; + spans[i] = children[i].preferred; + } + } + } + + /** + * Calculate the offsets and spans of the components, when they should + * be placed end-to-end. + * + * You must specify the amount of allocated space in + * allocated, the total size requirements of the set of + * components in total (this can be calculated using + * {@link #getTiledSizeRequirements} and the size requirements of the + * components in children. + * + * The calculated offset and span values for each component are then + * stored in the arrays offsets and spans. + * + * The components are tiled in the forward direction, beginning with + * an offset of 0. + * + * @param allocated the amount of allocated space + * @param total the total size requirements of the components + * @param children the size requirement of each component + * @param offsets will hold the offset values for each component + * @param spans will hold the span values for each component + */ + public static void calculateAlignedPositions(int allocated, + SizeRequirements total, + SizeRequirements[] children, + int[] offsets, int[] spans) + { + calculateTiledPositions(allocated, total, children, offsets, spans, true); + } + + /** + * Calculate the offsets and spans of the components, when they should + * be placed end-to-end. + * + * You must specify the amount of allocated space in + * allocated, the total size requirements of the set of + * components in total (this can be calculated using + * {@link #getTiledSizeRequirements} and the size requirements of the + * components in children. + * + * The calculated offset and span values for each component are then + * stored in the arrays offsets and spans. + * + * Depending on the value of forward the components are + * placed in the forward direction (left-right or top-bottom), where + * the offsets begin with 0, or in the reverse direction + * (right-left or bottom-top). + * + * @param allocated the amount of allocated space + * @param total the total size requirements of the components + * @param children the size requirement of each component + * @param offsets will hold the offset values for each component + * @param spans will hold the span values for each component + * @param forward whether the components should be placed in the forward + * direction (left-right or top-bottom) or reverse direction + * (right-left or bottom-top) + */ + public static void calculateAlignedPositions(int allocated, + SizeRequirements total, + SizeRequirements[] children, + int[] offset, int[] spans, + boolean forward) + { + // TODO + } + + /** + * Returns an array of new preferred sizes for the children based on + * delta. delta specifies a change in the + * allocated space. The sizes of the children will be shortened or + * lengthened to accomodate the new allocation. + * + * @param delta the change of the size of the total allocation for + * the components + * @param children the size requirements of each component + * + * @return the new preferred sizes for each component + */ + public static int[] adjustSizes(int delta, SizeRequirements[] children) + { + return null; // TODO + } +} diff --git a/libjava/classpath/javax/swing/SizeSequence.java b/libjava/classpath/javax/swing/SizeSequence.java new file mode 100644 index 0000000..cf6e5f0 --- /dev/null +++ b/libjava/classpath/javax/swing/SizeSequence.java @@ -0,0 +1,249 @@ +/* SizeSequence.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * SizeSequence + * @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 diff --git a/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java b/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java new file mode 100644 index 0000000..48f864b --- /dev/null +++ b/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java @@ -0,0 +1,333 @@ +/* SortingFocusTraversalPolicy.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.awt.Component; +import java.awt.Container; +import java.util.Comparator; +import java.util.Iterator; +import java.util.TreeSet; + +/** + * @author Graydon Hoare + * @author Michael Koch + * + * @since 1.4 + */ +public class SortingFocusTraversalPolicy + extends InternalFrameFocusTraversalPolicy +{ + /** + * The comparator used to sort elements in the focus traversal cycle + * managed by this class. + */ + Comparator comparator; + + /** + *

Whether or not to perform an "implicit DownCycle" when selecting + * successor components within a focus cycle.

+ * + *

When this is true, requesting the "next" component following a + * component which is a focus cycle root (and, necessarily, a container) + * will enter the focus cycle root of that container, and return its + * default focus.

+ * + *

When this property is false, requesting the "next" component will + * simply advance within the containing focus cycle, subject to the + * {@link #comparator} order and the {@link #accept} judgment.

+ * + * @see #getNextFocusableComponent + */ + boolean implicitDownCycleTraversal = true; + + /** + * Creates a new SortingFocusTraversalPolicy with no + * comparator set. + */ + protected SortingFocusTraversalPolicy() + { + // Do nothing here. + } + + /** + * Creates a new SortingFocusTraversalPolicy with the given + * comparator set. + * + * @param the comparator to set + */ + public SortingFocusTraversalPolicy(Comparator comparator) + { + this.comparator = comparator; + } + + /** + * Decide whether a component is an acceptable focus owner. + * + * @param comp The component which is a candidate for focus ownership. + * + * @return true if the component is focusable, displayable, visible, and + * enabled; otherwise false + */ + protected boolean accept(Component comp) + { + return (comp.isVisible() + && comp.isDisplayable() + && comp.isEnabled() + && comp.isFocusable()); + } + + /** + * Get the current value of the {@link #comparator} property. + * + * @return the current value of the property + * + * @see #setComparator + */ + protected Comparator getComparator() + { + return comparator; + } + + /** + * Set the current value of the {@link #comparator} property. + * + * @param comparator the new value of the property + * + * @see #getComparator + */ + protected void setComparator(Comparator comparator) + { + this.comparator = comparator; + } + + private TreeSet getSortedCycle(Container root, TreeSet set) + { + if (set == null) + set = (getComparator() == null + ? new TreeSet() + : new TreeSet(getComparator())); + + if (root != null) + { + Component[] comps = root.getComponents(); + for (int i = 0; i < comps.length; ++i) + { + Component c = comps[i]; + if (accept(c)) + set.add(c); + if (c instanceof Container) + getSortedCycle((Container) c, set); + } + } + return set; + } + + /** + * Return the component which follows the specified component in this + * focus cycle, relative to the order imposed by {@link + * #comparator}. Candidate components are only considered if they are + * accepted by the {@link #accept} method. + * + * If {@link #getImplicitDownCycleTraversal} is true and the + * comp is a focus cycle root, an "implicit DownCycle" + * occurs and the method returns the + * getDefaultComponent(comp). + * + * @param root the focus cycle root to search for a successor within + * @param comp the component to search for the successor of + * + * @return the component following the specified component under + * the specified root, or null if no such component is found + * + * @throws IllegalArgumentException if either argument is null, or + * if the root is not a focus cycle root of the component + */ + public Component getComponentAfter(Container root, + Component comp) + { + if (comp == null || root == null || !comp.isFocusCycleRoot(root)) + throw new IllegalArgumentException(); + + if (getImplicitDownCycleTraversal() + && comp instanceof Container + && ((Container)comp).isFocusCycleRoot()) + { + return getDefaultComponent((Container) comp); + } + + TreeSet set = getSortedCycle(root, null); + Iterator i = set.iterator(); + while (i.hasNext()) + { + Component c = (Component) i.next(); + if (c != null && c.equals(comp)) + { + if (i.hasNext()) + return (Component) i.next(); + break; + } + } + return null; + } + + + /** + * Return the component which precedes the specified component in this + * focus cycle, relative to the order imposed by {@link + * #comparator}. Candidate components are only considered if they are + * accepted by the {@link #accept} method. + * + * @param root the focus cycle root to search for a predecessor within + * @param comp the component to search for the predecessor of + * + * @return the component preceding the specified component under the + * specified root, or null if no such component is found + * + * @throws IllegalArgumentException if either argument is null, or + * if the root is not a focus cycle root of the component + */ + public Component getComponentBefore(Container root, + Component comp) + { + if (comp == null || root == null || !comp.isFocusCycleRoot(root)) + throw new IllegalArgumentException(); + TreeSet set = getSortedCycle(root, null); + Iterator i = set.iterator(); + Component prev = null; + while (i.hasNext()) + { + Component c = (Component) i.next(); + if (c != null && c.equals(comp)) + break; + prev = c; + } + return prev; + } + + /** + * Return the default component of root, which is by default + * the same as the first component, returned by {@link + * #getFirstComponent}. + * + * @param root the focus cycle root to return the default component of + * + * @return the default focus component for root + * + * @throws IllegalArgumentException if root is null + */ + public Component getDefaultComponent(Container root) + { + return getFirstComponent(root); + } + + /** + * Return the first focusable component of the focus cycle root + * comp under the ordering imposed by the {@link + * #comparator} property. Candidate components are only considered if + * they are accepted by the {@link #accept} method. + * + * @param root the focus cycle root to search for the first component of + * + * @return the first component under root, or null if + * no components are found. + * + * @throws IllegalArgumentException if root is null + */ + public Component getFirstComponent(Container root) + { + if (root == null) + throw new IllegalArgumentException(); + TreeSet set = getSortedCycle(root, null); + Iterator i = set.iterator(); + if (i.hasNext()) + return (Component) i.next(); + return null; + } + + /** + * Return the last focusable component of the focus cycle root + * comp under the ordering imposed by the {@link + * #comparator} property. Candidate components are only considered if + * they are accepted by the {@link #accept} method. + * + * @param root the focus cycle root to search for the last component of + * + * @return the last component under root, or null if + * no components are found. + * + * @throws IllegalArgumentException if root is null + */ + public Component getLastComponent(Container root) + { + if (root == null) + throw new IllegalArgumentException(); + TreeSet set = getSortedCycle(root, null); + Iterator i = set.iterator(); + Component last = null; + while (i.hasNext()) + last = (Component) i.next(); + return last; + } + + /** + * Return the current value of the {@link implicitDownCycleTraversal} + * property. + * + * @return the current value of the property + * + * @see setImplicitDownCycleTraversal + */ + public boolean getImplicitDownCycleTraversal() + { + return implicitDownCycleTraversal; + } + + /** + * Set the current value of the {@link implicitDownCycleTraversal} + * property. + * + * @param down the new value of the property + * + * @see getImplicitDownCycleTraversal + */ + public void setImplicitDownCycleTraversal(boolean down) + { + implicitDownCycleTraversal = down; + } +} diff --git a/libjava/classpath/javax/swing/SpinnerDateModel.java b/libjava/classpath/javax/swing/SpinnerDateModel.java new file mode 100644 index 0000000..c0de7d5 --- /dev/null +++ b/libjava/classpath/javax/swing/SpinnerDateModel.java @@ -0,0 +1,237 @@ +/* SpinnerDateModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; + +/** + * SpinnerDateModel + * + * Implements a SpinnerModel for dates, rotating a calendar field such as + * month, year, day, week, hour, minute. + * + * @author Sven de Marothy + * @version 0.1 (first implementation) + */ +public class SpinnerDateModel extends AbstractSpinnerModel + implements Serializable +{ + private Calendar date; + private Comparable start; + private Comparable end; + private int calendarField; + + /** + * For compatability with Sun's JDK + * FIXME: Which fields should be serialized? + */ + private static final long serialVersionUID = -4802518107105940612L; + + /** + * Constructs a SpinnerDateModel using the current date, + * no start or end limit, and Calendar.DAY_OF_MONTH as the calendar field. + */ + public SpinnerDateModel() + { + this(new Date(), null, null, Calendar.DAY_OF_MONTH); + } + + /** + * Constructs a SpinnerDateModel which spins a given calendar field, + * using a given date and start and end date limits. + * @param value - the initial Date value + * @param start - start limit, as a Date object, or null + * for no lower limit. + * @param end - end limit, or null for no upper limit. + * @param calendarField - the Calendar field to spin, + * (Calendar.ZONE_OFFSET and Calendar.DST_OFFSET are invalid) + */ + public SpinnerDateModel(Date value, Comparable start, Comparable end, + int calendarField) + { + date = Calendar.getInstance(); + date.setTime(value); + this.start = start; + this.end = end; + setCalendarField(calendarField); + } + + /** + * Returns the value of the Calendar field to spin. + */ + public int getCalendarField() + { + return calendarField; + } + + /** + * Returns the current date in the sequence. + * @return a Date object. + */ + public Date getDate() + { + return date.getTime(); + } + + /** + * Returns the starting limit of the SpinnerModel. + * @return a Date object, or null if there is no limit. + */ + public Comparable getStart() + { + return start; + } + + /** + * Returns the end limit of the SpinnerModel. + * @return a Date object, or null if there is no limit. + */ + public Comparable getEnd() + { + return end; + } + + /** + * Returns the current date in the sequence, + * this method returns the same as getDate(). + * @return a Date object. + */ + public Object getValue() + { + return date.getTime(); + } + + /** + * Returns the next date in the sequence, or null if the + * next date is equal to or past the end limit. + * @return a Date object, or null. + */ + public Object getNextValue() + { + Calendar nextCal = Calendar.getInstance(); + nextCal.setTime(date.getTime()); + nextCal.roll(calendarField, true); + Date nextDate = nextCal.getTime(); + if (end != null) + if (end.compareTo(nextDate) < 0) + return null; + return nextDate; + } + + /** + * Returns the previous date in the sequence, or null if the + * next date is equal to or past the end limit. + * @return a Date object, or null. + */ + public Object getPreviousValue() + { + Calendar prevCal = Calendar.getInstance(); + prevCal.setTime(date.getTime()); + prevCal.roll(calendarField, false); + Date prevDate = prevCal.getTime(); + if (end != null) + if (end.compareTo(prevDate) > 0) + return null; + return prevDate; + } + + /** + * Sets the date field to change. It must be a valid Calendar field, + * excluding Calendar.ZONE_OFFSET and Calendar.DST_OFFSET. + * @param calendarField - the calendar field to set. + */ + public void setCalendarField(int calendarField) + { + if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT + || calendarField == Calendar.ZONE_OFFSET + || calendarField == Calendar.DST_OFFSET) + throw new IllegalArgumentException("Illegal calendarField"); + + if (this.calendarField != calendarField) + { + this.calendarField = calendarField; + fireStateChanged(); + } + } + + /** + * Sets the starting date limit for the sequence. + * + * @param start - a Date object of the limit date, + * or null for no limit. + */ + public void setStart(Comparable start) + { + if (this.start != start) + { + this.start = start; + fireStateChanged(); + } + } + + /** + * Sets the end date limit for the sequence. + * + * @param end - a Date object of the limit date, + * or null for no limit. + */ + public void setEnd(Comparable end) + { + if (this.end != end) + { + this.end = end; + fireStateChanged(); + } + } + + /** + * Sets the current date in the sequence. + * + * @param value - a Date object. + */ + public void setValue(Object value) + { + if (! (value instanceof Date) || value == null) + throw new IllegalArgumentException("Value not a date."); + date.setTime((Date) value); + fireStateChanged(); + } +} diff --git a/libjava/classpath/javax/swing/SpinnerListModel.java b/libjava/classpath/javax/swing/SpinnerListModel.java new file mode 100644 index 0000000..a0dc4d1 --- /dev/null +++ b/libjava/classpath/javax/swing/SpinnerListModel.java @@ -0,0 +1,296 @@ +/* SpinnerListModel.java -- A spinner model backed by a list or an array. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * An implementation of SpinnerModel which uses the values + * contained within a list or an array. The backing list or array is + * only stored as a reference within the class. As a result, changes + * made elsewhere to the members of the list or array are reflected by + * this model. + *

+ * + * The model itself inherits a list of ChangeListeners from + * AbstractSpinnerModel. As this code is unaware of changes + * made to the backing list or array, it is the responsibility of the + * application using the model to invoke fireStateChanged(), + * in order to notify any ChangeListeners, when the list or array + * changes. The model handles notification when the reference itself + * is changed via setList() or when the current value is + * set directly using setValue(). + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see SpinnerModel + * @see AbstractSpinnerModel + * @see JSpinner + * @since 1.4 + */ + +public class SpinnerListModel + extends AbstractSpinnerModel + implements Serializable +{ + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 3358804052191994516L; + + /** + * The backing list for this model. + */ + private List list; + + /** + * The current index in the list. + */ + private transient int index; + + /** + * Constructs a default SpinnerListModel. This + * is a model backed by a list containing only the single + * String 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); + } + + /** + * Constructs a SpinnerListModel using the supplied list. + * The model maintains a reference to this list, and returns + * consecutive elements in response to calls to getNextValue(). + * The initial value is that at position 0, so an initial call + * to getValue() returns the same as list.get(0). + * + * @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 SpinnerListModel using the supplied array. + * The model stores a reference to the wrapper list returned by + * Arrays.asList(). 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 getNextValue(). The initial + * value returned by getValue() is the same as + * array[0]. + * + * @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)); + } + + /** + * 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 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; + } + } + + /** + * 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 getNextValue() + * or getPreviousValue(). + * + * @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 + * ChangeEvent 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; + } + + /** + * 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, getNextValue() and + * getPreviousValue() 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/SpinnerModel.java b/libjava/classpath/javax/swing/SpinnerModel.java new file mode 100644 index 0000000..4ad962b --- /dev/null +++ b/libjava/classpath/javax/swing/SpinnerModel.java @@ -0,0 +1,111 @@ +/* SpinnerModel.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import javax.swing.event.ChangeListener; + +/** + * The data model that is used in {@link JSpinner}s. + * + * @since 1.4 + */ +public interface SpinnerModel +{ + /** + * Sets the current value of the model to that specified. + * Implementations can choose to refuse to accept the value + * and throw an exception instead. For example, a date model + * may throw invalid dates, or a list model may throw out + * values which don't exist in the underlying list. Models + * may also throw out unusual values, such as null. The decision + * is left to the discretion of the implementator. If the + * operation succeeds, the implementation should also notify + * any registered ChangeListeners. + * + * @param value The new value of the model. + * @throws IllegalArgumentException if the model does not accept + * the given value. + */ + void setValue(Object value); + + /** + * Returns the current value of the model. + * + * @return The current value. + */ + Object getValue(); + + /** + * Returns the next value from the model. If the model is bounded, + * this method may return null when the upper bound is met. + * The current value is not changed. + * + * @return The next value, or null if there are no more values + * to retrieve. + */ + Object getNextValue(); + + /** + * Returns the previous value from the model. If the model is + * bounded, this method may return null when the lower bound is + * met. The current value is not changed. + * + * @return The previous value, or null if there are no more + * values to retrieve. + */ + Object getPreviousValue(); + + /** + * Adds a ChangeListener to the list of registered + * listeners. Each listener is notified when the current value + * is changed. + * + * @param listener The new listener to register. + */ + void addChangeListener(ChangeListener listener); + + /** + * Removes a given ChangeListener from the list + * of registered listeners. + * + * @param listener The listener to remove. + */ + void removeChangeListener(ChangeListener listener); + +} diff --git a/libjava/classpath/javax/swing/SpinnerNumberModel.java b/libjava/classpath/javax/swing/SpinnerNumberModel.java new file mode 100644 index 0000000..2274c9e --- /dev/null +++ b/libjava/classpath/javax/swing/SpinnerNumberModel.java @@ -0,0 +1,298 @@ +/* SpinnerNumberModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.io.Serializable; + +/** + * SpinnerNumberModel + * + * @author Ka-Hing Cheung + * @version 1.0 + */ +public class SpinnerNumberModel extends AbstractSpinnerModel + implements Serializable +{ + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 7279176385485777821L; + + /** DOCUMENT ME! */ + private Number value; + + /** DOCUMENT ME! */ + private Comparable minimum; + + /** DOCUMENT ME! */ + private Comparable maximum; + + /** DOCUMENT ME! */ + private Number stepSize; + + /** + * Creates a SpinnerNumberModel with initial value 0, step 1, + * and no maximum nor minimum. + */ + public SpinnerNumberModel() + { + this(new Integer(0), null, null, new Integer(1)); + } + + /** + * Creates a SpinnerNumberModel with double precision + * + * @param value the initial value + * @param minimum the minimum value + * @param maximum the maximum value + * @param stepSize the step size + * @throws IllegalArgumentException if minimum <= value <= maximum does not + * hold + */ + public SpinnerNumberModel(double value, double minimum, double maximum, + double stepSize) + { + this(new Double(value), new Double(minimum), new Double(maximum), + new Double(stepSize)); + } + + /** + * Creates a SpinnerNumberModel with integer precision + * + * @param value the initial value + * @param minimum the minimum value + * @param maximum the maximum value + * @param stepSize the step size + * @throws IllegalArgumentException if minimum <= value <= maximum does not + * hold + */ + public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize) + { + this(new Integer(value), new Integer(minimum), new Integer(maximum), + new Integer(stepSize)); + } + + /** + * Creates a SpinnerNumberModel with Numbers and + * Comparables. + * + * @param value the initial value + * @param minimum the minimum value, if null there's no minimum + * @param maximum the maximum value, if null there's no maximum + * @param stepSize the step size + * + * @throws IllegalArgumentException if minimum <= value <= maximum + * does not hold + */ + public SpinnerNumberModel(Number value, Comparable minimum, + Comparable maximum, Number stepSize) + { + if (stepSize == null) + throw new IllegalArgumentException("stepSize may not be null"); + if (value == null) + throw new IllegalArgumentException("value may not be null"); + if (minimum != null) + { + if (minimum.compareTo(value) > 0) + throw new IllegalArgumentException("minimum is not <= value"); + } + else + minimum = new Comparable() + { + public int compareTo(Object obj) + { + return -1; + } + }; + + + if (maximum != null) + { + if (maximum.compareTo(value) < 0) + throw new IllegalArgumentException("maximum is not >= value"); + } + else + maximum = new Comparable() + { + public int compareTo(Object obj) + { + return 1; + } + }; + + + this.value = value; + this.stepSize = stepSize; + this.minimum = minimum; + this.maximum = maximum; + } + + /** + * Sets the new value and fire a change event + * + * @param value the new value + * + * @throws IllegalArgumentException if minimum <= value <= maximum + * does not hold + */ + public void setValue(Object value) + { + if (! (value instanceof Number)) + throw new IllegalArgumentException("value must be a Number"); + + this.value = (Number) value; + fireStateChanged(); + } + + /** + * Gets the current value + * + * @return the current value + */ + public Object getValue() + { + return value; + } + + /** + * Gets the next value without changing the current value, or null if the + * current value is maximum. + * + * @return the next value + */ + public Object getNextValue() + { + Number num; + + if (value instanceof Double) + num = new Double(value.doubleValue() + stepSize.doubleValue()); + else if (value instanceof Float) + num = new Double(value.floatValue() + stepSize.floatValue()); + else if (value instanceof Long) + num = new Long(value.longValue() + stepSize.longValue()); + else if (value instanceof Integer) + num = new Integer(value.intValue() + stepSize.intValue()); + else if (value instanceof Short) + num = new Short((short) (value.shortValue() + stepSize.shortValue())); + else + num = new Byte((byte) (value.byteValue() + stepSize.byteValue())); + + return maximum.compareTo(num) >= 0 ? num : null; + } + + /** + * Gets the previous value without changing the current value, or null if + * the current value is minimum. + * + * @return the previous value + */ + public Object getPreviousValue() + { + Number num; + + if (value instanceof Double) + num = new Double(value.doubleValue() - stepSize.doubleValue()); + else if (value instanceof Float) + num = new Double(value.floatValue() - stepSize.floatValue()); + else if (value instanceof Long) + num = new Long(value.longValue() - stepSize.longValue()); + else if (value instanceof Integer) + num = new Integer(value.intValue() - stepSize.intValue()); + else if (value instanceof Short) + num = new Short((short) (value.shortValue() - stepSize.shortValue())); + else + num = new Byte((byte) (value.byteValue() - stepSize.byteValue())); + + return minimum.compareTo(num) <= 0 ? num : null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getNumber() + { + return value; + } + + public Comparable getMinimum() + { + return minimum; + } + + public void setMinimum(Comparable newMinimum) + { + if (minimum != newMinimum) + { + minimum = newMinimum; + fireStateChanged(); + } + } + + public Comparable getMaximum() + { + return maximum; + } + + public void setMaximum(Comparable newMaximum) + { + if (maximum != newMaximum) + { + maximum = newMaximum; + fireStateChanged(); + } + } + + public Number getStepSize() + { + return stepSize; + } + + public void setStepSize(Number newStepSize) + { + if (newStepSize == null) + throw new IllegalArgumentException(); + + if (stepSize != newStepSize) + { + stepSize = newStepSize; + fireStateChanged(); + } + } +} diff --git a/libjava/classpath/javax/swing/Spring.java b/libjava/classpath/javax/swing/Spring.java new file mode 100644 index 0000000..4255e86 --- /dev/null +++ b/libjava/classpath/javax/swing/Spring.java @@ -0,0 +1,580 @@ +/* Spring.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * Calculates the space between component edges, that are layed out by + * {@link SpringLayout}. + *

+ * A Spring defines a minimum, preferred and maximum distance for each edge + * (north, east, south, west) of a component. + *

+ * However, springs are not static, their actual values are computed at + * runtime. That means, if a Spring C is defined as the sum of Spring A and + * Spring B, then the values (min, pref and max) are not calculated at + * creation of Spring C, but instead always when {@link #getValue} is + * called. So, when Spring A or Spring B changes, this is reflected in + * Spring C. + * + * @author Roman Kennke (roman@ontographics.com) + */ +public abstract class Spring +{ + + /** Indicates a not-set value. **/ + public static final int UNSET = -2147483648; + + /** + * Creates a new Spring object. This constructor is used by the static + * methods which create Springs. + */ + protected Spring() + { + } + + /** + * Creates a Spring which min, pref and max values are all the same. + * These kind of Springs are 'struts'. + * + * @param val the constant for min, pref and max values. + * @return a Spring object with constant values for min, pref and max. + */ + public static Spring constant(int val) + { + return new SimpleSpring(val, val, val); + } + + /** Creates a Spring which min, pref and max values are constants. + * @param min the constant for the minimum value. + * @param pref the constant for the preferred value. + * @param max the constant for the maximum value. + * @return a Spring object with constant values for min, pref and max. + */ + public static Spring constant(int min, int pref, int max) + { + return new SimpleSpring(min, pref, max); + } + + /** + * Returns the maximum value of the Spring. + * + * @return the maximum value. + */ + public abstract int getMaximumValue(); + + /** + * Returns the minimum value of this Spring. + * + * @return the minimum value. + */ + public abstract int getMinimumValue(); + + /** + * Return the preferred value of this Spring. + * + * @return the preferred value. + */ + public abstract int getPreferredValue(); + + /** + * Return the actual value of this Spring. + * + * @return the actual value of this Spring. + */ + public abstract int getValue(); + + /** + * Creates and returns a Spring, which always has the maximum values + * min = max(min_s1, min_s2), pref = max(pref_s1, pref_s2), max = + * max(max_s1, max_s2). + * + * @param s1 the first summand of the max Spring. + * @param s2 the second summand of the max Spring. + * @return a Spring which is max(s1, s2). + */ + public static Spring max(Spring s1, Spring s2) + { + return new MaxSpring(s1, s2); + } + + /** + * Creates and returns a Spring, which is always the negation of s. + * min = -min_s, pref = -pref_s, max = -max_pref. + * + * @param s the Spring to be negated. + * @return the negative of s. + */ + public static Spring minus(Spring s) + { + return new MinusSpring(s); + } + + /** + * Sets the actual value. If value is out of the (min, max) + * bounds, then the value is adjusted, so that is inside these bounds. + * + * @param value the value to be set. + */ + public abstract void setValue(int value); + + /** + * Creates and returns a Spring, which is always the sum of s1 and s2. + * min_sum = min_s1 + min_s2, pref_sum = pref_s1 + pref_s2, max_sum = + * max_s1 + max_s2. + * + * @param s1 the 1st summand of the sum Spring. + * @param s2 the 2nd summand of the sum Spring. + * @return a sum which is s1 + s2. + */ + public static Spring sum(Spring s1, Spring s2) + { + return new AddSpring(s1, s2); + } + + /** + * A simple Spring, that holds constant values for min, pref and max. + * + * @author Roman Kennke (roman@ontographics.com) + */ + private static final class SimpleSpring extends Spring + { + + /** The constant value for min. */ + private final int min; + + /** The constant value for pref. */ + private final int pref; + + /** The constant value for max. */ + private final int max; + + /** The actual value of the spring. */ + private int value; + + /** + * Creates a new SimpleSpring object. + * + * @param min the constant minimum value. + * @param pref the constant preferred value. + * @param max the constant maximum value. + */ + public SimpleSpring(int newMin, int newPref, int newMax) + { + min = newMin; + pref = newPref; + max = newMax; + value = Spring.UNSET; + } + + /** + * Returns the maximum value of this Spring. + * + * @return the maximum value. + */ + public int getMaximumValue() + { + return max; + } + + /** + * Returns the minimum value of this Spring. + * + * @return the minimum value. + */ + public int getMinimumValue() + { + return min; + } + + /** + * Returns the preferred value of this Spring. + * + * @return the preferred value. + */ + public int getPreferredValue() + { + return pref; + } + + /** + * Return the actual current value of this Spring. + * + * @return the current value. + */ + public int getValue() + { + + if (value == Spring.UNSET) + { + value = pref; + } + + return value; + } + + /** + * Sets the current value. + * + * @param val the value to be set. + */ + public void setValue(int val) + { + + if (val > max) + { + value = max; + } + else if (val < min) + { + value = min; + } + else + { + value = val; + } + } + + } + + + /** + * A Spring, that is the sum of two other Springs. + * + * @author Roman Kennke (roman@ontographics.com) + */ + private static final class AddSpring extends Spring + { + + /** The springs, that are the 'operands' of this Spring. */ + private final Spring s1; + private final Spring s2; + + /** The current value for this Spring. */ + private int value; + + /** + * Creates a new AddSpring object. + * + * @param s1 the first operand. + * @param s2 the second operand. + */ + protected AddSpring(Spring s1, Spring s2) + { + super(); + this.s1 = s1; + this.s2 = s2; + value = Spring.UNSET; + } + + /** + * Returns the maximum value of this Spring. + * + * @return the maximum value. + */ + public int getMaximumValue() + { + int max1 = s1.getMaximumValue(); + int max2 = s2.getMaximumValue(); + return max1 + max2; + } + + /** + * Return the minimum value of this Spring. + * + * @return the minimum value. + */ + public int getMinimumValue() + { + int min1 = s1.getMinimumValue(); + int min2 = s2.getMinimumValue(); + return min1 + min2; + } + + /** + * Returns the preferred value of this Spring. + * + * @return the preferred value. + */ + public int getPreferredValue() + { + int pref1 = s1.getPreferredValue(); + int pref2 = s2.getPreferredValue(); + return pref1 + pref2; + } + + /** + * Returns the actual current value of this Spring. + * + * @return the current value of this Spring. + */ + public int getValue() + { + if (value == Spring.UNSET) + { + int val1 = s1.getValue(); + int val2 = s2.getValue(); + value = val1 + val2; + } + return value; + } + + /** + * Sets the current value. + * + * @param val the value to be set. + */ + public void setValue(int val) + { + + if (val > getMaximumValue()) + { + value = getMaximumValue(); + } + else if (val < getMinimumValue()) + { + value = getMinimumValue(); + } + else + { + value = val; + } + + } + + } + + + /** + * A Spring that is calculated as the negation of another Spring. + * + * @author Roman Kennke (roman@ontographics.com) + */ + private static final class MinusSpring extends Spring + { + + /** The Spring from which to calculate the negation. */ + private final Spring s; + + /** The current value of this Spring. */ + private int value; + + /** + * Creates a new MinusSpring object. + * @param s the Spring from which to calculate the negation. + */ + protected MinusSpring(Spring s) + { + super(); + this.s = s; + value = Spring.UNSET; + } + + /** Returns the maximum value of this Spring. + * + * @return the maximum value. + */ + public int getMaximumValue() + { + return -s.getMinimumValue(); + } + + /** + * Returns the minimum value of this Spring. + * + * @return the minimum value. + */ + public int getMinimumValue() + { + return -s.getMaximumValue(); + } + + /** + * Returns the preferred value of this Spring. + * + * @return the preferred value. + */ + public int getPreferredValue() + { + return -s.getPreferredValue(); + } + + /** + * Returns the current value of this Spring. + * + * @return the current value. + */ + public int getValue() + { + if (value == Spring.UNSET) + { + value = -s.getValue(); + } + return value; + } + + /** + * Sets the current value. + * + * @param val the value to be set. + */ + public void setValue(int val) + { + + if (val > getMaximumValue()) + { + value = getMaximumValue(); + } + else if (val < getMinimumValue()) + { + value = getMinimumValue(); + } + else + { + value = val; + } + + } + + } + + + /** + * A Spring, that is calculated as the maximum of two Springs. + * + * @author Roman Kennke (roman@ontographics.com) + */ + private static final class MaxSpring extends Spring + { + + /** The two other Springs from which to calculate the maximum. */ + private final Spring s1; + private final Spring s2; + + /** The current value of this Spring. */ + private int value; + + /** + * Creates a new MaxSpring object. + * + * @param s1 the 1st operand. + * @param s2 the 2nd operand. + */ + protected MaxSpring(Spring s1, Spring s2) + { + super(); + this.s1 = s1; + this.s2 = s2; + value = Spring.UNSET; + } + + + /** + * Returns the maximum value of this Spring. + * + * @return the maximum value. + */ + public int getMaximumValue() + { + int max1 = s1.getMaximumValue(); + int max2 = s2.getMaximumValue(); + return Math.max(max1, max2); + } + + /** + * Returns the minimum value of this Spring. + * + * @return the minimum value. + */ + public int getMinimumValue() + { + int min1 = s1.getMinimumValue(); + int min2 = s2.getMinimumValue(); + return Math.max(min1, min2); + } + + /** + * Returns the preferred value of this Spring. + * + * @return the preferred value. + */ + public int getPreferredValue() + { + int pref1 = s1.getPreferredValue(); + int pref2 = s2.getPreferredValue(); + return Math.max(pref1, pref2); + } + + /** + * Returns the actual value of this Spring. + * + * @return the current value. + */ + public int getValue() + { + if (value == Spring.UNSET) + { + int val1 = s1.getValue(); + int val2 = s2.getValue(); + value = Math.max(val1, val2); + } + return value; + } + + /** + * Sets the current value. + * + * @param val the value to be set. + */ + public void setValue(int val) + { + + if (val > getMaximumValue()) + { + value = getMaximumValue(); + } + else if (val < getMinimumValue()) + { + value = getMinimumValue(); + } + else + { + value = val; + } + } + } +} diff --git a/libjava/classpath/javax/swing/SpringLayout.java b/libjava/classpath/javax/swing/SpringLayout.java new file mode 100644 index 0000000..b45edba --- /dev/null +++ b/libjava/classpath/javax/swing/SpringLayout.java @@ -0,0 +1,657 @@ +/* SpringLayout.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager2; +import java.util.HashMap; +import java.util.Map; + +/** + * A very flexible layout manager. Components are laid out by defining the + * relationships between them. The relationships are expressed as + * {@link Spring}s. You can attach a Spring for each edge of a component and + * link it to an edge of a different component. For example, you can say, + * the northern edge of component A should be attached to the southern edge + * of component B, and the space between them should be something between + * x and y pixels, and preferably z pixels. + *

While quite simple, this layout manager can be used to emulate most other + * layout managers, and can also be used to solve some layout problems, which + * would be hard to solve with other layout managers.

+ * + * @author Roman Kennke (roman@ontographics.com) + */ +public class SpringLayout implements LayoutManager2 +{ + + /** The right edge of a component. */ + public static final String EAST = "East"; + + /** The top edge of a component. */ + public static final String NORTH = "North"; + + /** The bottom edge of a component. */ + public static final String SOUTH = "South"; + + /** The left edge of a component. */ + public static final String WEST = "West"; + + /** maps components to their constraints. */ + private Map constraintsMap; + + /** + * The constraints that define the relationships between components. + * Each Constraints object can hold 4 Springs: one for each edge of the + * component. Additionally it can hold Springs for the components width + * and the components height. Since the height and width constraints are + * dependend on the other constraints, a component can be over-constraint. + * In this case (like when all of NORTH, SOUTH and HEIGHT are constraint), + * the values are adjusted, so that the mathematics still hold true. + * + * @author Roman Kennke (roman@ontographics.com) + */ + public static class Constraints + { + + // The constraints for each edge, and width and height. + /** The Spring for the left edge. */ + private Spring x; + + /** The Spring for the upper edge. */ + private Spring y; + + /** The Spring for the height. */ + private Spring height; + + /** The Spring for the width. */ + private Spring width; + + /** The Spring for the right edge. */ + private Spring east; + + /** The Spring for the bottom edge. */ + private Spring south; + + /** + * Creates a new Constraints object. + * There is no constraint set. + */ + public Constraints() + { + x = y = height = width = east = south = null; + } + + /** + * Creates a new Constraints object. + * + * @param x the constraint for the left edge of the component. + * @param y the constraint for the upper edge of the component. + */ + public Constraints(Spring x, Spring y) + { + this.x = x; + this.y = y; + width = height = east = south = null; + } + + /** + * Creates a new Constraints object. + * + * @param x the constraint for the left edge of the component. + * @param y the constraint for the upper edge of the component. + * @param width the constraint for the width of the component. + * @param height the constraint for the height of the component. + */ + public Constraints(Spring x, Spring y, Spring width, Spring height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + east = south = null; + } + + /** + * Returns the constraint for the edge with the edgeName. + * This is expected to be one of + * {@link #EAST}, {@link #WEST}, {@link NORTH} or {@link SOUTH}. + * + * @param edgeName the name of the edge. + * @return the constraint for the specified edge. + */ + public Spring getConstraint(String edgeName) + { + Spring retVal = null; + if (edgeName.equals(SpringLayout.NORTH)) + retVal = y; + else if (edgeName.equals(SpringLayout.WEST)) + retVal = x; + else if (edgeName.equals(SpringLayout.SOUTH)) + { + retVal = south; + if ((retVal == null) && (y != null) && (height != null)) + retVal = Spring.sum(y, height); + } + else if (edgeName.equals(SpringLayout.EAST)) + { + retVal = east; + if ((retVal == null) && (x != null) && (width != null)) + retVal = Spring.sum(x, width); + } + + return retVal; + } + + /** + * Returns the constraint for the height of the component. + * + * @return the height constraint. + */ + public Spring getHeight() + { + Spring retVal = height; + if ((retVal == null) && (y != null) && (south != null)) + { + retVal = Spring.sum(south, Spring.minus(y)); + } + return retVal; + } + + /** + * Returns the constraint for the width of the component. + * + * @return the width constraint. + */ + public Spring getWidth() + { + Spring retVal = width; + if ((retVal == null) && (x != null) && (east != null)) + { + retVal = Spring.sum(east, Spring.minus(x)); + } + return retVal; + } + + /** + * Returns the constraint for the left edge of the component. + * + * @return the left-edge constraint (== WEST). + */ + public Spring getX() + { + Spring retVal = x; + if ((retVal == null) && (width != null) && (east != null)) + { + retVal = Spring.sum(east, Spring.minus(width)); + } + return retVal; + } + + /** + * Returns the constraint for the upper edge of the component. + * + * @return the upper-edge constraint (== NORTH). + */ + public Spring getY() + { + Spring retVal = y; + if ((retVal == null) && (height != null) && (south != null)) + { + retVal = Spring.sum(south, Spring.minus(height)); + } + return retVal; + } + + /** + * Sets a constraint for the specified edge. If this leads to an + * over-constrained situation, the constraints get adjusted, so that + * the mathematics still hold true. + * + * @param edgeName the name of the edge, one of {@link #EAST}, + * {@link #WEST}, {@link NORTH} or {@link SOUTH}. + * @param s the constraint to be set. + */ + public void setConstraint(String edgeName, Spring s) + { + + if (edgeName.equals(SpringLayout.WEST)) + { + x = s; + if ((width != null) && (east != null)) + width = Spring.sum(east, Spring.minus(x)); + } + else if (edgeName.equals(SpringLayout.NORTH)) + { + y = s; + if ((height != null) && (south != null)) + height = Spring.sum(south, Spring.minus(y)); + } + else if (edgeName.equals(SpringLayout.EAST)) + { + east = s; + if ((x != null) && (width != null)) + x = Spring.sum(east, Spring.minus(width)); + } + else if (edgeName.equals(SpringLayout.SOUTH)) + { + south = s; + if ((height != null) && (y != null)) + y = Spring.sum(south, Spring.minus(height)); + } + + } + + /** + * Sets the height-constraint. + * + * @param s the constraint to be set. + */ + public void setHeight(Spring s) + { + height = s; + if ((south != null) && (y != null)) + south = Spring.sum(y, height); + + } + + /** + * Sets the width-constraint. + * + * @param s the constraint to be set. + */ + public void setWidth(Spring s) + { + width = s; + if ((east != null) && (x != null)) + east = Spring.sum(x, width); + + } + + /** + * Sets the WEST-constraint. + * + * @param s the constraint to be set. + */ + public void setX(Spring s) + { + x = s; + if ((width != null) && (east != null)) + width = Spring.sum(east, Spring.minus(x)); + + } + + /** + * Sets the NORTH-constraint. + * + * @param s the constraint to be set. + */ + public void setY(Spring s) + { + y = s; + if ((height != null) && (south != null)) + height = Spring.sum(south, Spring.minus(y)); + + } + } + + /** + * Creates a new SpringLayout. + */ + public SpringLayout() + { + + constraintsMap = new HashMap(); + } + + /** + * Adds a layout component and a constraint object to this layout. + * This method is usually only called by a {@java.awt.Container}s add + * Method. + * + * @param component the component to be added. + * @param constraint the constraint to be set. + */ + public void addLayoutComponent(Component component, Object constraint) + { + constraintsMap.put(component, constraint); + } + + + /** + * Adds a layout component and a constraint object to this layout. + * This method is usually only called by a {@java.awt.Container}s add + * Method. This method does nothing, since SpringLayout does not manage + * String-indexed components. + * + * @param component the component to be added. + * @param constraint the constraint to be set. + */ + public void addLayoutComponent(String name, Component c) + { + // do nothing here. + } + + /** + * Returns the constraint of the edge named by edgeName. + * + * @param c the component from which to get the constraint. + * @param edgeName the name of the edge, one of {@link #EAST}, + * {@link #WEST}, {@link NORTH} or {@link SOUTH}. + * @return the constraint of the edge edgeName of the + * component c. + */ + public Spring getConstraint(String edgeName, Component c) + { + Constraints constraints = getConstraints(c); + return constraints.getConstraint(edgeName); + } + + /** + * Returns the {@link Constraints} object associated with the specified + * component. + * + * @param c the component for which to determine the constraint. + * @return the {@link Constraints} object associated with the specified + * component. + */ + 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)); + } + else + { + 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); + + } + + return constraints; + } + + /** + * Returns the X alignment of the Container p. + * + * @param p the {@link java.awt.Container} for which to determine the X + * alignment. + * @return always 0.0 + */ + public float getLayoutAlignmentX(Container p) + { + return 0.0F; + } + + /** + * Returns the Y alignment of the Container p. + * + * @param p the {@link java.awt.Container} for which to determine the Y + * alignment. + * @return always 0.0 + */ + public float getLayoutAlignmentY(Container p) + { + return 0.0F; + } + + /** + * Recalculate a possibly cached layout. + */ + public void invalidateLayout(Container p) + { + // nothing to do here yet + } + + /** + * Lays out the container p. + * + * @param p the container to be laid out. + */ + public void layoutContainer(Container p) + { + + addLayoutComponent(p, new Constraints(Spring.constant(0), + Spring.constant(0))); + + int offsetX = p.getInsets().left; + int offsetY = p.getInsets().right; + + Component[] components = p.getComponents(); + 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(); + int width = constraints.getWidth().getValue(); + int height = constraints.getHeight().getValue(); + + c.setLocation(x + offsetX, y + offsetY); + c.setSize(width, height); + } + + } + + /** + * Calculates the maximum size of the layed out container. This + * respects the maximum sizes of all contained components. + * + * @param p the container to be laid out. + * @return the maximum size of the container. + */ + public Dimension maximumLayoutSize(Container p) + { + int maxX = 0; + int maxY = 0; + + int offsetX = p.getInsets().left; + int offsetY = p.getInsets().right; + + Component[] components = p.getComponents(); + for (int index = 0; index < components.length; index++) + { + Component c = components[index]; + Constraints constraints = getConstraints(c); + int x = constraints.getX().getMaximumValue(); + int y = constraints.getY().getMaximumValue(); + int width = constraints.getWidth().getMaximumValue(); + int height = constraints.getHeight().getMaximumValue(); + + int rightEdge = offsetX + x + width; + if (rightEdge > maxX) + maxX = rightEdge; + int bottomEdge = offsetY + y + height; + if (bottomEdge > maxY) + maxY = bottomEdge; + } + + return new Dimension(maxX, maxY); + } + + + /** + * Calculates the minimum size of the layed out container. This + * respects the minimum sizes of all contained components. + * + * @param p the container to be laid out. + * @return the minimum size of the container. + */ + public Dimension minimumLayoutSize(Container p) + { + int maxX = 0; + int maxY = 0; + + int offsetX = p.getInsets().left; + int offsetY = p.getInsets().right; + + Component[] components = p.getComponents(); + for (int index = 0; index < components.length; index++) + { + Component c = components[index]; + Constraints constraints = getConstraints(c); + int x = constraints.getX().getMinimumValue(); + int y = constraints.getY().getMinimumValue(); + int width = constraints.getWidth().getMinimumValue(); + int height = constraints.getHeight().getMinimumValue(); + + int rightEdge = offsetX + x + width; + if (rightEdge > maxX) + maxX = rightEdge; + int bottomEdge = offsetY + y + height; + if (bottomEdge > maxY) + maxY = bottomEdge; + } + + return new Dimension(maxX, maxY); + } + + /** + * Calculates the preferred size of the layed out container. This + * respects the preferred sizes of all contained components. + * + * @param p the container to be laid out. + * @return the preferred size of the container. + */ + public Dimension preferredLayoutSize(Container p) + { + int maxX = 0; + int maxY = 0; + + int offsetX = p.getInsets().left; + int offsetY = p.getInsets().right; + + Component[] components = p.getComponents(); + for (int index = 0; index < components.length; index++) + { + Component c = components[index]; + Constraints constraints = getConstraints(c); + int x = constraints.getX().getPreferredValue(); + int y = constraints.getY().getPreferredValue(); + int width = constraints.getWidth().getPreferredValue(); + int height = constraints.getHeight().getPreferredValue(); + + int rightEdge = offsetX + x + width; + if (rightEdge > maxX) + maxX = rightEdge; + int bottomEdge = offsetY + y + height; + if (bottomEdge > maxY) + maxY = bottomEdge; + } + + return new Dimension(maxX, maxY); + } + + /** + * Attaches the edge e1 of component c1 to + * the edge e2 of component c2 width the + * fixed strut pad. + * + * @param e1 the edge of component 1. + * @param c1 the component 1. + * @param pad the space between the components in pixels. + * @param e2 the edge of component 2. + * @param c2 the component 2. + */ + public void putConstraint(String e1, Component c1, int pad, String e2, + Component c2) + { + Constraints constraints1 = getConstraints(c1); + Constraints constraints2 = getConstraints(c2); + + Spring strut = Spring.constant(pad); + Spring otherEdge = constraints2.getConstraint(e2); + constraints1.setConstraint(e1, Spring.sum(strut, otherEdge)); + + } + + /** + * Attaches the edge e1 of component c1 to + * the edge e2 of component c2 width the + * {@link Spring} s. + * + * @param e1 the edge of component 1. + * @param c1 the component 1. + * @param s the space between the components as a {@link Spring} object. + * @param e2 the edge of component 2. + * @param c2 the component 2. + */ + public void putConstraint(String e1, Component c1, Spring s, String e2, + Component c2) + { + Constraints constraints1 = getConstraints(c1); + Constraints constraints2 = getConstraints(c2); + + Spring otherEdge = constraints2.getConstraint(e2); + constraints1.setConstraint(e1, Spring.sum(s, otherEdge)); + + } + + /** + * Removes a layout component. + * @param c the layout component to remove. + */ + public void removeLayoutComponent(Component c) + { + // do nothing here + } +} diff --git a/libjava/classpath/javax/swing/SwingConstants.java b/libjava/classpath/javax/swing/SwingConstants.java new file mode 100644 index 0000000..bed8a467 --- /dev/null +++ b/libjava/classpath/javax/swing/SwingConstants.java @@ -0,0 +1,77 @@ +/* SwingConstants.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +/** + * Defines constant values that are used throughout the Swing packages. + */ +public interface SwingConstants +{ + int CENTER = 0; + int TOP = 1; + int LEFT = 2; + int BOTTOM = 3; + int RIGHT = 4; + + int NORTH = 1; + int NORTH_EAST = 2; + int EAST = 3; + int SOUTH_EAST = 4; + int SOUTH = 5; + int SOUTH_WEST = 6; + int WEST = 7; + int NORTH_WEST = 8; + + int HORIZONTAL = 0; + int VERTICAL = 1; + + int LEADING = 10; + int TRAILING = 11; + + /** + * @since 1.4 + */ + int NEXT = 12; + + /** + * @since 1.4 + */ + int PREVIOUS = 13; +} + diff --git a/libjava/classpath/javax/swing/SwingUtilities.java b/libjava/classpath/javax/swing/SwingUtilities.java new file mode 100644 index 0000000..69b6345 --- /dev/null +++ b/libjava/classpath/javax/swing/SwingUtilities.java @@ -0,0 +1,1395 @@ +/* SwingUtilities.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.applet.Applet; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleStateSet; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.InputMapUIResource; + +/** + * This class contains a number of static utility functions which are + * useful when drawing swing components, dispatching events, or calculating + * regions which need painting. + * + * @author Graydon Hoare (graydon@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +public class SwingUtilities + implements SwingConstants +{ + /** + * This frame should be used as parent for JWindow or JDialog + * that doesn't an owner + */ + private static OwnerFrame ownerFrame; + + private SwingUtilities() + { + // Do nothing. + } + + /** + * Calculates the portion of the base rectangle which is inside the + * insets. + * + * @param base The rectangle to apply the insets to + * @param insets The insets to apply to the base rectangle + * @param ret A rectangle to use for storing the return value, or + * null + * + * @return The calculated area inside the base rectangle and its insets, + * either stored in ret or a new Rectangle if ret is null + * + * @see #calculateInnerArea + */ + public static Rectangle calculateInsetArea(Rectangle base, Insets insets, + Rectangle ret) + { + if (ret == null) + ret = new Rectangle(); + ret.setBounds(base.x + insets.left, base.y + insets.top, + base.width - (insets.left + insets.right), + base.height - (insets.top + insets.bottom)); + return ret; + } + + /** + * Calculates the portion of the component's bounds which is inside the + * component's border insets. This area is usually the area a component + * should confine its painting to. The coordinates are returned in terms + * of the component's coordinate system, where (0,0) is the + * upper left corner of the component's bounds. + * + * @param c The component to measure the bounds of + * @param r A Rectangle to store the return value in, or + * null + * + * @return The calculated area inside the component and its border + * insets + * + * @see #calculateInsetArea + */ + public static Rectangle calculateInnerArea(JComponent c, Rectangle r) + { + Rectangle b = getLocalBounds(c); + return calculateInsetArea(b, c.getInsets(), r); + } + + /** + * Returns the focus owner or null if comp is not + * the focus owner or a parent of it. + * + * @param comp the focus owner or a parent of it + * + * @return the focus owner, or null + * + * @deprecated 1.4 Replaced by + * KeyboardFocusManager.getFocusOwner(). + */ + public static Component findFocusOwner(Component comp) + { + // Get real focus owner. + Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager() + .getFocusOwner(); + + // Check if comp is the focus owner or a parent of it. + Component tmp = focusOwner; + + while (tmp != null) + { + if (tmp == comp) + return focusOwner; + + tmp = tmp.getParent(); + } + + return null; + } + + /** + * Returns the Accessible child of the specified component + * which appears at the supplied Point. If there is no + * child located at that particular pair of co-ordinates, null is returned + * instead. + * + * @param c the component whose children may be found at the specified + * point. + * @param p the point at which to look for the existence of children + * of the specified component. + * @return the Accessible child at the point, p, + * or null if there is no child at this point. + * @see javax.accessibility.AccessibleComponent#getAccessibleAt + */ + public static Accessible getAccessibleAt(Component c, Point p) + { + return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p); + } + + /** + *

+ * Returns the Accessible child of the specified component + * that has the supplied index within the parent component. The indexing + * of the children is zero-based, making the first child have an index of + * 0. + *

+ *

+ * Caution is advised when using this method, as its operation relies + * on the behaviour of varying implementations of an abstract method. + * For greater surety, direct use of the AWT component implementation + * of this method is advised. + *

+ * + * @param c the component whose child should be returned. + * @param i the index of the child within the parent component. + * @return the Accessible child at index i + * in the component, c. + * @see javax.accessibility.AccessibleContext#getAccessibleChild + * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChild + */ + public static Accessible getAccessibleChild(Component c, int i) + { + return c.getAccessibleContext().getAccessibleChild(i); + } + + /** + *

+ * Returns the number of Accessible children within + * the supplied component. + *

+ *

+ * Caution is advised when using this method, as its operation relies + * on the behaviour of varying implementations of an abstract method. + * For greater surety, direct use of the AWT component implementation + * of this method is advised. + *

+ * + * @param c the component whose children should be counted. + * @return the number of children belonging to the component, + * c. + * @see javax.accessibility.AccessibleContext#getAccessibleChildrenCount + * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChildrenCount + */ + public static int getAccessibleChildrenCount(Component c) + { + return c.getAccessibleContext().getAccessibleChildrenCount(); + } + + /** + *

+ * Returns the zero-based index of the specified component + * within its parent. If the component doesn't have a parent, + * -1 is returned. + *

+ *

+ * Caution is advised when using this method, as its operation relies + * on the behaviour of varying implementations of an abstract method. + * For greater surety, direct use of the AWT component implementation + * of this method is advised. + *

+ * + * @param c the component whose parental index should be found. + * @return the index of the component within its parent, or -1 + * if the component doesn't have a parent. + * @see javax.accessibility.AccessibleContext#getAccessibleIndexInParent + * @see java.awt.Component.AccessibleAWTComponent#getAccessibleIndexInParent + */ + public static int getAccessibleIndexInParent(Component c) + { + return c.getAccessibleContext().getAccessibleIndexInParent(); + } + + /** + *

+ * Returns a set of AccessibleStates, which represent + * the state of the supplied component. + *

+ *

+ * Caution is advised when using this method, as its operation relies + * on the behaviour of varying implementations of an abstract method. + * For greater surety, direct use of the AWT component implementation + * of this method is advised. + *

+ * + * @param c the component whose accessible state should be retrieved. + * @return a set of AccessibleState objects, which represent + * the state of the supplied component. + * @see javax.accessibility.AccessibleContext#getAccessibleStateSet + * @see java.awt.Component.AccessibleAWTComponent#getAccessibleStateSet + */ + public static AccessibleStateSet getAccessibleStateSet(Component c) + { + return c.getAccessibleContext().getAccessibleStateSet(); + } + + /** + * Calculates the bounds of a component in the component's own coordinate + * space. The result has the same height and width as the component's + * bounds, but its location is set to (0,0). + * + * @param aComponent The component to measure + * + * @return The component's bounds in its local coordinate space + */ + public static Rectangle getLocalBounds(Component aComponent) + { + Rectangle bounds = aComponent.getBounds(); + return new Rectangle(0, 0, bounds.width, bounds.height); + } + + /** + * If comp is a RootPaneContainer, return its JRootPane. + * Otherwise call getAncestorOfClass(JRootPane.class, a). + * + * @param comp The component to get the JRootPane of + * + * @return a suitable JRootPane for comp, or null + * + * @see javax.swing.RootPaneContainer#getRootPane + * @see #getAncestorOfClass + */ + public static JRootPane getRootPane(Component comp) + { + if (comp instanceof RootPaneContainer) + return ((RootPaneContainer)comp).getRootPane(); + else + return (JRootPane) getAncestorOfClass(JRootPane.class, comp); + } + + /** + * Returns the least ancestor of comp which has the + * specified name. + * + * @param name The name to search for + * @param comp The component to search the ancestors of + * + * @return The nearest ancestor of comp with the given + * name, or null if no such ancestor exists + * + * @see java.awt.Component#getName + * @see #getAncestorOfClass + */ + public static Container getAncestorNamed(String name, Component comp) + { + while (comp != null && (comp.getName() != name)) + comp = comp.getParent(); + return (Container) comp; + } + + /** + * Returns the least ancestor of comp which is an instance + * of the specified class. + * + * @param c The class to search for + * @param comp The component to search the ancestors of + * + * @return The nearest ancestor of comp which is an instance + * of the given class, or null if no such ancestor exists + * + * @see #getAncestorOfClass + * @see #windowForComponent + */ + public static Container getAncestorOfClass(Class c, Component comp) + { + while (comp != null && (! c.isInstance(comp))) + comp = comp.getParent(); + return (Container) comp; + } + + /** + * Returns the first ancestor of comp that is a {@link Window} + * or null if comp is not contained in a + * {@link Window}. + * + * This is equivalent to calling + * getAncestorOfClass(Window, comp) or + * windowForComponent(comp). + * + * @param comp the component for which we are searching the ancestor Window + * + * @return the first ancestor Window of comp or + * null if comp is not contained in a Window + */ + public static Window getWindowAncestor(Component comp) + { + return (Window) getAncestorOfClass(Window.class, comp); + } + + /** + * Equivalent to calling getAncestorOfClass(Window, comp). + * + * @param comp The component to search for an ancestor window + * + * @return An ancestral window, or null if none exists + */ + public static Window windowForComponent(Component comp) + { + return (Window) getAncestorOfClass(Window.class, comp); + } + + /** + * Returns the "root" of the component tree containint comp + * The root is defined as either the least ancestor of + * comp which is a {@link Window}, or the greatest + * ancestor of comp which is a {@link Applet} if no {@link + * Window} ancestors are found. + * + * @param comp The component to search for a root + * + * @return The root of the component's tree, or null + */ + public static Component getRoot(Component comp) + { + Applet app = null; + Window win = null; + + while (comp != null) + { + if (win == null && comp instanceof Window) + win = (Window) comp; + else if (comp instanceof Applet) + app = (Applet) comp; + comp = comp.getParent(); + } + + if (win != null) + return win; + else + return app; + } + + /** + * Return true if a descends from b, in other words if b is an + * ancestor of a. + * + * @param a The child to search the ancestry of + * @param b The potential ancestor to search for + * + * @return true if a is a descendent of b, false otherwise + */ + public static boolean isDescendingFrom(Component a, Component b) + { + while (true) + { + if (a == null || b == null) + return false; + if (a == b) + return true; + a = a.getParent(); + } + } + + /** + * Returns the deepest descendent of parent which is both visible and + * contains the point (x,y). Returns parent when either + * parent is not a container, or has no children which contain + * (x,y). Returns null when either + * (x,y) is outside the bounds of parent, or parent is + * null. + * + * @param parent The component to search the descendents of + * @param x Horizontal coordinate to search for + * @param y Vertical coordinate to search for + * + * @return A component containing (x,y), or + * null + * + * @see java.awt.Container#findComponentAt + */ + public static Component getDeepestComponentAt(Component parent, int x, int y) + { + if (parent == null || (! parent.contains(x, y))) + return null; + + if (! (parent instanceof Container)) + return parent; + + Container c = (Container) parent; + return c.findComponentAt(x, y); + } + + /** + * Converts a point from a component's local coordinate space to "screen" + * coordinates (such as the coordinate space mouse events are delivered + * in). This operation is equivalent to translating the point by the + * location of the component (which is the origin of its coordinate + * space). + * + * @param p The point to convert + * @param c The component which the point is expressed in terms of + * + * @see convertPointFromScreen + */ + public static void convertPointToScreen(Point p, Component c) + { + Point c0 = c.getLocationOnScreen(); + p.translate(c0.x, c0.y); + } + + /** + * Converts a point from "screen" coordinates (such as the coordinate + * space mouse events are delivered in) to a component's local coordinate + * space. This operation is equivalent to translating the point by the + * negation of the component's location (which is the origin of its + * coordinate space). + * + * @param p The point to convert + * @param c The component which the point should be expressed in terms of + */ + public static void convertPointFromScreen(Point p, Component c) + { + Point c0 = c.getLocationOnScreen(); + p.translate(-c0.x, -c0.y); + } + + /** + * Converts a point (x,y) from the coordinate space of one + * component to another. This is equivalent to converting the point from + * source space to screen space, then back from screen space + * to destination space. If exactly one of the two + * Components is null, it is taken to refer to the root + * ancestor of the other component. If both are null, no + * transformation is done. + * + * @param source The component which the point is expressed in terms of + * @param x Horizontal coordinate of point to transform + * @param y Vertical coordinate of point to transform + * @param destination The component which the return value will be + * expressed in terms of + * + * @return The point (x,y) converted from the coordinate space of the + * source component to the coordinate space of the destination component + * + * @see #convertPointToScreen + * @see #convertPointFromScreen + * @see #convertRectangle + * @see #getRoot + */ + public static Point convertPoint(Component source, int x, int y, + Component destination) + { + Point pt = new Point(x, y); + + if (source == null && destination == null) + return pt; + + if (source == null) + source = getRoot(destination); + + if (destination == null) + destination = getRoot(source); + + if (source.isShowing() && destination.isShowing()) + { + convertPointToScreen(pt, source); + convertPointFromScreen(pt, destination); + } + + return pt; + } + + public static Point convertPoint(Component source, Point aPoint, Component destination) + { + return convertPoint(source, aPoint.x, aPoint.y, destination); + } + + /** + * Converts a rectangle from the coordinate space of one component to + * another. This is equivalent to converting the rectangle from + * source space to screen space, then back from screen space + * to destination space. If exactly one of the two + * Components is null, it is taken to refer to the root + * ancestor of the other component. If both are null, no + * transformation is done. + * + * @param source The component which the rectangle is expressed in terms of + * @param rect The rectangle to convert + * @param destination The component which the return value will be + * expressed in terms of + * + * @return A new rectangle, equal in size to the input rectangle, but + * with its position converted from the coordinate space of the source + * component to the coordinate space of the destination component + * + * @see #convertPointToScreen + * @see #convertPointFromScreen + * @see #convertPoint + * @see #getRoot + */ + public static Rectangle convertRectangle(Component source, + Rectangle rect, + Component destination) + { + Point pt = convertPoint(source, rect.x, rect.y, destination); + return new Rectangle(pt.x, pt.y, rect.width, rect.height); + } + + /** + * Convert a mouse event which refrers to one component to another. This + * includes changing the mouse event's coordinate space, as well as the + * source property of the event. If source is + * null, it is taken to refer to destination's + * root component. If destination is null, the + * new event will remain expressed in source's coordinate + * system. + * + * @param source The component the mouse event currently refers to + * @param sourceEvent The mouse event to convert + * @param destination The component the new mouse event should refer to + * + * @return A new mouse event expressed in terms of the destination + * component's coordinate space, and with the destination component as + * its source + * + * @see #convertPoint + */ + public static MouseEvent convertMouseEvent(Component source, + MouseEvent sourceEvent, + Component destination) + { + Point newpt = convertPoint(source, sourceEvent.getX(), sourceEvent.getY(), + destination); + + return new MouseEvent(destination, sourceEvent.getID(), + sourceEvent.getWhen(), sourceEvent.getModifiersEx(), + newpt.x, newpt.y, sourceEvent.getClickCount(), + sourceEvent.isPopupTrigger(), sourceEvent.getButton()); + } + + /** + * Recursively walk the component tree under comp calling + * updateUI on each {@link JComponent} found. This causes + * the entire tree to re-initialize its UI delegates. + * + * @param comp The component to walk the children of, calling updateUI + */ + public static void updateComponentTreeUI(Component comp) + { + if (comp == null) + return; + + if (comp instanceof Container) + { + Component[] children = ((Container)comp).getComponents(); + for (int i = 0; i < children.length; ++i) + updateComponentTreeUI(children[i]); + } + + if (comp instanceof JComponent) + ((JComponent)comp).updateUI(); + } + + + /** + *

Layout a "compound label" consisting of a text string and an icon + * which is to be placed near the rendered text. Once the text and icon + * are laid out, the text rectangle and icon rectangle parameters are + * altered to store the calculated positions.

+ * + *

The size of the text is calculated from the provided font metrics + * object. This object should be the metrics of the font you intend to + * paint the label with.

+ * + *

The position values control where the text is placed relative to + * the icon. The horizontal position value should be one of the constants + * LEADING, TRAILING, LEFT, + * RIGHT or CENTER. The vertical position value + * should be one fo the constants TOP, BOTTOM + * or CENTER.

+ * + *

The text-icon gap value controls the number of pixels between the + * icon and the text.

+ * + *

The alignment values control where the text and icon are placed, as + * a combined unit, within the view rectangle. The horizontal alignment + * value should be one of the constants LEADING, + * TRAILING, LEFT, RIGHT or + * CENTER. The vertical alignment valus should be one of the + * constants TOP, BOTTOM or + * CENTER.

+ * + *

If the LEADING or TRAILING constants are + * given for horizontal alignment or horizontal text position, they are + * interpreted relative to the provided component's orientation property, + * a constant in the {@link java.awt.ComponentOrientation} class. For + * example, if the component's orientation is LEFT_TO_RIGHT, + * then the LEADING value is a synonym for LEFT + * and the TRAILING value is a synonym for + * RIGHT

+ * + *

If the text and icon are equal to or larger than the view + * rectangle, the horizontal and vertical alignment values have no + * affect.

+ * + * @param c A component used for its orientation value + * @param fm The font metrics used to measure the text + * @param text The text to place in the compound label + * @param icon The icon to place next to the text + * @param verticalAlignment The vertical alignment of the label relative + * to its component + * @param horizontalAlignment The horizontal alignment of the label + * relative to its component + * @param verticalTextPosition The vertical position of the label's text + * relative to its icon + * @param horizontalTextPosition The horizontal position of the label's + * text relative to its icon + * @param viewR The view rectangle, specifying the area which layout is + * constrained to + * @param iconR A rectangle which is modified to hold the laid-out + * position of the icon + * @param textR A rectangle which is modified to hold the laid-out + * position of the text + * @param textIconGap The distance between text and icon + * + * @return The string of characters, possibly truncated with an elipsis, + * which is laid out in this label + */ + + public static String layoutCompoundLabel(JComponent c, + FontMetrics fm, + String text, + Icon icon, + int verticalAlignment, + int horizontalAlignment, + int verticalTextPosition, + int horizontalTextPosition, + Rectangle viewR, + Rectangle iconR, + Rectangle textR, + int textIconGap) + { + + // Fix up the orientation-based horizontal positions. + + if (horizontalTextPosition == LEADING) + { + if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) + horizontalTextPosition = RIGHT; + else + horizontalTextPosition = LEFT; + } + else if (horizontalTextPosition == TRAILING) + { + if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) + horizontalTextPosition = LEFT; + else + horizontalTextPosition = RIGHT; + } + + // Fix up the orientation-based alignments. + + if (horizontalAlignment == LEADING) + { + if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) + horizontalAlignment = RIGHT; + else + horizontalAlignment = LEFT; + } + else if (horizontalAlignment == TRAILING) + { + if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) + horizontalAlignment = LEFT; + else + horizontalAlignment = RIGHT; + } + + return layoutCompoundLabel(fm, text, icon, + verticalAlignment, + horizontalAlignment, + verticalTextPosition, + horizontalTextPosition, + viewR, iconR, textR, textIconGap); + } + + /** + *

Layout a "compound label" consisting of a text string and an icon + * which is to be placed near the rendered text. Once the text and icon + * are laid out, the text rectangle and icon rectangle parameters are + * altered to store the calculated positions.

+ * + *

The size of the text is calculated from the provided font metrics + * object. This object should be the metrics of the font you intend to + * paint the label with.

+ * + *

The position values control where the text is placed relative to + * the icon. The horizontal position value should be one of the constants + * LEFT, RIGHT or CENTER. The + * vertical position value should be one fo the constants + * TOP, BOTTOM or CENTER.

+ * + *

The text-icon gap value controls the number of pixels between the + * icon and the text.

+ * + *

The alignment values control where the text and icon are placed, as + * a combined unit, within the view rectangle. The horizontal alignment + * value should be one of the constants LEFT, RIGHT or + * CENTER. The vertical alignment valus should be one of the + * constants TOP, BOTTOM or + * CENTER.

+ * + *

If the text and icon are equal to or larger than the view + * rectangle, the horizontal and vertical alignment values have no + * affect.

+ * + *

Note that this method does not know how to deal with + * horizontal alignments or positions given as LEADING or + * TRAILING values. Use the other overloaded variant of this + * method if you wish to use such values. + * + * @param fm The font metrics used to measure the text + * @param text The text to place in the compound label + * @param icon The icon to place next to the text + * @param verticalAlignment The vertical alignment of the label relative + * to its component + * @param horizontalAlignment The horizontal alignment of the label + * relative to its component + * @param verticalTextPosition The vertical position of the label's text + * relative to its icon + * @param horizontalTextPosition The horizontal position of the label's + * text relative to its icon + * @param viewR The view rectangle, specifying the area which layout is + * constrained to + * @param iconR A rectangle which is modified to hold the laid-out + * position of the icon + * @param textR A rectangle which is modified to hold the laid-out + * position of the text + * @param textIconGap The distance between text and icon + * + * @return The string of characters, possibly truncated with an elipsis, + * which is laid out in this label + */ + + public static String layoutCompoundLabel(FontMetrics fm, + String text, + Icon icon, + int verticalAlignment, + int horizontalAlignment, + int verticalTextPosition, + int horizontalTextPosition, + Rectangle viewR, + Rectangle iconR, + Rectangle textR, + int textIconGap) + { + + // Work out basic height and width. + + if (icon == null) + { + textIconGap = 0; + iconR.width = 0; + iconR.height = 0; + } + else + { + iconR.width = icon.getIconWidth(); + iconR.height = icon.getIconHeight(); + } + if (text == null) + { + textIconGap = 0; + textR.width = 0; + textR.height = 0; + } + else + { + int fromIndex = 0; + textR.width = fm.stringWidth(text); + textR.height = fm.getHeight(); + while (text.indexOf('\n', fromIndex) != -1) + { + textR.height += fm.getHeight(); + fromIndex = text.indexOf('\n', fromIndex) + 1; + } + } + + // Work out the position of text and icon, assuming the top-left coord + // starts at (0,0). We will fix that up momentarily, after these + // "position" decisions are made and we look at alignment. + + switch (horizontalTextPosition) + { + case LEFT: + textR.x = 0; + iconR.x = textR.width + textIconGap; + break; + case RIGHT: + iconR.x = 0; + textR.x = iconR.width + textIconGap; + break; + case CENTER: + int centerLine = Math.max(textR.width, iconR.width) / 2; + textR.x = centerLine - textR.width/2; + iconR.x = centerLine - iconR.width/2; + break; + } + + switch (verticalTextPosition) + { + case TOP: + textR.y = 0; + iconR.y = (horizontalTextPosition == CENTER + ? textR.height + textIconGap : 0); + break; + case BOTTOM: + iconR.y = 0; + textR.y = (horizontalTextPosition == CENTER + ? iconR.height + textIconGap + : iconR.height - textR.height); + break; + case CENTER: + int centerLine = Math.max(textR.height, iconR.height) / 2; + textR.y = centerLine - textR.height/2; + iconR.y = centerLine - iconR.height/2; + break; + } + // The two rectangles are laid out correctly now, but only assuming + // that their upper left corner is at (0,0). If we have any alignment other + // than TOP and LEFT, we need to adjust them. + + Rectangle u = textR.union(iconR); + int horizontalAdjustment = viewR.x; + int verticalAdjustment = viewR.y; + switch (verticalAlignment) + { + case TOP: + break; + case BOTTOM: + verticalAdjustment += (viewR.height - u.height); + break; + case CENTER: + verticalAdjustment += ((viewR.height/2) - (u.height/2)); + break; + } + switch (horizontalAlignment) + { + case LEFT: + break; + case RIGHT: + horizontalAdjustment += (viewR.width - u.width); + break; + case CENTER: + horizontalAdjustment += ((viewR.width/2) - (u.width/2)); + break; + } + + iconR.x += horizontalAdjustment; + iconR.y += verticalAdjustment; + + textR.x += horizontalAdjustment; + textR.y += verticalAdjustment; + + return text; + } + + /** + * Calls {@link java.awt.EventQueue.invokeLater} with the + * specified {@link Runnable}. + */ + public static void invokeLater(Runnable doRun) + { + java.awt.EventQueue.invokeLater(doRun); + } + + /** + * Calls {@link java.awt.EventQueue.invokeAndWait} with the + * specified {@link Runnable}. + */ + public static void invokeAndWait(Runnable doRun) + throws InterruptedException, + InvocationTargetException + { + java.awt.EventQueue.invokeAndWait(doRun); + } + + /** + * Calls {@link java.awt.EventQueue.isEventDispatchThread}. + */ + public static boolean isEventDispatchThread() + { + return java.awt.EventQueue.isDispatchThread(); + } + + /** + * This method paints the given component at the given position and size. + * The component will be reparented to the container given. + * + * @param g The Graphics object to draw with. + * @param c The Component to draw + * @param p The Container to reparent to. + * @param x The x coordinate to draw at. + * @param y The y coordinate to draw at. + * @param w The width of the drawing area. + * @param h The height of the drawing area. + */ + public static void paintComponent(Graphics g, Component c, Container p, + int x, int y, int w, int h) + { + Container parent = c.getParent(); + if (parent != null) + parent.remove(c); + if (p != null) + p.add(c); + + Shape savedClip = g.getClip(); + + g.setClip(x, y, w, h); + g.translate(x, y); + + c.paint(g); + + g.translate(-x, -y); + g.setClip(savedClip); + } + + /** + * This method paints the given component in the given rectangle. + * The component will be reparented to the container given. + * + * @param g The Graphics object to draw with. + * @param c The Component to draw + * @param p The Container to reparent to. + * @param r The rectangle that describes the drawing area. + */ + public static void paintComponent(Graphics g, Component c, + Container p, Rectangle r) + { + paintComponent(g, c, p, r.x, r.y, r.width, r.height); + } + + /** + * This method returns the common Frame owner used in JDialogs or + * JWindow when no owner is provided. + * + * @return The common Frame + */ + static Frame getOwnerFrame() + { + if (ownerFrame == null) + ownerFrame = new OwnerFrame(); + return ownerFrame; + } + + /** + * Checks if left mouse button was clicked. + * + * @param event the event to check + * + * @return true if left mouse was clicked, false otherwise. + */ + public static boolean isLeftMouseButton(MouseEvent event) + { + return ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) + == InputEvent.BUTTON1_DOWN_MASK); + } + + /** + * Checks if middle mouse button was clicked. + * + * @param event the event to check + * + * @return true if middle mouse was clicked, false otherwise. + */ + public static boolean isMiddleMouseButton(MouseEvent event) + { + return ((event.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) + == InputEvent.BUTTON2_DOWN_MASK); + } + + /** + * Checks if right mouse button was clicked. + * + * @param event the event to check + * + * @return true if right mouse was clicked, false otherwise. + */ + public static boolean isRightMouseButton(MouseEvent event) + { + return ((event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) + == InputEvent.BUTTON3_DOWN_MASK); + } + + /** + * This frame should be used when constructing a Window/JDialog without + * a parent. In this case, we are forced to use this frame as a window's + * parent, because we simply cannot pass null instead of parent to Window + * constructor, since doing it will result in NullPointerException. + */ + private static class OwnerFrame extends Frame + { + public void setVisible(boolean b) + { + // Do nothing here. + } + + public boolean isShowing() + { + return true; + } + } + + public static boolean notifyAction(Action action, + KeyStroke ks, + KeyEvent event, + Object sender, + int modifiers) + { + if (action != null && action.isEnabled()) + { + String name = (String) action.getValue(Action.ACTION_COMMAND_KEY); + if (name == null + && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED) + name = new String(new char[] {event.getKeyChar()}); + action.actionPerformed(new ActionEvent(sender, + ActionEvent.ACTION_PERFORMED, + name, modifiers)); + return true; + } + return false; + } + + /** + *

Change the shared, UI-managed {@link ActionMap} for a given + * component. ActionMaps are arranged in a hierarchy, in order to + * encourage sharing of common actions between components. The hierarchy + * unfortunately places UI-managed ActionMaps at the end of the + * parent-pointer chain, as illustrated:

+ * + *
+   *  [{@link javax.swing.JComponent#getActionMap()}] 
+   *          --> [{@link javax.swing.ActionMap}] 
+   *     parent --> [{@link javax.swing.text.KeymapActionMap}] 
+   *       parent --> [{@link javax.swing.plaf.ActionMapUIResource}]
+   * 
+ * + *

Our goal with this method is to replace the first ActionMap along + * this chain which is an instance of {@link ActionMapUIResource}, since + * these are the ActionMaps which are supposed to be shared between + * components.

+ * + *

If the provided ActionMap is null, we interpret the + * call as a request to remove the UI-managed ActionMap from the + * component's ActionMap parent chain.

+ */ + public static void replaceUIActionMap(JComponent component, + ActionMap uiActionMap) + { + ActionMap child = component.getActionMap(); + if (child == null) + component.setActionMap(uiActionMap); + else + { + ActionMap parent = child.getParent(); + while(parent != null) + { + child = parent; + parent = child.getParent(); + } + + if (child != null) + child.setParent(uiActionMap); + } + } + + /** + *

Change the shared, UI-managed {@link InputMap} for a given + * component. InputMaps are arranged in a hierarchy, in order to + * encourage sharing of common input mappings between components. The + * hierarchy unfortunately places UI-managed InputMaps at the + * end of the parent-pointer chain, as illustrated:

+ * + *
+   *  [{@link javax.swing.JComponent#getInputMap()}] 
+   *          --> [{@link javax.swing.InputMap}] 
+   *     parent --> [{@link javax.swing.text.KeymapWrapper}] 
+   *       parent --> [{@link javax.swing.plaf.InputMapUIResource}]
+   * 
+ * + *

Our goal with this method is to replace the first InputMap along + * this chain which is an instance of {@link InputMapUIResource}, since + * these are the InputMaps which are supposed to be shared between + * components.

+ * + *

If the provided InputMap is null, we interpret the + * call as a request to remove the UI-managed InputMap from the + * component's InputMap parent chain.

+ */ + public static void replaceUIInputMap(JComponent component, + int condition, + InputMap uiInputMap) + { + InputMap child = component.getInputMap(condition); + if (child == null) + component.setInputMap(condition, uiInputMap); + else + { + while(child.getParent() != null + && !(child.getParent() instanceof InputMapUIResource)) + child = child.getParent(); + if (child != null) + child.setParent(uiInputMap); + } + } + + /** + * Subtracts a rectangle from another and return the area as an array + * of rectangles. + * Returns the areas of rectA which are not covered by rectB. + * If the rectangles do not overlap, or if either parameter is + * null, a zero-size array is returned. + * @param rectA The first rectangle + * @param rectB The rectangle to subtract from the first + * @return An array of rectangles representing the area in rectA + * not overlapped by rectB + */ + public static Rectangle[] computeDifference(Rectangle rectA, Rectangle rectB) + { + if (rectA == null || rectB == null) + return new Rectangle[0]; + + Rectangle[] r = new Rectangle[4]; + int x1 = rectA.x; + int y1 = rectA.y; + int w1 = rectA.width; + int h1 = rectA.height; + int x2 = rectB.x; + int y2 = rectB.y; + int w2 = rectB.width; + int h2 = rectB.height; + + // (outer box = rectA) + // ------------- + // |_____0_____| + // | |rectB| | + // |_1|_____|_2| + // | 3 | + // ------------- + int H0 = (y2 > y1) ? y2 - y1 : 0; // height of box 0 + int H3 = (y2 + h2 < y1 + h1) ? y1 + h1 - y2 - h2 : 0; // height box 3 + int W1 = (x2 > x1) ? x2 - x1 : 0; // width box 1 + int W2 = (x1 + w1 > x2 + w2) ? x1 + w1 - x2 - w2 : 0; // w. box 2 + int H12 = (H0 + H3 < h1) ? h1 - H0 - H3 : 0; // height box 1 & 2 + + if (H0 > 0) + r[0] = new Rectangle(x1, y1, w1, H0); + else + r[0] = null; + + if (W1 > 0 && H12 > 0) + r[1] = new Rectangle(x1, y1 + H0, W1, H12); + else + r[1] = null; + + if (W2 > 0 && H12 > 0) + r[2] = new Rectangle(x2 + w2, y1 + H0, W2, H12); + else + r[2] = null; + + if (H3 > 0) + r[3] = new Rectangle(x1, y1 + H0 + H12, w1, H3); + else + r[3] = null; + + // sort out null objects + int n = 0; + for (int i = 0; i < 4; i++) + if (r[i] != null) + n++; + Rectangle[] out = new Rectangle[n]; + for (int i = 3; i >= 0; i--) + if (r[i] != null) + out[--n] = r[i]; + + return out; + } + + /** + * Calculates the intersection of two rectangles. + * + * @param x upper-left x coodinate of first rectangle + * @param x upper-left y coodinate of first rectangle + * @param w width of first rectangle + * @param h height of first rectangle + * @param rect a Rectangle object of the second rectangle + * @throws a NullPointerException if rect is null. + * + * @return a rectangle corresponding to the intersection of the + * two rectangles. A zero rectangle is returned if the rectangles + * do not overlap. + */ + public static Rectangle computeIntersection(int x, int y, int w, int h, + Rectangle rect) + { + int x2 = (int) rect.getX(); + int y2 = (int) rect.getY(); + int w2 = (int) rect.getWidth(); + int h2 = (int) rect.getHeight(); + + int dx = (x > x2) ? x : x2; + int dy = (y > y2) ? y : y2; + int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx); + int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); + + if (dw >= 0 && dh >= 0) + return new Rectangle(dx, dy, dw, dh); + + return new Rectangle(0, 0, 0, 0); + } + + /** + * Calculates the width of a given string. + * + * @param fm the FontMetrics object to use + * @param str the string + * + * @return the width of the the string. + */ + public static int computeStringWidth(FontMetrics fm, String str) + { + return fm.stringWidth(str); + } + + /** + * Calculates the union of two rectangles. + * + * @param x upper-left x coodinate of first rectangle + * @param x upper-left y coodinate of first rectangle + * @param w width of first rectangle + * @param h height of first rectangle + * @param rect a Rectangle object of the second rectangle + * @throws a NullPointerException if rect is null. + * + * @return a rectangle corresponding to the union of the + * two rectangles. A rectangle encompassing both is returned if the + * rectangles do not overlap. + */ + public static Rectangle computeUnion(int x, int y, int w, int h, + Rectangle rect) + { + int x2 = (int) rect.getX(); + int y2 = (int) rect.getY(); + int w2 = (int) rect.getWidth(); + int h2 = (int) rect.getHeight(); + + int dx = (x < x2) ? x : x2; + int dy = (y < y2) ? y : y2; + int dw = (x + w > x2 + w2) ? (x + w - dx) : (x2 + w2 - dx); + int dh = (y + h > y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); + + if (dw >= 0 && dh >= 0) + return new Rectangle(dx, dy, dw, dh); + + return new Rectangle(0, 0, 0, 0); + } + + /** + * Tests if a rectangle contains another. + * @param a first rectangle + * @param b second rectangle + * @return true if a contains b, false otherwise + * @throws NullPointerException + */ + public static boolean isRectangleContainingRectangle(Rectangle a, Rectangle b) + { + // Note: zero-size rects inclusive, differs from Rectangle.contains() + return b.width >= 0 && b.height >= 0 && b.width >= 0 && b.height >= 0 + && b.x >= a.x && b.x + b.width <= a.x + a.width && b.y >= a.y + && b.y + b.height <= a.y + a.height; + } + + /** + * Returns the InputMap that is provided by the ComponentUI of + * component for the specified condition. + * + * @param component the component for which the InputMap is returned + * @param cond the condition that specifies which of the three input + * maps should be returned, may be + * {@link JComponent#WHEN_IN_FOCUSED_WINDOW}, + * {@link JComponent#WHEN_FOCUSED} or + * {@link JComponent#WHEN_ANCESTOR_OF_FOCUSED_COMPONENT + * + * @return + */ + public static InputMap getUIInputMap(JComponent component, int cond) + { + if (UIManager.getUI(component) != null) + // we assume here that the UI class sets the parent of the component's + // InputMap, which is the correct behaviour. If it's not, then + // this can be considered a bug + return component.getInputMap(cond).getParent(); + else + return null; + } + + /** + * Returns the ActionMap that is provided by the ComponentUI of + * component. + * + * @param component the component for which the ActionMap is returned + */ + public static ActionMap getUIActionMap(JComponent component) + { + if (UIManager.getUI(component) != null) + // we assume here that the UI class sets the parent of the component's + // ActionMap, which is the correct behaviour. If it's not, then + // this can be considered a bug + return component.getActionMap().getParent(); + else + return null; + } +} diff --git a/libjava/classpath/javax/swing/Timer.java b/libjava/classpath/javax/swing/Timer.java new file mode 100644 index 0000000..87f420a --- /dev/null +++ b/libjava/classpath/javax/swing/Timer.java @@ -0,0 +1,485 @@ +/* Timer.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; + +/** + * Fires one or more action events after the specified delay. + * @author Ronald Veldema + * @author Audrius Meskauskas (audriusa@Bionformatics.org) - bug fixes + * and documentation comments + */ +public class Timer + implements Serializable +{ + /** + * The timer thread + */ + private class Waker + extends Thread + { + /** + * 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; + } + } + } + + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = -1116180831621385484L; + + /** + * The encloding class, used with {@link SwingUtilities#invokeLater} + * to invoke the {@link #drainEvents()}. + */ + private Runnable drainer = new Runnable() + { + public void run() + { + drainEvents(); + } + }; + + /** + * If true, the timer prints a message to + * {@link System#out} when firing each event. + */ + static boolean logTimers; + + /** + * A field to store all listeners who are listening to this timer. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * true if the timer coalesces events. + */ + boolean coalesce = true; + + /** + * true if the timer is firing repetetive events. + */ + boolean repeats = true; + + /** + * true if the timer is currently active, firing events + * as scheduled. + */ + boolean running; + + /** + * The delay between subsequent repetetive events. + */ + int delay; + + /** + * The initial delay before the first event. + */ + int initialDelay; + + /** + * The number of events that have been already fired by this timer. + * This is used as a numeric identifier for the next event that would + * be fired. + */ + int ticks; + + /** + * Stores the thread that posts events to the queue at required time + * intervals. + */ + private Waker waker; + + /** + * This object manages a "queue" of virtual actionEvents, maintained as a + * simple long counter. When the timer expires, a new event is queued, + * and a dispatcher object is pushed into the system event queue. When + * the system thread runs the dispatcher, it will fire as many + * ActionEvents as have been queued, unless the timer is set to + * coalescing mode, in which case it will fire only one ActionEvent. + */ + private long queue; + + /** + * synchronized(queueLock) replaces + * synchronized(queue) that is not supported by this language. + */ + private Object queueLock = new Object(); + + /** + * Creates a new Timer object. + * + * @param d the default value for both initial and between event delay, in + * milliseconds. + * @param listener the first action listener, can be null. + */ + public Timer(int d, ActionListener listener) + { + delay = d; + initialDelay = d; + + if (listener != null) + addActionListener(listener); + } + + /** + * Get the array of action listeners. + * + * @return the array of action listeners that are listening for the events, + * fired by this timer + * + * @since 1.4 + */ + public ActionListener[] getActionListeners() + { + return (ActionListener[]) listenerList.getListeners(ActionListener.class); + } + + /** + * Sets whether the Timer coalesces multiple pending event firings. + * If the coalescing is enabled, the multiple events that have not been + * fired on time are replaced by the single event. The events may not + * be fired on time if the application is busy. + * + * @param c true (default) to enable the event coalescing, + * false otherwise + */ + public void setCoalesce(boolean c) + { + coalesce = c; + } + + /** + * Checks if the Timer coalesces multiple pending event firings. + * If the coalescing is enabled, the multiple events that have not been + * fired on time are replaced by the single event. The events may not + * be fired on time if the application is busy. + * + * @return true if the coalescing is enabled, + * false otherwise + */ + public boolean isCoalesce() + { + return coalesce; + } + + /** + * Get the event listeners of the given type that are listening for the + * events, fired by this timer. + * + * @param listenerType the listener type (for example, ActionListener.class) + * + * @return the array of event listeners that are listening for the events, + * fired by this timer + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Set the timer logging state. If it is set to true, the + * timer prints a message to {@link System#out} when firing each + * action event. + * + * @param lt true if logging is enabled, false + * (default value) otherwise + */ + public static void setLogTimers(boolean lt) + { + logTimers = lt; + } + + /** + * Return the logging state. + * + * @return true if the timer is printing a message to + * {@link System#out} + * when firing each action event + */ + public static boolean getLogTimers() + { + return logTimers; + } + + /** + * Set the delay between firing the subsequent events. + * This parameter does not change the value of the initial delay before + * firing the first event. + * + * @param d The time gap between the subsequent events, in milliseconds + */ + public void setDelay(int d) + { + delay = d; + } + + /** + * Get the delay between firing the subsequent events. + * + * @return The delay between subsequent events, in milliseconds + */ + public int getDelay() + { + return delay; + } + + /** + * Set the intial delay before firing the first event since calling + * the {@link #start()} method. If the initial delay has not been + * set, it is assumed having the same value as the delay between the + * subsequent events. + * + * @param i the initial delay, in milliseconds + */ + public void setInitialDelay(int i) + { + initialDelay = i; + } + + /** + * Get the intial delay before firing the first event since calling + * the {@link #start()} method. If the initial delay has not been + * set, returns the same value as {@link #getDelay()}. + * + * @return the initial delay before firing the first action event. + */ + public int getInitialDelay() + { + return initialDelay; + } + + /** + * Enable firing the repetetive events. + * + * @param r true (default value) to fire repetetive events. + * false to fire + * only one event after the initial delay + */ + public void setRepeats(boolean r) + { + repeats = r; + } + + /** + * Check is this timer fires repetetive events. + * + * @return true if the timer fires repetetive events, + * false if it fires + * only one event after the initial delay + */ + public boolean isRepeats() + { + return repeats; + } + + /** + * Get the timer state. + * + * @return true if the timer has been started and is firing + * the action events as scheduled. false + * if the timer is inactive. + */ + public boolean isRunning() + { + return running; + } + + /** + * Add the action listener + * + * @param listener the action listener to add + */ + public void addActionListener(ActionListener listener) + { + listenerList.add(ActionListener.class, listener); + } + + /** + * Remove the action listener. + * + * @param listener the action listener to remove + */ + public void removeActionListener(ActionListener listener) + { + listenerList.remove(ActionListener.class, listener); + } + + /** + * Cancel all pending tasks and fire the first event after the initial + * delay. + */ + public void restart() + { + stop(); + start(); + } + + /** + * Start firing the action events. + */ + public void start() + { + if (isRunning()) + return; + waker = new Waker(); + waker.start(); + } + + /** + * Stop firing the action events. + */ + public void stop() + { + running = false; + if (waker != null) + waker.interrupt(); + synchronized (queueLock) + { + queue = 0; + } + } + + /** + * Fire the given action event to the action listeners. + * + * @param event the event to fire + */ + protected void fireActionPerformed(ActionEvent event) + { + ActionListener[] listeners = getActionListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners [ i ].actionPerformed(event); + } + + /** + * Fire the action event, named "Timer" and having the numeric + * identifier, equal to the numer of events that have been + * already fired before. + */ + void fireActionPerformed() + { + fireActionPerformed(new ActionEvent(this, ticks++, "Timer")); + } + + /** + * Fire the queued action events. + * In the coalescing mode, a single event is fired as a replacement + * for all queued events. In non coalescing mode, a series of + * all queued events is fired. + * This is package-private to avoid an accessor method. + */ + void drainEvents() + { + synchronized (queueLock) + { + if (isCoalesce()) + { + if (queue > 0) + fireActionPerformed(); + } + else + { + while (queue > 0) + { + fireActionPerformed(); + queue--; + } + } + queue = 0; + } + } + + /** + * Post a scheduled event to the event queue. + * Package-private to avoid an accessor method. + */ + void queueEvent() + { + synchronized (queueLock) + { + queue++; + if (queue == 1) + SwingUtilities.invokeLater(drainer); + } + } +} diff --git a/libjava/classpath/javax/swing/ToolTipManager.java b/libjava/classpath/javax/swing/ToolTipManager.java new file mode 100644 index 0000000..6169376 --- /dev/null +++ b/libjava/classpath/javax/swing/ToolTipManager.java @@ -0,0 +1,646 @@ +/* ToolTipManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +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; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; + +/** + * This class is responsible for the registration of JToolTips to Components + * and for displaying them when appropriate. + */ +public class ToolTipManager extends MouseAdapter implements MouseMotionListener +{ + /** + * This ActionListener is associated with the Timer that listens to whether + * the JToolTip can be hidden after four seconds. + */ + protected class stillInsideTimerAction implements ActionListener + { + /** + * This method creates a new stillInsideTimerAction object. + */ + protected stillInsideTimerAction() + { + } + + /** + * This method hides the JToolTip when the Timer has finished. + * + * @param event The ActionEvent. + */ + public void actionPerformed(ActionEvent event) + { + hideTip(); + } + } + + /** + * This Actionlistener is associated with the Timer that listens to whether + * the mouse cursor has re-entered the JComponent in time for an immediate + * redisplay of the JToolTip. + */ + protected class outsideTimerAction implements ActionListener + { + /** + * This method creates a new outsideTimerAction object. + */ + protected outsideTimerAction() + { + } + + /** + * This method is called when the Timer that listens to whether the mouse + * cursor has re-entered the JComponent has run out. + * + * @param event The ActionEvent. + */ + public void actionPerformed(ActionEvent event) + { + } + } + + /** + * This ActionListener is associated with the Timer that listens to whether + * it is time for the JToolTip to be displayed after the mouse has entered + * the JComponent. + */ + protected class insideTimerAction implements ActionListener + { + /** + * This method creates a new insideTimerAction object. + */ + protected insideTimerAction() + { + } + + /** + * This method displays the JToolTip when the Mouse has been still for the + * delay. + * + * @param event The ActionEvent. + */ + public void actionPerformed(ActionEvent event) + { + showTip(); + if (insideTimer != null) + insideTimer.start(); + } + } + + /** + * The Timer that determines whether the Mouse has been still long enough + * for the JToolTip to be displayed. + */ + Timer enterTimer; + + /** + * The Timer that determines whether the Mouse has re-entered the JComponent + * quickly enough for the JToolTip to be displayed immediately. + */ + Timer exitTimer; + + /** + * The Timer that determines whether the JToolTip has been displayed long + * enough for it to be hidden. + */ + Timer insideTimer; + + /** A global enabled setting for the ToolTipManager. */ + private transient boolean enabled = true; + + /** lightWeightPopupEnabled */ + protected boolean lightWeightPopupEnabled = true; + + /** heavyWeightPopupEnabled */ + protected boolean heavyWeightPopupEnabled = false; + + /** The shared instance of the ToolTipManager. */ + private static ToolTipManager shared; + + /** The current component the tooltip is being displayed for. */ + private static Component currentComponent; + + /** The current tooltip. */ + private static JToolTip currentTip; + + /** The last known position of the mouse cursor. */ + private static Point currentPoint; + + /** + * The panel that holds the tooltip when the tooltip is displayed fully + * inside the current container. + */ + private static Container containerPanel; + + /** + * The window used when the tooltip doesn't fit inside the current + * container. + */ + private static JWindow tooltipWindow; + + /** + * Creates a new ToolTipManager and sets up the timers. + */ + ToolTipManager() + { + enterTimer = new Timer(750, new insideTimerAction()); + enterTimer.setRepeats(false); + + insideTimer = new Timer(4000, new stillInsideTimerAction()); + insideTimer.setRepeats(false); + + exitTimer = new Timer(500, new outsideTimerAction()); + exitTimer.setRepeats(false); + } + + /** + * This method returns the shared instance of ToolTipManager used by all + * JComponents. + * + * @return The shared instance of ToolTipManager. + */ + public static ToolTipManager sharedInstance() + { + if (shared == null) + shared = new ToolTipManager(); + + return shared; + } + + /** + * This method sets whether ToolTips are enabled or disabled for all + * JComponents. + * + * @param enabled Whether ToolTips are enabled or disabled for all + * JComponents. + */ + public void setEnabled(boolean enabled) + { + if (! enabled) + { + enterTimer.stop(); + exitTimer.stop(); + insideTimer.stop(); + } + + this.enabled = enabled; + } + + /** + * This method returns whether ToolTips are enabled. + * + * @return Whether ToolTips are enabled. + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * This method returns whether LightweightToolTips are enabled. + * + * @return Whether LighweightToolTips are enabled. + */ + public boolean isLightWeightPopupEnabled() + { + return lightWeightPopupEnabled; + } + + /** + * This method sets whether LightweightToolTips are enabled. If you mix + * Lightweight and Heavyweight components, you must set this to false to + * ensure that the ToolTips popup above all other components. + * + * @param enabled Whether LightweightToolTips will be enabled. + */ + public void setLightWeightPopupEnabled(boolean enabled) + { + lightWeightPopupEnabled = enabled; + heavyWeightPopupEnabled = ! enabled; + } + + /** + * This method returns the initial delay before the ToolTip is shown when + * the mouse enters a Component. + * + * @return The initial delay before the ToolTip is shown. + */ + public int getInitialDelay() + { + return enterTimer.getDelay(); + } + + /** + * This method sets the initial delay before the ToolTip is shown when the + * mouse enters a Component. + * + * @param delay The initial delay before the ToolTip is shown. + */ + public void setInitialDelay(int delay) + { + enterTimer.setDelay(delay); + } + + /** + * This method returns the time the ToolTip will be shown before being + * hidden. + * + * @return The time the ToolTip will be shown before being hidden. + */ + public int getDismissDelay() + { + return insideTimer.getDelay(); + } + + /** + * This method sets the time the ToolTip will be shown before being hidden. + * + * @param delay The time the ToolTip will be shown before being hidden. + */ + public void setDismissDelay(int delay) + { + insideTimer.setDelay(delay); + } + + /** + * This method returns the amount of delay where if the mouse re-enters a + * Component, the tooltip will be shown immediately. + * + * @return The reshow delay. + */ + public int getReshowDelay() + { + return exitTimer.getDelay(); + } + + /** + * This method sets the amount of delay where if the mouse re-enters a + * Component, the tooltip will be shown immediately. + * + * @param delay The reshow delay. + */ + public void setReshowDelay(int delay) + { + exitTimer.setDelay(delay); + } + + /** + * This method registers a JComponent with the ToolTipManager. + * + * @param component The JComponent to register with the ToolTipManager. + */ + public void registerComponent(JComponent component) + { + component.addMouseListener(this); + component.addMouseMotionListener(this); + } + + /** + * This method unregisters a JComponent with the ToolTipManager. + * + * @param component The JComponent to unregister with the ToolTipManager. + */ + public void unregisterComponent(JComponent component) + { + component.removeMouseMotionListener(this); + component.removeMouseListener(this); + } + + /** + * This method is called whenever the mouse enters a JComponent registered + * with the ToolTipManager. When the mouse enters within the period of time + * specified by the reshow delay, the tooltip will be displayed + * immediately. Otherwise, it must wait for the initial delay before + * displaying the tooltip. + * + * @param event The MouseEvent. + */ + public void mouseEntered(MouseEvent event) + { + if (currentComponent != null + && getContentPaneDeepestComponent(event) == currentComponent) + return; + currentPoint = event.getPoint(); + currentComponent = (Component) event.getSource(); + + if (exitTimer.isRunning()) + { + exitTimer.stop(); + showTip(); + insideTimer.start(); + return; + } + + // This should always be stopped unless we have just fake-exited. + if (! enterTimer.isRunning()) + enterTimer.start(); + } + + /** + * This method is called when the mouse exits a JComponent registered with + * the ToolTipManager. When the mouse exits, the tooltip should be hidden + * immediately. + * + * @param event The MouseEvent. + */ + public void mouseExited(MouseEvent event) + { + if (getContentPaneDeepestComponent(event) == currentComponent) + return; + + currentPoint = event.getPoint(); + currentComponent = null; + hideTip(); + + if (! enterTimer.isRunning() && insideTimer.isRunning()) + exitTimer.start(); + if (enterTimer.isRunning()) + enterTimer.stop(); + if (insideTimer.isRunning()) + insideTimer.stop(); + } + + /** + * This method is called when the mouse is pressed on a JComponent + * registered with the ToolTipManager. When the mouse is pressed, the + * tooltip (if it is shown) must be hidden immediately. + * + * @param event The MouseEvent. + */ + public void mousePressed(MouseEvent event) + { + currentPoint = event.getPoint(); + if (enterTimer.isRunning()) + enterTimer.restart(); + else if (insideTimer.isRunning()) + { + insideTimer.stop(); + hideTip(); + } + + if (currentComponent == null) + currentComponent = (Component) event.getSource(); + + currentComponent.invalidate(); + currentComponent.validate(); + currentComponent.repaint(); + } + + /** + * This method is called when the mouse is dragged in a JComponent + * registered with the ToolTipManager. + * + * @param event The MouseEvent. + */ + public void mouseDragged(MouseEvent event) + { + currentPoint = event.getPoint(); + if (enterTimer.isRunning()) + enterTimer.restart(); + } + + /** + * This method is called when the mouse is moved in a JComponent registered + * with the ToolTipManager. + * + * @param event The MouseEvent. + */ + 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(); + } + + /** + * This method displays the ToolTip. It can figure out the method needed to + * show it as well (whether to display it in heavyweight/lightweight panel + * or a window.) This is package-private to avoid an accessor method. + */ + void showTip() + { + if (! enabled || currentComponent == null) + return; + + if (currentTip == null + || currentTip.getComponent() != currentComponent + && currentComponent instanceof JComponent) + currentTip = ((JComponent) currentComponent).createToolTip(); + 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(); + } + else + { + 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(); + } + currentTip.setVisible(true); + } + + /** + * This method hides the ToolTip. + * This is package-private to avoid an accessor method. + */ + void hideTip() + { + if (currentTip == null || ! currentTip.isVisible() || ! enabled) + return; + currentTip.setVisible(false); + if (containerPanel != null) + { + Container parent = containerPanel.getParent(); + 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) + { + tooltipWindow.hide(); + 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; + } + + /** + * This method returns the deepest component in the content pane for the + * first RootPaneContainer up from the currentComponent. This method is + * used in conjunction with one of the mouseXXX methods. + * + * @param e The MouseEvent. + * + * @return The deepest component in the content pane. + */ + private Component getContentPaneDeepestComponent(MouseEvent e) + { + Component source = (Component) e.getSource(); + Container parent = (Container) SwingUtilities.getAncestorOfClass(JRootPane.class, + currentComponent); + if (parent == null) + return null; + parent = ((JRootPane) parent).getContentPane(); + Point p = e.getPoint(); + p = SwingUtilities.convertPoint(source, p, parent); + 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 new file mode 100644 index 0000000..96cb9d4 --- /dev/null +++ b/libjava/classpath/javax/swing/TransferHandler.java @@ -0,0 +1,190 @@ +/* TransferHandler.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.io.Serializable; + +public class TransferHandler implements Serializable +{ + static class TransferAction extends AbstractAction + { + private String command; + + public TransferAction(String command) + { + this.command = command; + } + + public void actionPerformed(ActionEvent event) + { + JComponent component = (JComponent) event.getSource(); + TransferHandler transferHandler = component.getTransferHandler(); + Clipboard clipboard = getClipboard(component); + + if (command.equals(COMMAND_COPY)) + transferHandler.exportToClipboard(component, clipboard, COPY); + else if (command.equals(COMMAND_CUT)) + transferHandler.exportToClipboard(component, clipboard, MOVE); + else if (command.equals(COMMAND_PASTE)) + { + Transferable transferable = clipboard.getContents(null); + + if (transferable != null) + transferHandler.importData(component, transferable); + } + } + + 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; + } + } + + private static final long serialVersionUID = -967749805571669910L; + + private static final String COMMAND_COPY = "copy"; + private static final String COMMAND_CUT = "cut"; + private static final String COMMAND_PASTE = "paste"; + + public static final int NONE = 0; + public static final int COPY = 1; + public static final int MOVE = 2; + public static final int COPY_OR_MOVE = 3; + + private static Action copyAction = new TransferAction(COMMAND_COPY); + private static Action cutAction = new TransferAction(COMMAND_CUT); + private static Action pasteAction = new TransferAction(COMMAND_PASTE); + + /** + * Clipboard if system clipboard may not be used. + * Package-private to avoid an accessor method. + */ + static Clipboard clipboard; + + private int sourceActions; + private Icon visualRepresentation; + + public static Action getCopyAction() + { + return copyAction; + } + + public static Action getCutAction() + { + return cutAction; + } + + public static Action getPasteAction() + { + return pasteAction; + } + + protected TransferHandler() + { + this.sourceActions = NONE; + } + + public TransferHandler(String property) + { + this.sourceActions = property != null ? COPY : NONE; + } + + public boolean canImport (JComponent c, DataFlavor[] flavors) + { + return false; + } + + protected Transferable createTransferable(JComponent c) + { + return null; + } + + public void exportAsDrag (JComponent c, InputEvent e, int action) + { + } + + protected void exportDone (JComponent c, Transferable data, int action) + { + } + + public void exportToClipboard(JComponent c, Clipboard clip, int action) + { + } + + public int getSourceActions (JComponent c) + { + return sourceActions; + } + + public Icon getVisualRepresentation (Transferable t) + { + return visualRepresentation; + } + + public boolean importData (JComponent c, Transferable t) + { + return false; + } +} diff --git a/libjava/classpath/javax/swing/UIDefaults.java b/libjava/classpath/javax/swing/UIDefaults.java new file mode 100644 index 0000000..06fee05 --- /dev/null +++ b/libjava/classpath/javax/swing/UIDefaults.java @@ -0,0 +1,842 @@ +/* UIDefaults.java -- database for all settings and interface bindings. + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Insets; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.lang.reflect.Method; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; + +/** + * UIDefaults is a database where all settings and interface bindings are + * stored into. A PLAF implementation fills one of these (see for example + * plaf/basic/BasicLookAndFeel.java) with "ButtonUI" -> new BasicButtonUI(). + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public class UIDefaults extends Hashtable +{ + + /** Our ResourceBundles. */ + private LinkedList bundles; + + /** The default locale. */ + private Locale defaultLocale; + + /** We use this for firing PropertyChangeEvents. */ + private PropertyChangeSupport propertyChangeSupport; + + /** + * Used for lazy instantiation of UIDefaults values so that they are not + * all loaded when a Swing application starts up, but only the values that + * are really needed. An ActiveValue is newly instantiated + * every time when the value is requested, as opposed to the normal + * {@link LazyValue} that is only instantiated once. + */ + public static interface ActiveValue + { + Object createValue(UIDefaults table); + } + + public static class LazyInputMap implements LazyValue + { + Object[] bind; + public LazyInputMap(Object[] bindings) + { + bind = bindings; + } + public Object createValue(UIDefaults table) + { + InputMap im = new InputMap (); + for (int i = 0; 2*i+1 < bind.length; ++i) + { + im.put (KeyStroke.getKeyStroke ((String) bind[2*i]), + bind[2*i+1]); + } + return im; + } + } + + /** + * Used for lazy instantiation of UIDefaults values so that they are not + * all loaded when a Swing application starts up, but only the values that + * are really needed. A LazyValue is only instantiated once, + * as opposed to the {@link ActiveValue} that is newly created every time + * it is requested. + */ + public static interface LazyValue + { + Object createValue(UIDefaults table); + } + + public static class ProxyLazyValue implements LazyValue + { + LazyValue inner; + public ProxyLazyValue(String s) + { + final String className = s; + inner = new LazyValue () + { + public Object createValue (UIDefaults table) + { + try + { + return Class + .forName(className) + .getConstructor(new Class[] {}) + .newInstance(new Object[] {}); + } + catch (Exception e) + { + return null; + } + } + }; + } + + public ProxyLazyValue(String c, String m) + { + final String className = c; + final String methodName = m; + inner = new LazyValue () + { + public Object createValue (UIDefaults table) + { + try + { + return Class + .forName (className) + .getMethod (methodName, new Class[] {}) + .invoke (null, new Object[] {}); + } + catch (Exception e) + { + return null; + } + } + }; + } + + public ProxyLazyValue(String c, Object[] os) + { + final String className = c; + final Object[] objs = os; + final Class[] clss = new Class[objs.length]; + for (int i = 0; i < objs.length; ++i) + { + clss[i] = objs[i].getClass(); + } + inner = new LazyValue() + { + public Object createValue(UIDefaults table) + { + try + { + return Class + .forName(className) + .getConstructor(clss) + .newInstance(objs); + } + catch (Exception e) + { + return null; + } + } + }; + } + + public ProxyLazyValue(String c, String m, Object[] os) + { + final String className = c; + final String methodName = m; + final Object[] objs = os; + final Class[] clss = new Class[objs.length]; + for (int i = 0; i < objs.length; ++i) + { + clss[i] = objs[i].getClass(); + } + inner = new LazyValue() + { + public Object createValue(UIDefaults table) + { + try + { + return Class + .forName(className) + .getMethod(methodName, clss) + .invoke(null, objs); + } + catch (Exception e) + { + return null; + } + } + }; + } + + public Object createValue(UIDefaults table) + { + return inner.createValue(table); + } + } + + /** Our serialVersionUID for serialization. */ + private static final long serialVersionUID = 7341222528856548117L; + + /** + * Constructs a new empty UIDefaults instance. + */ + public UIDefaults() + { + bundles = new LinkedList(); + defaultLocale = Locale.getDefault(); + propertyChangeSupport = new PropertyChangeSupport(this); + } + + /** + * Constructs a new UIDefaults instance and loads the specified entries. + * The entries are expected to come in pairs, that means + * entries[0] is a key, entries[1] is a value, + * entries[2] a key and so forth. + * + * @param entries the entries to initialize the UIDefaults instance with + */ + public UIDefaults(Object[] entries) + { + this(); + + for (int i = 0; (2 * i + 1) < entries.length; ++i) + put(entries[2 * i], entries[2 * i + 1]); + } + + /** + * Returns the entry for the specified key in the default + * locale. + * + * @return the entry for the specified key + */ + public Object get(Object key) + { + return this.get(key, getDefaultLocale()); + } + + /** + * Returns the entry for the specified key in the Locale + * loc. + * + * @param key the key for which we return the value + * @param loc the locale + */ + public Object get(Object key, Locale loc) + { + Object obj = null; + + if (super.containsKey(key)) + { + obj = super.get(key); + } + else if (key instanceof String) + { + String keyString = (String) key; + ListIterator i = bundles.listIterator(0); + while (i.hasNext()) + { + String bundle_name = (String) i.next(); + ResourceBundle res = + ResourceBundle.getBundle(bundle_name, loc); + if (res != null) + { + try + { + obj = res.getObject(keyString); + break; + } + catch (MissingResourceException me) + { + // continue, this bundle has no such key + } + } + } + } + + // now we've found the object, resolve it. + // nb: LazyValues aren't supported in resource bundles, so it's correct + // to insert their results in the locale-less hashtable. + + if (obj == null) + return null; + + if (obj instanceof LazyValue) + { + Object resolved = ((LazyValue) obj).createValue(this); + super.remove(key); + super.put(key, resolved); + return resolved; + } + else if (obj instanceof ActiveValue) + { + return ((ActiveValue) obj).createValue(this); + } + + return obj; + } + + /** + * Puts a key and value into this UIDefaults object.
+ * In contrast to + * {@link java.util.Hashtable}s null-values are accepted + * here and treated like #remove(key). + *
+ * This fires a PropertyChangeEvent with key as name and the old and new + * values. + * + * @param key the key to put into the map + * @param value the value to put into the map + * + * @return the old value for key or null if key + * had no value assigned + */ + public Object put(Object key, Object value) + { + Object old = checkAndPut(key, value); + + if (key instanceof String && old != value) + firePropertyChange((String) key, old, value); + return old; + } + + /** + * Puts a set of key-value pairs into the map. + * The entries are expected to come in pairs, that means + * entries[0] is a key, entries[1] is a value, + * entries[2] a key and so forth. + *
+ * If a value is null it is treated like #remove(key). + *
+ * This unconditionally fires a PropertyChangeEvent with + * 'UIDefaults' as name and null for + * old and new value. + * + * @param entries the entries to be put into the map + */ + public void putDefaults(Object[] entries) + { + for (int i = 0; (2 * i + 1) < entries.length; ++i) + { + checkAndPut(entries[2 * i], entries[2 * i + 1]); + } + firePropertyChange("UIDefaults", null, null); + } + + /** + * Checks the value for null and put it into the Hashtable, if + * it is not null. If the value is null then + * remove the corresponding key. + * + * @param key the key to put into this UIDefauls table + * @param value the value to put into this UIDefaults table + * + * @return the old value for key + */ + private Object checkAndPut(Object key, Object value) + { + Object old; + + if (value != null) + old = super.put(key, value); + else + old = super.remove(key); + + return old; + } + + /** + * Returns a font entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the font entry for key or null if no such entry + * exists + */ + public Font getFont(Object key) + { + Object o = get(key); + return o instanceof Font ? (Font) o : null; + } + + /** + * Returns a font entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the font entry for key or null if no such entry + * exists + */ + public Font getFont(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Font ? (Font) o : null; + } + + /** + * Returns a color entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the color entry for key or null if no such entry + * exists + */ + public Color getColor(Object key) + { + Object o = get(key); + return o instanceof Color ? (Color) o : null; + } + + /** + * Returns a color entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the color entry for key or null if no such entry + * exists + */ + public Color getColor(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Color ? (Color) o : null; + } + + /** + * Returns an icon entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the icon entry for key or null if no such entry + * exists + */ + public Icon getIcon(Object key) + { + Object o = get(key); + return o instanceof Icon ? (Icon) o : null; + } + + /** + * Returns an icon entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the icon entry for key or null if no such entry + * exists + */ + public Icon getIcon(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Icon ? (Icon) o : null; + } + + /** + * Returns a border entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the border entry for key or null if no such entry + * exists + */ + public Border getBorder(Object key) + { + Object o = get(key); + return o instanceof Border ? (Border) o : null; + } + + /** + * Returns a border entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the border entry for key or null if no such entry + * exists + */ + public Border getBorder(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Border ? (Border) o : null; + } + + /** + * Returns a string entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the string entry for key or null if no such entry + * exists + */ + public String getString(Object key) + { + Object o = get(key); + return o instanceof String ? (String) o : null; + } + + /** + * Returns a string entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the string entry for key or null if no such entry + * exists + */ + public String getString(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof String ? (String) o : null; + } + + /** + * Returns an integer entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the integer entry for key or null if no such entry + * exists + */ + public int getInt(Object key) + { + Object o = get(key); + return o instanceof Integer ? ((Integer) o).intValue() : 0; + } + + /** + * Returns an integer entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the integer entry for key or null if no such entry + * exists + */ + public int getInt(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Integer ? ((Integer) o).intValue() : 0; + } + + /** + * Returns a boolean entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the boolean entry for key or null if no such entry + * exists + */ + public boolean getBoolean(Object key) + { + return Boolean.TRUE.equals(get(key)); + } + + /** + * Returns a boolean entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the boolean entry for key or null if no such entry + * exists + */ + public boolean getBoolean(Object key, Locale l) + { + return Boolean.TRUE.equals(get(key, l)); + } + + /** + * Returns an insets entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the insets entry for key or null if no such entry + * exists + */ + public Insets getInsets(Object key) + { + Object o = get(key); + return o instanceof Insets ? (Insets) o : null; + } + + /** + * Returns an insets entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the boolean entry for key or null if no such entry + * exists + */ + public Insets getInsets(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Insets ? (Insets) o : null; + } + + /** + * Returns a dimension entry for the default locale. + * + * @param key the key to the requested entry + * + * @return the dimension entry for key or null if no such entry + * exists + */ + public Dimension getDimension(Object key) + { + Object o = get(key); + return o instanceof Dimension ? (Dimension) o : null; + } + + /** + * Returns a dimension entry for a specic locale. + * + * @param key the key to the requested entry + * @param locale the locale to the requested entry + * + * @return the boolean entry for key or null if no such entry + * exists + */ + public Dimension getDimension(Object key, Locale l) + { + Object o = get(key, l); + return o instanceof Dimension ? (Dimension) o : null; + } + + /** + * Returns the ComponentUI class that renders a component. id + * is the ID for which the String value of the classname is stored in + * this UIDefaults map. + * + * @param id the ID of the UI class + * @param loader the ClassLoader to use + * + * @return the UI class for id + */ + public Class getUIClass(String id, ClassLoader loader) + { + String className = (String) get (id); + if (className == null) + return null; + try + { + if (loader != null) + return loader.loadClass (className); + return Class.forName (className); + } + catch (Exception e) + { + return null; + } + } + + /** + * Returns the ComponentUI class that renders a component. id + * is the ID for which the String value of the classname is stored in + * this UIDefaults map. + * + * @param id the ID of the UI class + * + * @return the UI class for id + */ + public Class getUIClass(String id) + { + return getUIClass (id, null); + } + + /** + * If a key is requested in #get(key) that has no value, this method + * is called before returning null. + * + * @param msg the error message + */ + protected void getUIError(String msg) + { + System.err.println ("UIDefaults.getUIError: " + msg); + } + + /** + * Returns the {@link ComponentUI} for the specified {@link JComponent}. + * + * @param target the component for which the ComponentUI is requested + * + * @return the {@link ComponentUI} for the specified {@link JComponent} + */ + public ComponentUI getUI(JComponent target) + { + String classId = target.getUIClassID (); + Class cls = getUIClass (classId); + if (cls == null) + { + getUIError ("failed to locate UI class:" + classId); + return null; + } + + Method factory; + + try + { + factory = cls.getMethod ("createUI", new Class[] { JComponent.class } ); + } + catch (NoSuchMethodException nme) + { + getUIError ("failed to locate createUI method on " + cls.toString ()); + return null; + } + + try + { + return (ComponentUI) factory.invoke (null, new Object[] { target }); + } + catch (java.lang.reflect.InvocationTargetException ite) + { + getUIError ("InvocationTargetException ("+ ite.getTargetException() + +") calling createUI(...) on " + cls.toString ()); + return null; + } + catch (Exception e) + { + getUIError ("exception calling createUI(...) on " + cls.toString ()); + return null; + } + } + + /** + * Adds a {@link PropertyChangeListener} to this UIDefaults map. + * Registered PropertyChangeListener are notified when values + * are beeing put into this UIDefaults map. + * + * @param listener the PropertyChangeListener to add + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * Removes a PropertyChangeListener from this UIDefaults map. + * + * @param listener the PropertyChangeListener to remove + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + propertyChangeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns an array of all registered PropertyChangeListeners. + * + * @return all registered PropertyChangeListeners + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return propertyChangeSupport.getPropertyChangeListeners(); + } + + /** + * Fires a PropertyChangeEvent. + * + * @param property the property name + * @param oldValue the old value + * @param newValue the new value + */ + protected void firePropertyChange(String property, + Object oldValue, Object newValue) + { + propertyChangeSupport.firePropertyChange(property, oldValue, newValue); + } + + /** + * Adds a ResourceBundle for localized values. + * + * @param name the name of the ResourceBundle to add + */ + public void addResourceBundle(String name) + { + bundles.addFirst(name); + } + + /** + * Removes a ResourceBundle. + * + * @param name the name of the ResourceBundle to remove + */ + public void removeResourceBundle(String name) + { + bundles.remove(name); + } + + /** + * Sets the current locale to loc. + * + * @param loc the Locale to be set + */ + public void setDefaultLocale(Locale loc) + { + defaultLocale = loc; + } + + /** + * Returns the current default locale. + * + * @return the current default locale + */ + public Locale getDefaultLocale() + { + return defaultLocale; + } +} diff --git a/libjava/classpath/javax/swing/UIManager.java b/libjava/classpath/javax/swing/UIManager.java new file mode 100644 index 0000000..7f6d65e --- /dev/null +++ b/libjava/classpath/javax/swing/UIManager.java @@ -0,0 +1,491 @@ +/* UIManager.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Insets; +import java.beans.PropertyChangeListener; +import java.io.Serializable; +import java.util.Locale; + +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalLookAndFeel; + +public class UIManager implements Serializable +{ + public static class LookAndFeelInfo + { + String name, clazz; + + public LookAndFeelInfo(String name, + String clazz) + { + this.name = name; + this.clazz = clazz; + } + + public String getName() + { + return name; + } + + public String getClassName() + { + return clazz; + } + + /** + * Returns a String representation of the LookAndFeelInfo object. + * + * @return a String representation of the LookAndFeelInfo object + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append(getClass().getName()); + s.append('['); + s.append(getName()); + s.append(' '); + s.append(getClassName()); + s.append(']'); + return s.toString(); + } + } + + private static final long serialVersionUID = -5547433830339189365L; + + static LookAndFeelInfo [] installed = { + new LookAndFeelInfo ("Metal", "javax.swing.plaf.metal.MetalLookAndFeel") + }; + + static LookAndFeel[] aux_installed; + + static LookAndFeel look_and_feel = new MetalLookAndFeel(); + + static + { + String defaultlaf = System.getProperty("swing.defaultlaf"); + try { + if (defaultlaf != null) + { + Class lafClass = Class.forName(defaultlaf); + LookAndFeel laf = (LookAndFeel) lafClass.newInstance(); + setLookAndFeel(laf); + } + } + catch (Exception ex) + { + System.err.println("cannot initialize Look and Feel: " + defaultlaf); + System.err.println("errot: " + ex.getMessage()); + System.err.println("falling back to Metal Look and Feel"); + } + } + + public UIManager() + { + // Do nothing here. + } + + /** + * Add a PropertyChangeListener to the listener list. + * + * @param listener the listener to add + */ + public static void addPropertyChangeListener(PropertyChangeListener listener) + { + // FIXME + } + + /** + * Remove a PropertyChangeListener from the listener list. + * + * @param listener the listener to remove + */ + public static void removePropertyChangeListener(PropertyChangeListener listener) + { + // FIXME + } + + /** + * Returns an array of all added PropertyChangeListener objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public static PropertyChangeListener[] getPropertyChangeListeners() + { + // FIXME + throw new Error ("Not implemented"); + } + + /** + * Add a LookAndFeel to the list of auxiliary look and feels. + */ + public static void addAuxiliaryLookAndFeel (LookAndFeel l) + { + if (aux_installed == null) + { + aux_installed = new LookAndFeel[1]; + aux_installed[0] = l; + return; + } + + LookAndFeel[] T = new LookAndFeel[ aux_installed.length+1 ]; + System.arraycopy(aux_installed, 0, T, 0, aux_installed.length); + aux_installed = T; + aux_installed[aux_installed.length-1] = l; + } + + public static boolean removeAuxiliaryLookAndFeel(LookAndFeel laf) + { + if (aux_installed == null) + return false; + + for (int i=0;ifalse
if key is not present. + * + * @since 1.4 + */ + public static boolean getBoolean(Object key) + { + Boolean value = (Boolean) getLookAndFeel().getDefaults().get(key); + return value != null ? value.booleanValue() : false; + } + + /** + * Returns a boolean value from the defaults table, + * false if key is not present. + * + * @since 1.4 + */ + public static boolean getBoolean(Object key, Locale locale) + { + Boolean value = (Boolean) getLookAndFeel().getDefaults().get(key, locale); + return value != null ? value.booleanValue() : false; + } + + /** + * Returns a border from the defaults table. + */ + public static Border getBorder(Object key) + { + return (Border) getLookAndFeel().getDefaults().get(key); + } + + /** + * Returns a border from the defaults table. + * + * @since 1.4 + */ + public static Border getBorder(Object key, Locale locale) + { + return (Border) getLookAndFeel().getDefaults().get(key, locale); + } + + /** + * Returns a drawing color from the defaults table. + */ + public static Color getColor(Object key) + { + return (Color) getLookAndFeel().getDefaults().get(key); + } + + /** + * Returns a drawing color from the defaults table. + */ + public static Color getColor(Object key, Locale locale) + { + return (Color) getLookAndFeel().getDefaults().get(key); + } + + /** + * this string can be passed to Class.forName() + */ + public static String getCrossPlatformLookAndFeelClassName() + { + return "javax.swing.plaf.metal.MetalLookAndFeel"; + } + + /** + * Returns the default values for this look and feel. + */ + public static UIDefaults getDefaults() + { + return getLookAndFeel().getDefaults(); + } + + /** + * Returns a dimension from the defaults table. + */ + public static Dimension getDimension(Object key) + { + return (Dimension) getLookAndFeel().getDefaults().get(key); + } + + /** + * Returns a dimension from the defaults table. + */ + public static Dimension getDimension(Object key, Locale locale) + { + return (Dimension) getLookAndFeel().getDefaults().get(key, locale); + } + + /** + * Retrieves a font from the defaults table of the current + * LookAndFeel. + * + * @param key an Object that specifies the font. Typically, + * this is a String such as + * TitledBorder.font. + */ + public static Font getFont(Object key) + { + return (Font) getLookAndFeel().getDefaults().get(key); + } + + /** + * Retrieves a font from the defaults table of the current + * LookAndFeel. + * + * @param key an Object that specifies the font. Typically, + * this is a String such as + * TitledBorder.font. + */ + public static Font getFont(Object key, Locale locale) + { + return (Font) getLookAndFeel().getDefaults().get(key ,locale); + } + + /** + * Returns an Icon from the defaults table. + */ + public static Icon getIcon(Object key) + { + return (Icon) getLookAndFeel().getDefaults().get(key); + } + + /** + * Returns an Icon from the defaults table. + */ + public static Icon getIcon(Object key, Locale locale) + { + return (Icon) getLookAndFeel().getDefaults().get(key, locale); + } + + /** + * Returns an Insets object from the defaults table. + */ + public static Insets getInsets(Object key) + { + return (Insets) getLookAndFeel().getDefaults().getInsets(key); + } + + /** + * Returns an Insets object from the defaults table. + */ + public static Insets getInsets(Object key, Locale locale) + { + return (Insets) getLookAndFeel().getDefaults().getInsets(key, locale); + } + + public static LookAndFeelInfo[] getInstalledLookAndFeels() + { + return installed; + } + + public static int getInt(Object key) + { + Integer x = (Integer) getLookAndFeel().getDefaults().get(key); + if (x == null) + return 0; + return x.intValue(); + } + + public static int getInt(Object key, Locale locale) + { + Integer x = (Integer) getLookAndFeel().getDefaults().get(key, locale); + if (x == null) + return 0; + return x.intValue(); + } + + public static LookAndFeel getLookAndFeel() + { + return look_and_feel; + } + + /** + * Returns the UIDefaults table of the currently active + * look and feel. + */ + public static UIDefaults getLookAndFeelDefaults() + { + return getLookAndFeel().getDefaults(); + } + + /** + * Returns a string from the defaults table. + */ + public static String getString(Object key) + { + return (String) getLookAndFeel().getDefaults().get(key); + } + + /** + * Returns a string from the defaults table. + */ + public static String getString(Object key, Locale locale) + { + return (String) getLookAndFeel().getDefaults().get(key, locale); + } + + /** + * Returns the name of the LookAndFeel class that implements the + * native systems look and feel if there is one, otherwise the name + * of the default cross platform LookAndFeel class. + */ + public static String getSystemLookAndFeelClassName() + { + return getCrossPlatformLookAndFeelClassName(); + } + + /** + * Returns the Look and Feel object that renders the target component. + */ + public static ComponentUI getUI(JComponent target) + { + return getDefaults().getUI(target); + } + + /** + * Creates a new look and feel and adds it to the current array. + */ + public static void installLookAndFeel(String name, String className) + { + } + + /** + * Adds the specified look and feel to the current array and then calls + * setInstalledLookAndFeels(javax.swing.UIManager.LookAndFeelInfo[]). + */ + public static void installLookAndFeel(LookAndFeelInfo info) + { + } + + /** + * Stores an object in the defaults table. + */ + public static Object put(Object key, Object value) + { + return getLookAndFeel().getDefaults().put(key,value); + } + + /** + * Replaces the current array of installed LookAndFeelInfos. + */ + public static void setInstalledLookAndFeels(UIManager.LookAndFeelInfo[] infos) + { + } + + /** + * Set the current default look. + */ + public static void setLookAndFeel(LookAndFeel newLookAndFeel) + throws UnsupportedLookAndFeelException + { + if (! newLookAndFeel.isSupportedLookAndFeel()) + throw new UnsupportedLookAndFeelException(newLookAndFeel.getName()); + + if (look_and_feel != null) + look_and_feel.uninitialize(); + + // Set the current default look and feel using a LookAndFeel object. + look_and_feel = newLookAndFeel; + look_and_feel.initialize(); + + //revalidate(); + //repaint(); + } + + /** + * Set the current default look and feel using a class name. + */ + public static void setLookAndFeel (String className) + throws ClassNotFoundException, InstantiationException, IllegalAccessException, + UnsupportedLookAndFeelException + { + Class c = Class.forName(className); + LookAndFeel a = (LookAndFeel) c.newInstance(); // throws class-cast-exception + setLookAndFeel(a); + } +} diff --git a/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java new file mode 100644 index 0000000..5abe45f --- /dev/null +++ b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java @@ -0,0 +1,47 @@ +/* UnsupportedLookAndFeelException.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + + +public class UnsupportedLookAndFeelException extends Exception +{ + public UnsupportedLookAndFeelException(String a) + { + super(a); + } +} diff --git a/libjava/classpath/javax/swing/ViewportLayout.java b/libjava/classpath/javax/swing/ViewportLayout.java new file mode 100644 index 0000000..18b4912 --- /dev/null +++ b/libjava/classpath/javax/swing/ViewportLayout.java @@ -0,0 +1,169 @@ +/* ViewportLayout.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.io.Serializable; + +/** + * ViewportLayout + * @author Andrew Selkirk + * @author Graydon Hoare + */ +public class ViewportLayout implements LayoutManager, Serializable +{ + private static final long serialVersionUID = -788225906076097229L; + + public ViewportLayout() + { + } + public void addLayoutComponent(String name, Component c) + { + } + public void removeLayoutComponent(Component c) + { + } + + public Dimension preferredLayoutSize(Container parent) + { + JViewport vp = (JViewport)parent; + Component view = vp.getView(); + if (view != null) + return view.getPreferredSize(); + else + return new Dimension(); + } + + public Dimension minimumLayoutSize(Container parent) + { + JViewport vp = (JViewport)parent; + Component view = vp.getView(); + if (view != null) + return view.getMinimumSize(); + else + return new Dimension(); + } + + /** + * Layout the view and viewport to respect the following rules. These are + * not precisely the rules described in sun's javadocs, but they are the + * rules which sun's swing implementation follows, if you watch its + * behavior: + * + *
    + * + *
  1. If the port is larger than the view's minimum size, put the port + * at view position (0,0) and make the view's size equal to + * the port's.
  2. + * + *
  3. If the port is smaller than the view, leave the view at its + * minimum size. also, do not move the port, unless the port + * extends into space past the edge of the view. If so, move the + * port up or to the left, in view space, by the amount of empty space + * (keep the lower and right edges lined up)
  4. + * + *
+ * + * @see JViewport#getViewSize + * @see JViewport#setViewSize + * @see JViewport#getViewPosition + * @see JViewport#setViewPosition + */ + + public void layoutContainer(Container parent) + { + // The way to interpret this function is basically to ignore the names + // of methods it calls, and focus on the variable names here. getViewRect + // doesn't, for example, return the view; it returns the port bounds in + // view space. Likwise setViewPosition doesn't reposition the view; it + // positions the port, in view coordinates. + + JViewport port = (JViewport) parent; + Component view = port.getView(); + + if (view == null) + return; + + // These dimensions and positions are in *view space*. Do not mix + // variables in here from port space (eg. parent.getBounds()). This + // function should be entirely in view space, because the methods on + // the viewport require inputs in view space. + + Rectangle portBounds = port.getViewRect(); + Dimension viewPref = view.getPreferredSize(); + Dimension viewMinimum = view.getMinimumSize(); + Point portLowerRight = new Point(portBounds.x + portBounds.width, + portBounds.y + portBounds.height); + + // vertical implementation of the above rules + if (portBounds.height >= viewMinimum.height) + { + portBounds.y = 0; + viewPref.height = portBounds.height; + } + else + { + viewPref.height = viewMinimum.height; + int overextension = portLowerRight.y - viewPref.height; + if (overextension > 0) + portBounds.y -= overextension; + } + + // horizontal implementation of the above rules + if (portBounds.width >= viewMinimum.width) + { + portBounds.x = 0; + viewPref.width = portBounds.width; + } + else + { + viewPref.width = viewMinimum.width; + int overextension = portLowerRight.x - viewPref.width; + if (overextension > 0) + portBounds.x -= overextension; + } + + port.setViewPosition(portBounds.getLocation()); + port.setViewSize(viewPref); + } +} diff --git a/libjava/classpath/javax/swing/WindowConstants.java b/libjava/classpath/javax/swing/WindowConstants.java new file mode 100644 index 0000000..5e36443 --- /dev/null +++ b/libjava/classpath/javax/swing/WindowConstants.java @@ -0,0 +1,73 @@ +/* WindowConstants.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing; + +/** + * Defines some constants that are used in Swing's top-level + * containers. + * + * @author Andrew Selkirk + */ +public interface WindowConstants { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * DO_NOTHING_ON_CLOSE + */ + int DO_NOTHING_ON_CLOSE = 0; + + /** + * HIDE_ON_CLOSE + */ + int HIDE_ON_CLOSE = 1; + + /** + * 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 new file mode 100644 index 0000000..d755b67 --- /dev/null +++ b/libjava/classpath/javax/swing/border/AbstractBorder.java @@ -0,0 +1,192 @@ +/* AbstractBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.io.Serializable; + + +/** + * An invisible zero-width border, serving as a base class for + * implementing more interesting borders. + * + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Ronald Veldema (rveldema@cs.vu.nl) + */ +public abstract class AbstractBorder + implements Border, Serializable +{ + static final long serialVersionUID = -545885975315191844L; + + + /** + * Constructs a new AbstractBorder. + */ + public AbstractBorder () + { + } + + + /** + * Performs nothing, because the default implementation provided by + * this class is an invisible, zero-width border. Subclasses will + * likely want to override this method, but they are not required + * for doing so. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + 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. + */ + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom 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 new Insets (0, 0, 0, 0); + } + + + /** + * Determines the insets of this border. The implementation provided + * by AbstractButton sets the left, right, + * top and bottom fields of the passed + * insets parameter to zero. + * + * @param c the component whose border is to be measured. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + 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 + * translucent borders must return false, or ugly + * artifacts can appear on screen. The default implementation + * provided by AbstractBorder always returns false. + * + * @return false. + */ + 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 + * they can safely draw without intersecting with a border might + * want to use this helper method. + * + * @param c the component in the center of this border. + * @param x the horizontal position of the border. + * @param y the vertical position of the border. + * @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) + { + return getInteriorRectangle (c, this, x, y, width, height); + } + + + /** + * Returns a rectangle that covers the specified area minus a + * border. Components that wish to determine an area into which + * they can safely draw without intersecting with a border might + * want to use this helper method. + * + * @param c the component in the center of this border. + * @param x the horizontal position of the border. + * @param y the vertical position of the border. + * @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) + { + Insets borderInsets; + + if (b != null) + { + borderInsets = b.getBorderInsets (c); + x += borderInsets.left; + y += borderInsets.top; + width -= borderInsets.left + borderInsets.right; + height -= borderInsets.top + borderInsets.bottom; + } + + return new Rectangle (x, y, width, height); + } +} diff --git a/libjava/classpath/javax/swing/border/BevelBorder.java b/libjava/classpath/javax/swing/border/BevelBorder.java new file mode 100644 index 0000000..e755fdc --- /dev/null +++ b/libjava/classpath/javax/swing/border/BevelBorder.java @@ -0,0 +1,568 @@ +/* BevelBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * A rectangular, two pixel thick border that causes the enclosed area + * to appear as if it was raising out of or lowered into the screen. Some + * LookAndFeels use this kind of border for rectangular buttons. + * + *

A BevelBorder has a highlight and a shadow color. In the raised + * variant, the highlight color is used for the top and left edges, + * and the shadow color is used for the bottom and right edge. For an + * image, see the documentation of the individual constructors. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BevelBorder + extends AbstractBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -1034942243356299676L; + + + /** + * Indicates that the BevelBorder looks like if the enclosed area was + * raising out of the screen. + */ + public static final int RAISED = 0; + + + /** + * Indicates that the BevelBorder looks like if the enclosed area was + * pressed into the screen. + */ + public static final int LOWERED = 1; + + + /** + * The type of this BevelBorder, which is either {@link #RAISED} + * or {@link #LOWERED}. + */ + protected int bevelType; + + + /** + * The outer highlight color, or null to indicate that + * the color shall be derived from the background of the component + * whose border is being painted. + */ + protected Color highlightOuter; + + + /** + * The inner highlight color, or null to indicate that + * the color shall be derived from the background of the component + * whose border is being painted. + */ + protected Color highlightInner; + + + /** + * The outer shadow color, or null to indicate that the + * color shall be derived from the background of the component whose + * border is being painted. + */ + protected Color shadowOuter; + + + /** + * The inner shadow color, or null to indicate that the + * color shall be derived from the background of the component whose + * border is being painted. + */ + protected Color shadowInner; + + + /** + * Constructs a BevelBorder whose colors will be derived from the + * background of the enclosed component. The background color is + * retrieved each time the border is painted, so a BevelBorder + * constructed by this method will automatically reflect a change + * to the component’s background color. + * + *

[An illustration showing raised and lowered BevelBorders] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link #RAISED} or {@link #LOWERED}. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + */ + public BevelBorder(int bevelType) + { + if ((bevelType != RAISED) && (bevelType != LOWERED)) + throw new IllegalArgumentException(); + + this.bevelType = bevelType; + } + + + /** + * Constructs a BevelBorder given its appearance type and two colors + * for its highlight and shadow. + * + *

[An illustration showing BevelBorders that were constructed
+   * with this method] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link #RAISED} or {@link #LOWERED}. + * + * @param highlight the color that will be used for the inner + * side of the highlighted edges (top and left if + * if bevelType is {@link #RAISED}; bottom + * and right otherwise). The color for the outer side + * is a brightened version of this color. + * + * @param shadow the color that will be used for the outer + * side of the shadowed edges (bottom and right + * if bevelType is {@link #RAISED}; top + * and left otherwise). The color for the inner side + * is a brightened version of this color. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + * + * @throws NullPointerException if highlight or + * shadow is null. + * + * @see java.awt.Color.brighter() + */ + public BevelBorder(int bevelType, Color highlight, Color shadow) + { + this(bevelType, + /* highlightOuter */ highlight.brighter(), + /* highlightInner */ highlight, + /* shadowOuter */ shadow, + /* shadowInner */ shadow.brighter()); + } + + + /** + * Constructs a BevelBorder given its appearance type and all + * colors. + * + *

[An illustration showing BevelBorders that were constructed
+   * with this method] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link #RAISED} or {@link #LOWERED}. + * + * @param highlightOuter the color that will be used for the outer + * side of the highlighted edges (top and left if + * bevelType is {@link #RAISED}; bottom and + * right otherwise). + * + * @param highlightInner the color that will be used for the inner + * side of the highlighted edges. + * + * @param shadowOuter the color that will be used for the outer + * side of the shadowed edges (bottom and right + * if bevelType is {@link #RAISED}; top + * and left otherwise). + * + * @param shadowInner the color that will be used for the inner + * side of the shadowed edges. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + * + * @throws NullPointerException if one of the passed colors + * is null. + */ + public BevelBorder(int bevelType, + Color highlightOuter, Color highlightInner, + Color shadowOuter, Color shadowInner) + { + this(bevelType); // checks the validity of bevelType + + if ((highlightOuter == null) || (highlightInner == null) + || (shadowOuter == null) || (shadowInner == null)) + throw new NullPointerException(); + + this.highlightOuter = highlightOuter; + this.highlightInner = highlightInner; + this.shadowOuter = shadowOuter; + this.shadowInner = shadowInner; + } + + + /** + * Paints the border for a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + switch (bevelType) + { + case RAISED: + paintRaisedBevel(c, g, x, y, width, height); + break; + + case LOWERED: + paintLoweredBevel(c, g, x, y, width, height); + break; + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + + + /** + * Determines the color that will be used for the outer side of + * highlighted edges when painting the border. If a highlight color + * has been specified upon constructing the border, that color is + * returned. Otherwise, the inner highlight color is brightened. + * + * @param c the component enclosed by this border. + * + * @see #getHighlightInnerColor(java.awt.Component) + * @see java.awt.Color#brighter() + */ + public Color getHighlightOuterColor(Component c) + { + if (highlightOuter != null) + return highlightOuter; + else + return getHighlightInnerColor(c).brighter(); + } + + + /** + * Determines the color that will be used for the inner side of + * highlighted edges when painting the border. If a highlight color + * has been specified upon constructing the border, that color is + * returned. Otherwise, the background color of the enclosed + * component is brightened. + * + * @param c the component enclosed by this border. + * + * @see java.awt.Component#getBackground() + * @see java.awt.Color#brighter() + */ + public Color getHighlightInnerColor(Component c) + { + if (highlightInner != null) + return highlightInner; + else + return c.getBackground().brighter(); + } + + + /** + * Determines the color that will be used for the inner side of + * shadowed edges when painting the border. If a shadow color has + * been specified upon constructing the border, that color is + * returned. Otherwise, the background color of the enclosed + * component is darkened. + * + * @param c the component enclosed by this border. + * + * @see java.awt.Component#getBackground() + * @see java.awt.Color#darker() + */ + public Color getShadowInnerColor(Component c) + { + if (shadowInner != null) + return shadowInner; + else + return c.getBackground().darker(); + } + + + /** + * Determines the color that will be used for the outer side of + * shadowed edges when painting the border. If a shadow color + * has been specified upon constructing the border, that color is + * returned. Otherwise, the inner shadow color is darkened. + * + * @param c the component enclosed by this border. + * + * @see #getShadowInnerColor(java.awt.Component) + * @see java.awt.Color#darker() + */ + public Color getShadowOuterColor(Component c) + { + if (shadowOuter != null) + return shadowOuter; + else + return getShadowInnerColor(c).darker(); + } + + + /** + * Returns the color that will be used for the outer side of + * highlighted edges when painting the border, or null + * if that color will be derived from the background of the enclosed + * Component. + */ + public Color getHighlightOuterColor() + { + return highlightOuter; + } + + + /** + * Returns the color that will be used for the inner side of + * highlighted edges when painting the border, or null + * if that color will be derived from the background of the enclosed + * Component. + */ + public Color getHighlightInnerColor() + { + return highlightInner; + } + + + /** + * Returns the color that will be used for the inner side of + * shadowed edges when painting the border, or null if + * that color will be derived from the background of the enclosed + * Component. + */ + public Color getShadowInnerColor() + { + return shadowInner; + } + + + /** + * Returns the color that will be used for the outer side of + * shadowed edges when painting the border, or null if + * that color will be derived from the background of the enclosed + * Component. + */ + public Color getShadowOuterColor() + { + return shadowOuter; + } + + + /** + * Returns the appearance of this border, which is either {@link + * #RAISED} or {@link #LOWERED}. + */ + public int getBevelType() + { + return bevelType; + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + *

If the border colors are derived from the background color of + * the enclosed component, the result is true because + * the derivation method always returns opaque colors. Otherwise, + * the result depends on the opacity of the individual colors. + * + * @return true if the border is fully opaque, or + * false if some pixels of the background + * can shine through the border. + */ + 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. + */ + return + ((highlightOuter == null) || (highlightOuter.getAlpha() == 255)) + && ((highlightInner == null) || (highlightInner.getAlpha() == 255)) + && ((shadowInner == null) || (shadowInner.getAlpha() == 255)) + && ((shadowOuter == null) ||(shadowOuter.getAlpha() == 255)); + } + + + /** + * Paints a raised bevel border around a component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + protected void paintRaisedBevel(Component c, Graphics g, + int x, int y, int width, int height) + { + paintBevel(g, x, y, width, height, + getHighlightOuterColor(c), getHighlightInnerColor(c), + getShadowInnerColor(c), getShadowOuterColor(c)); + } + + + /** + * Paints a lowered bevel border around a component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + protected void paintLoweredBevel(Component c, Graphics g, + int x, int y, int width, int height) + { + paintBevel(g, x, y, width, height, + getShadowInnerColor(c), getShadowOuterColor(c), + getHighlightInnerColor(c), getHighlightOuterColor(c)); + } + + + /** + * Paints a two-pixel bevel in four colors. + * + *

+   * @@@@@@@@@@@@
+   * @..........#    @ = color a
+   * @.        X#    . = color b
+   * @.        X#    X = color c
+   * @.XXXXXXXXX#    # = color d
+   * ############
+ * + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * @param a the color for the outer side of the top and left edges. + * @param b the color for the inner side of the top and left edges. + * @param c the color for the inner side of the bottom and right edges. + * @param d the color for the outer side of the bottom and right edges. + */ + private static void paintBevel(Graphics g, + int x, int y, int width, int height, + Color a, Color b, Color c, Color d) + { + Color oldColor; + + oldColor = g.getColor(); + g.translate(x, y); + width = width - 1; + height = height - 1; + + 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. + */ + g.setColor(a); + g.drawLine(0, 0, width, 0); // a, horizontal + g.drawLine(0, 1, 0, height); // a, vertical + + g.setColor(b); + g.drawLine(1, 1, width - 1, 1); // b, horizontal + g.drawLine(1, 2, 1, height - 1); // b, vertical + + g.setColor(c); + g.drawLine(2, height - 1, width - 1, height - 1); // c, horizontal + g.drawLine(width - 1, 2, width - 1, height - 2); // c, vertical + + g.setColor(d); + g.drawLine(1, height, width, height); // d, horizontal + g.drawLine(width, 1, width, height - 1); // d, vertical + } + finally + { + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} + diff --git a/libjava/classpath/javax/swing/border/Border.java b/libjava/classpath/javax/swing/border/Border.java new file mode 100644 index 0000000..11bddfe --- /dev/null +++ b/libjava/classpath/javax/swing/border/Border.java @@ -0,0 +1,105 @@ +/* Border.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * An public interface for decorative or spacing borders around a Component. + * + *

To reduce memory consumption, several Components may share a + * single Border instance. {@link javax.swing.BorderFactory} is a + * factory class for producing commonly used shared borders. + * + * @see javax.swing.BorderFactory + * @see EmptyBorder + * @see CompoundBorder + * @see BevelBorder + * @see EtchedBorder + * @see LineBorder + * @see MatteBorder + * @see SoftBevelBorder + * @see TitledBorder + * @see AbstractBorder + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Michael Koch (konqueror@gmx.de) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public interface Border +{ + /** + * Paints the border for a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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); + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + */ + Insets getBorderInsets(Component c); + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return true if the border is fully opaque, or + * false if some pixels of the background + * can shine through the border. + */ + boolean isBorderOpaque(); +} diff --git a/libjava/classpath/javax/swing/border/CompoundBorder.java b/libjava/classpath/javax/swing/border/CompoundBorder.java new file mode 100644 index 0000000..2130a0e --- /dev/null +++ b/libjava/classpath/javax/swing/border/CompoundBorder.java @@ -0,0 +1,257 @@ +/* CompoundBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + +/** + * A Border that is composed of an interior and an exterior border, + * where the interior border is tightly nested into the exterior. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class CompoundBorder + extends AbstractBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 9054540377030555103L; + + + /** + * The inside border, which is painted between the bordered + * Component and the outside border. It is valid for + * insideBorder to be null. + */ + protected Border insideBorder; + + + /** + * The outside border, which is painted outside both the + * bordered Component and the inside border. It is valid for + * outsideBorder to be null. + */ + protected Border outsideBorder; + + + /** + * Constructs a CompoundBorder whose inside and outside borders + * are both null. While this does not really make + * any sense (there exists a class EmptyBorder as well, and not + * every Component needs to have a border at all), the API + * specification requires the existence of this constructor. + * + * @see EmptyBorder + */ + public CompoundBorder () + { + this (null, null); + } + + + /** + * Constructs a CompoundBorder with the specified inside and + * outside borders. + * + * @param outsideBorder the outside border, which is painted to the + * outside of both insideBorder and the enclosed + * component. It is acceptable to pass null, in + * which case no outside border is painted. + * + * @param insideBorder the inside border, which is painted to + * between outsideBorder and the enclosed + * component. It is acceptable to pass null, in + * which case no inside border is painted. + */ + 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 + * translucent borders must return false, or ugly + * artifacts can appear on screen. + * + * @return true if both the inside and outside borders + * are opaque, or false otherwise. + */ + 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. + */ + if ((insideBorder == null) || (outsideBorder == null)) + return false; + + return insideBorder.isBorderOpaque() + && outsideBorder.isBorderOpaque(); + } + + + /** + * Paints the compound border by first painting the outside border, + * then painting the inside border tightly nested into the outside. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + 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 (outsideBorder != null) + { + Insets outsideInsets; + + outsideBorder.paintBorder(c, g, x, y, width, height); + outsideInsets = outsideBorder.getBorderInsets(c); + + x += outsideInsets.left; + y += outsideInsets.top; + + /* Reduce width and height by the respective extent of the + * outside border. + */ + width -= outsideInsets.left + outsideInsets.right; + height -= outsideInsets.top + outsideInsets.bottom; + } + + if (insideBorder != null) + 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 + * border. + * + * @param c the component in the center of this border. + * @param insets an Insets object for holding the added insets. + * + * @return the insets object. + */ + public Insets getBorderInsets(Component c, Insets insets) + { + Insets borderInsets; + + if (insets == null) + insets = new Insets (0,0,0,0); + else + insets.left = insets.right = insets.top = insets.bottom = 0; + + /* If there is an outside border, add it to insets. */ + if (outsideBorder != null) + { + borderInsets = outsideBorder.getBorderInsets(c); + insets.left += borderInsets.left; + insets.right += borderInsets.right; + insets.top += borderInsets.top; + insets.bottom += borderInsets.bottom; + } + + /* If there is an inside border, add it to insets. */ + if (insideBorder != null) + { + borderInsets = insideBorder.getBorderInsets(c); + insets.left += borderInsets.left; + insets.right += borderInsets.right; + insets.top += borderInsets.top; + insets.bottom += borderInsets.bottom; + } + + 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) + { + /* 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 null. + */ + 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 + * be null. + */ + public Border getInsideBorder () + { + return insideBorder; + } +} + diff --git a/libjava/classpath/javax/swing/border/EmptyBorder.java b/libjava/classpath/javax/swing/border/EmptyBorder.java new file mode 100644 index 0000000..0f3b7b6 --- /dev/null +++ b/libjava/classpath/javax/swing/border/EmptyBorder.java @@ -0,0 +1,223 @@ +/* EmptyBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * A border for leaving a specifiable number of pixels empty around + * the enclosed component. An EmptyBorder requires some space on each + * edge, but does not perform any drawing. + * + *

[An illustration of EmptyBorder] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class EmptyBorder + extends AbstractBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -8116076291731988694L; + + + /** + * The number of pixels required at the left edge. + */ + protected int left; + + + /** + * The number of pixels required at the right edge. + */ + protected int right; + + + /** + * The number of pixels required at the top edge. + */ + protected int top; + + + /** + * The number of pixels required at the bottom edge. + */ + protected int bottom; + + + /** + * Constructs an empty border given the number of pixels required + * on each side. + * + * @param top the number of pixels that the border will need + * for its top edge. + * + * @param left the number of pixels that the border will need + * for its left edge. + * + * @param bottom the number of pixels that the border will need + * for its bottom edge. + * + * @param right the number of pixels that the border will need + * for its right edge. + */ + public EmptyBorder(int top, int left, int bottom, int right) + { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + + /** + * Constructs an empty border given the number of pixels required + * on each side, passed in an Insets object. + * + * @param borderInsets the Insets for the new border. + */ + public EmptyBorder(Insets borderInsets) + { + this(borderInsets.top, borderInsets.left, + borderInsets.bottom, borderInsets.right); + } + + + /** + * Performs nothing because an EmptyBorder does not paint any + * pixels. While the inherited implementation provided by + * {@link AbstractBorder#paintBorder} is a no-op as well, + * it is overwritten in order to match the API of the Sun + * reference implementation. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + if (insets == null) + insets = new Insets(0, 0, 0, 0); + + insets.left = left; + insets.right = right; + insets.top = top; + insets.bottom = bottom; + return insets; + } + + + /** + * Measures the width of this border. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets() + { + return getBorderInsets(null, null); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. Since an empty border does not paint any pixels + * whatsoever, the result is false. + * + * @return false. + */ + public boolean isBorderOpaque() + { + /* The inherited implementation of AbstractBorder.isBorderOpaque() + * would also return false. It is not clear why this is overriden + * in the Sun implementation, at least not from just reading the + * JavaDoc. + */ + return false; + } +} diff --git a/libjava/classpath/javax/swing/border/EtchedBorder.java b/libjava/classpath/javax/swing/border/EtchedBorder.java new file mode 100644 index 0000000..ea2a61d --- /dev/null +++ b/libjava/classpath/javax/swing/border/EtchedBorder.java @@ -0,0 +1,411 @@ +/* EtchedBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * A border that looks like an engraving etched into the background + * surface, or (in its raised variant) coming out of the surface + * plane. Using different constructors, it is possible to either + * explicitly specify the border colors, or to let the colors derive + * from the background color of the enclosed Component. + * + *

[An illustration of the two EtchedBorder variants] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class EtchedBorder + extends AbstractBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 4001244046866360638L; + + + /** + * Indicates that the border appears as coming out of the + * background. + */ + public static final int RAISED = 0; + + + /** + * Indicates that the border appears as engraved into the + * background. + */ + public static final int LOWERED = 1; + + + /** + * The type of this EtchedBorder, which is either {@link #RAISED} + * or {@link #LOWERED}. + */ + protected int etchType; + + + /** + * The highlight color, or null to indicate that the + * color shall be derived from the background of the enclosed + * component. + */ + protected Color highlight; + + + /** + * The shadow color, or null to indicate that the + * color shall be derived from the background of the enclosed + * component. + */ + protected Color shadow; + + + /** + * Constructs a lowered EtchedBorder. The colors will be derived + * from the background color of the enclosed Component when the + * border gets painted. + */ + public EtchedBorder() + { + this(LOWERED); + } + + + /** + * Constructs an EtchedBorder with the specified appearance. The + * colors will be derived from the background color of the enclosed + * Component when the border gets painted. + * + *

[An illustration of the two EtchedBorder variants] + * + * @param etchType the desired appearance of the border. The value + * must be either {@link #RAISED} or {@link #LOWERED}. + * + * @throws IllegalArgumentException if etchType has + * an unsupported value. + */ + public EtchedBorder(int etchType) + { + if ((etchType != RAISED) && (etchType != LOWERED)) + throw new IllegalArgumentException(); + + this.etchType = etchType; + + /* The highlight and shadow fields already have a null value + * when the constructor gets called, so there is no need to + * assign a value here. + */ + } + + + /** + * Constructs a lowered EtchedBorder, explicitly selecting the + * colors that will be used for highlight and shadow. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @see #EtchedBorder(int, Color, Color) + */ + public EtchedBorder(Color highlight, Color shadow) + { + this(LOWERED, highlight, shadow); + } + + + /** + * Constructs an EtchedBorder with the specified appearance, + * explicitly selecting the colors that will be used for + * highlight and shadow. + * + *

[An illustration that shows which pixels get painted
+   * in what color] + * + * @param etchType the desired appearance of the border. The value + * must be either {@link #RAISED} or {@link #LOWERED}. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @throws IllegalArgumentException if etchType has + * an unsupported value. + */ + public EtchedBorder(int etchType, Color highlight, Color shadow) + { + this(etchType); // Checks the validity of the value. + this.highlight = highlight; + this.shadow = shadow; + } + + + /** + * Paints the border for a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + switch (etchType) + { + case RAISED: + paintEtchedBorder(g, x, y, width, height, + getHighlightColor(c), getShadowColor(c)); + break; + + case LOWERED: + paintEtchedBorder(g, x, y, width, height, + getShadowColor(c), getHighlightColor(c)); + break; + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + *

If the border colors are derived from the background color of + * the enclosed component, the result is true because + * the derivation method always returns opaque colors. Otherwise, + * the result depends on the opacity of the individual colors. + * + * @return true if the border is fully opaque, or + * false if some pixels of the background + * can shine through the border. + */ + 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. + */ + return + ((highlight == null) || (highlight.getAlpha() == 255)) + && ((shadow == null) || (shadow.getAlpha() == 255)); + } + + + /** + * Returns the appearance of this EtchedBorder, which is either + * {@link #RAISED} or {@link #LOWERED}. + */ + public int getEtchType() + { + return etchType; + } + + + /** + * Determines the color that will be used for highlighted parts when + * painting the border around a given component. If a highlight + * color has been specified upon constructing the border, that color + * is returned. Otherwise, the background color of the enclosed + * component is brightened. + * + * @param c the component enclosed by this border. + * + * @see java.awt.Component#getBackground() + * @see java.awt.Color#brighter() + */ + public Color getHighlightColor(Component c) + { + if (highlight != null) + return highlight; + else + return c.getBackground().brighter(); + } + + + /** + * Returns the color that will be used for highlighted parts when + * painting the border, or null if that color will be + * derived from the background of the enclosed Component. + */ + public Color getHighlightColor() + { + return highlight; + } + + + /** + * Determines the color that will be used for shadowed parts when + * painting the border around a given component. If a shadow color + * has been specified upon constructing the border, that color is + * returned. Otherwise, the background color of the enclosed + * component is darkened. + * + * @param c the component enclosed by this border. + * + * @see java.awt.Component#getBackground() + * @see java.awt.Color#darker() + */ + public Color getShadowColor(Component c) + { + if (shadow != null) + return shadow; + else + return c.getBackground().darker(); + } + + + /** + * Returns the color that will be used for shadowed parts when + * painting the border, or null if that color will be + * derived from the background of the enclosed Component. + */ + public Color getShadowColor() + { + return shadow; + } + + + /** + * Paints a two-pixel etching in two colors. + * + *

+   * @@@@@@@@@@@.
+   * @.........@.    @ = color a
+   * @.        @.    . = color b
+   * @.        @.
+   * @@@@@@@@@@@.
+   * ............
+ * + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * @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) + { + Color oldColor; + + oldColor = g.getColor(); + g.translate(x, y); + width = width - 1; + height = height - 1; + + 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. + */ + g.setColor(a); + g.drawRect(0, 0, width - 1, height - 1); + + g.setColor(b); + g.drawLine(1, 1, width - 2, 1); // top edge + g.drawLine(1, 2, 1, height - 2); // left edge + g.drawLine(0, height, width, height); // bottom edge + g.drawLine(width, 0, width, height - 1); // right edge + } + finally + { + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} + diff --git a/libjava/classpath/javax/swing/border/LineBorder.java b/libjava/classpath/javax/swing/border/LineBorder.java new file mode 100644 index 0000000..00c1634 --- /dev/null +++ b/libjava/classpath/javax/swing/border/LineBorder.java @@ -0,0 +1,343 @@ +/* LineBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * A border that consists of a line whose thickness and color can be + * specified. There also is a variant with rounded corners. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class LineBorder + extends AbstractBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -787563427772288970L; + + + /** + * A shared instance of a black, one pixel thick, plain LineBorder. + * The singleton object is lazily created by {@link + * #createBlackLineBorder()} upon its first invocation. + */ + private static LineBorder blackLineBorder; + + + /** + * A shared instance of a gray, one pixel thick, plain LineBorder. + * The singleton object is lazily created by {@link + * #createBlackGrayBorder()} upon its first invocation. + */ + private static LineBorder grayLineBorder; + + + /** + * The width of the line in pixels. + */ + protected int thickness; + + + /** + * The color of the line. + */ + protected Color lineColor; + + + /** + * Indicates whether the line is drawn with rounded corners + * (true) or not ((false). + */ + protected boolean roundedCorners; + + + /** + * Constructs a LineBorder given its color. The border will be one + * pixel thick and have plain corners. + * + * @param color the color for drawing the border. + * + * @see #LineBorder(java.awt.Color, int, boolean) + */ + public LineBorder(Color color) + { + this(color, /* thickness */ 1, /* roundedCorners */ false); + } + + + /** + * Constructs a LineBorder given its color and thickness. The + * border will have plain corners. + * + * @param color the color for drawing the border. + * @param thickness the width of the line in pixels. + * + * @see #LineBorder(java.awt.Color, int, boolean) + */ + public LineBorder(Color color, int thickness) + { + this (color, thickness, /* roundedCorners */ false); + } + + + /** + * Constructs a LineBorder given its color, thickness, and whether + * it has rounded corners. + * + *

[An illustration of two LineBorders] + * + *

Note that the enlarged view in the right-hand picture shows + * that the implementation draws one more pixel than specified, + * provided that roundedCorders is true + * and anti-aliasing is turned on while painting. While this might + * be considered a bug, the Sun reference implementation (at least + * JDK 1.3.1 on Apple MacOS X 10.1.5) can be observed to fill + * exactly the same pixels as shown above. The GNU Classpath + * LineBorder replicates the observed behavior of the Sun + * implementation. + * + * @param color the color for drawing the border. + * @param thickness the width of the line in pixels. + * @param roundedCorners true for rounded corners, + * false for plain corners. + * + * @since 1.3 + */ + // For the bug mentioned in the JavaDoc, please see also the comment + // in the paintBorder method below. + // + public LineBorder(Color color, int thickness, boolean roundedCorners) + { + if ((color == null) || (thickness < 0)) + throw new IllegalArgumentException(); + + this.lineColor = color; + this.thickness = thickness; + this.roundedCorners = roundedCorners; + } + + + /** + * Returns a black, one pixel thick, plain LineBorder. The method + * may always return the same (singleton) LineBorder instance. + */ + public static Border createBlackLineBorder() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (blackLineBorder == null) + blackLineBorder = new LineBorder(Color.black); + + return blackLineBorder; + } + + + /** + * Returns a gray, one pixel thick, plain LineBorder. The method + * may always return the same (singleton) LineBorder instance. + */ + public static Border createGrayLineBorder() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (grayLineBorder == null) + grayLineBorder = new LineBorder(Color.gray); + + return grayLineBorder; + } + + + /** + * Paints the line border around a given Component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Color oldColor = g.getColor(); + + try + { + g.setColor(lineColor); + + /* 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. + */ + for (int i = 0; i < thickness; i++) + { + if (roundedCorners) + g.drawRoundRect(x, y, width, height, thickness, thickness); + else + g.drawRect(x, y, width, height); + + x += 1; + y += 1; + width -= 2; + height -= 2; + } + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge, which is the + * thickness of the line. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return new Insets(thickness, thickness, thickness, thickness); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge, which is the thickness + * of the line. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + insets.left = insets.right = insets.top = insets.bottom = thickness; + return insets; + } + + + /** + * Returns the color of the line. + */ + public Color getLineColor() + { + return lineColor; + } + + + /** + * Returns the thickness of the line in pixels. + */ + public int getThickness() + { + return thickness; + } + + + /** + * Returns whether this LineBorder os drawm with rounded + * or with plain corners. + * + * @return true if the corners are rounded, + * false if the corners are plain. + */ + public boolean getRoundedCorners() + { + return roundedCorners; + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return true if the corners are plain and the line + * color is fully opaque; false if the corners + * are rounded or the line color is partially transparent. + */ + public boolean isBorderOpaque() + { + return (!roundedCorners) && (lineColor.getAlpha() == 255); + } +} + diff --git a/libjava/classpath/javax/swing/border/MatteBorder.java b/libjava/classpath/javax/swing/border/MatteBorder.java new file mode 100644 index 0000000..f7ff1ca --- /dev/null +++ b/libjava/classpath/javax/swing/border/MatteBorder.java @@ -0,0 +1,404 @@ +/* MatteBorder.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.Icon; + +/** + * A border that is filled with either a solid color or with repeated + * icon tiles. + * + *

[Two MatteBorders] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class MatteBorder + extends EmptyBorder +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 4422248989617298224L; + + + /** + * The color that is used for filling the border, or + * null if the border is filled with repetitions of a + * tile icon. + * + * @see #tileIcon + */ + protected Color color; + + + /** + * The icon is used for filling the border with a tile, or + * null if the border is filled with a solid + * color. + * + * @see #color + */ + protected Icon tileIcon; + + + /** + * Constructs a MatteBorder given the width on each side + * and a fill color. + * + *

[A picture of a MatteBorder made by this constructor] + * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param matteColor the color for filling the border. + */ + public MatteBorder(int top, int left, int bottom, int right, + Color matteColor) + { + super(top, left, bottom, right); + + if (matteColor == null) + throw new IllegalArgumentException(); + + this.color = matteColor; + } + + + /** + * Constructs a MatteBorder given its insets and fill color. + * + *

[A picture of a MatteBorder made by this constructor] + * + * @param borderInsets an Insets object whose top, + * left, bottom and right + * fields indicate the with of the border at the respective + * edge. + * + * @param matteColor the color for filling the border. + */ + public MatteBorder(Insets borderInsets, Color matteColor) + { + this(borderInsets.top, borderInsets.left, + borderInsets.bottom, borderInsets.right, + matteColor); + } + + + /** + * Constructs a MatteBorder given the width on each side + * and an icon for tiling the border area. + * + *

[A picture of a MatteBorder made by this constructor] + * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorder(int top, int left, int bottom, int right, + Icon tileIcon) + { + super(top, left, bottom, right); + + if (tileIcon == null) + throw new IllegalArgumentException(); + + this.tileIcon = tileIcon; + } + + + /** + * Constructs a MatteBorder given its insets and an icon + * for tiling the border area. + * + *

[A picture of a MatteBorder made by this constructor] + * + * @param borderInsets an Insets object whose top, + * left, bottom and right + * fields indicate the with of the border at the respective + * edge. + * + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorder(Insets borderInsets, Icon tileIcon) + { + this(borderInsets.top, borderInsets.left, + borderInsets.bottom, borderInsets.right, + tileIcon); + } + + + /** + * Constructs a MatteBorder given an icon for tiling the + * border area. The icon width is used for the border insets + * at the left and right edge, the icon height for the top and + * bottom edge. + * + *

[A picture of a MatteBorder made by this constructor] + * + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorder(Icon tileIcon) + { + this(-1, -1, -1, -1, tileIcon); + } + + + /** + * Paints the border for a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Insets i = getBorderInsets(); + paintEdge(c, g, x, y, width, i.top, 0, 0); // top edge + paintEdge(c, g, x, y + height - i.bottom, // bottom edge + width, i.bottom, + 0, height - i.bottom); + paintEdge(c, g, x, y + i.top, // left edge + i.left, height - i.top, + 0, i.top); + paintEdge(c, g, x + width - i.right, y + i.top, // right edge + i.right, height - i.bottom, + width - i.right, i.top); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return this.getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + if (insets == null) + insets = new Insets(0, 0, 0, 0); + + if ((tileIcon != null) + && (top < 0) && (left < 0) + && (right < 0) && (bottom < 0)) + { + insets.left = insets.right = tileIcon.getIconWidth(); + insets.top = insets.bottom = tileIcon.getIconHeight(); + return insets; + } + + /* Copy top, left, bottom and right into the respective + * field of insets. + */ + return super.getBorderInsets(c, insets); + } + + + /** + * Measures the width of this border. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets() + { + /* The inherited implementation of EmptyBorder.isBorderOpaque() + * would do the same. It is not clear why this is overriden in the + * Sun implementation, at least not from just reading the JavaDoc. + */ + return this.getBorderInsets(null, null); + } + + + /** + * Returns the color that is used for filling the border, or + * null if the border is filled with repetitions of a + * tile icon. + */ + public Color getMatteColor() + { + return color; + } + + + /** + * Returns the icon is used for tiling the border, or + * null if the border is filled with a color instead of + * an icon. + */ + public Icon getTileIcon() + { + return tileIcon; + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return true if the border is filled with an + * opaque color; false if it is filled with + * a semi-transparent color or with an icon. + */ + public boolean isBorderOpaque() + { + return (color != null) && (color.getAlpha() == 255); + } + + + /** + * Paints a rectangular area of the border. This private helper + * method is called once for each of the border edges + * by {@link #paintBorder}. + * + * @param c the component whose border is being painted. + * @param g the graphics for painting. + * @param x the horizontal position of the rectangular area. + * @param y the vertical position of the rectangular area. + * @param width the width of the rectangular area. + * @param height the height of the rectangular area. + * @param dx the x displacement for repeating the tile. + * @param dy the y displacement for repeating the tile. + */ + private void paintEdge(Component c, Graphics g, + int x, int y, int width, int height, + int dx, int dy) + { + Color oldColor; + int iconWidth, iconHeight; + Graphics clipped; + + if ((width <= 0) || (height <= 0)) + return; + + /* Paint a colored rectangle if desired. */ + if (color != null) + { + oldColor = g.getColor(); + try + { + g.setColor(color); + g.fillRect(x, y, width, height); + } + finally + { + g.setColor(oldColor); + } + return; + } + + /* Determine the width and height of the icon. Some icons return + * -1 if it is an image whose dimensions have not yet been + * retrieved. There is not much we can do about this, but we + * should at least avoid entering the paint loop below + * with negative increments. + */ + iconWidth = tileIcon.getIconWidth(); + iconHeight = tileIcon.getIconHeight(); + if ((iconWidth <= 0) || (iconHeight <= 0)) + return; + + dx = dx % iconWidth; + dy = dy % iconHeight; + + clipped = g.create(); + try + { + clipped.setClip(x, y, width, height); + for (int ty = y - dy; ty < y + height; ty += iconHeight) + for (int tx = x - dx; tx < x + width; tx += iconWidth) + tileIcon.paintIcon(c, clipped, tx, ty); + } + finally + { + clipped.dispose(); + } + } +} + diff --git a/libjava/classpath/javax/swing/border/SoftBevelBorder.java b/libjava/classpath/javax/swing/border/SoftBevelBorder.java new file mode 100644 index 0000000..fa718e3 --- /dev/null +++ b/libjava/classpath/javax/swing/border/SoftBevelBorder.java @@ -0,0 +1,329 @@ +/* SoftBevelBorder.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + + +/** + * A rectangular, three pixel thick border that looks like a BevelBorder + * with slightly softened corners. + * + *

Like BevelBorder, SoftBevelBorder has a highlight and a shadow + * color. In the raised variant, the highlight color is used for the + * top and left edges, and the shadow color is used for the bottom and + * right edge. In the lowered variant, color usage is reversed. For + * an image, see the documentation of the individual constructors. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class SoftBevelBorder + extends BevelBorder +{ + /** + * Determined using the serialver tool + * of Sun JDK 1.4.1_01 on GNU/Linux 2.4.20. Interestingly, + * the Apple/Sun JDK 1.3.1 on MacOS X 10.1.5 gives a different + * value, namely -6658357140774549493L. + */ + static final long serialVersionUID = 5248789787305979975L; + + + /** + * Constructs a SoftBevelBorder whose colors will be derived from the + * background of the enclosed component. The background color is + * retrieved each time the border is painted, so a SoftBevelBorder + * constructed by this method will automatically reflect a change + * to the component’s background color. + * + *

[An illustration showing raised and lowered SoftBevelBorders] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link BevelBorder#RAISED} + * or {@link BevelBorder#LOWERED}. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + */ + public SoftBevelBorder(int bevelType) + { + super(bevelType); + } + + + /** + * Constructs a SoftBevelBorder given its appearance type and two + * colors for its highlight and shadow. + * + *

[An illustration showing SoftBevelBorders that were
+   * constructed with this method] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link BevelBorder#RAISED} or {@link + * BevelBorder#LOWERED}. + * + * @param highlight the color that will be used for the inner side + * of the highlighted edges (top and left if if + * bevelType is {@link BevelBorder#RAISED}; + * bottom and right otherwise). The color for the outer side + * is a brightened version of this color. + * + * @param shadow the color that will be used for the outer side of + * the shadowed edges (bottom and right if + * bevelType is {@link BevelBorder#RAISED}; top + * and left otherwise). The color for the inner side is a + * brightened version of this color. + * + * @throws IllegalArgumentException if bevelType has an + * unsupported value. + * + * @throws NullPointerException if highlight or + * shadow is null. + * + * @see java.awt.Color.brighter() + */ + public SoftBevelBorder(int bevelType, Color highlight, Color shadow) + { + this(bevelType, + /* highlightOuter */ highlight.brighter(), + /* highlightInner */ highlight, + /* shadowOuter */ shadow, + /* shadowInner */ shadow.brighter()); + } + + + /** + * Constructs a SoftBevelBorder given its appearance type and all + * colors. + * + *

[An illustration showing SoftBevelBorders that were
+   * constructed with this method] + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link BevelBorder#RAISED} or {@link + * BevelBorder#LOWERED}. + * + * @param highlightOuter the color that will be used for the outer + * side of the highlighted edges (top and left if + * bevelType is {@link BevelBorder#RAISED}; + * bottom and right otherwise). + * + * @param highlightInner the color that will be used for the inner + * side of the highlighted edges. + * + * @param shadowOuter the color that will be used for the outer side + * of the shadowed edges (bottom and right if + * bevelType is {@link BevelBorder#RAISED}; top + * and left otherwise). + * + * @param shadowInner the color that will be used for the inner + * side of the shadowed edges. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + * + * @throws NullPointerException if one of the passed colors + * is null. + */ + public SoftBevelBorder(int bevelType, + Color highlightOuter, Color highlightInner, + Color shadowOuter, Color shadowInner) + { + super(bevelType, + highlightOuter, highlightInner, + shadowOuter, shadowInner); + } + + + /** + * Paints the border for a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + switch (bevelType) + { + case RAISED: + paintSoftBevel(g, x, y, width, height, + getHighlightOuterColor(c), getHighlightInnerColor(c), + getShadowInnerColor(c), getShadowOuterColor(c)); + break; + + case LOWERED: + paintSoftBevel(g, x, y, width, height, + getShadowOuterColor(c), getShadowInnerColor(c), + getHighlightInnerColor(c), getHighlightOuterColor(c)); + break; + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return new Insets(3, 3, 3, 3); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + insets.left = insets.right = insets.top = insets.bottom = 3; + return insets; + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + *

The enlarged view (see documentation for constructors) shows + * that a SoftBevelBorder does not paint all pixels. Therefore, + * this method always returns false. + * + * @return false. + */ + public boolean isBorderOpaque() + { + return false; + } + + + /** + * Paints a soft bevel in four colors. + * + *

+   * @@@@@@@@@@@.
+   * @@.........#    @ = color a
+   * @..        #    . = color b
+   * @.         #    X = color c
+   * ..        X#    # = color d
+   * . ##########
+ * + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * @param a the color for the outer side of the top and left edges. + * @param b the color for the inner side of the top and left edges. + * @param c the color for the inner side of the bottom and right edges. + * @param d the color for the outer side of the bottom and right edges. + */ + private static void paintSoftBevel(Graphics g, + int x, int y, int width, int height, + Color a, Color b, Color c, Color d) + { + Color oldColor; + + oldColor = g.getColor(); + g.translate(x, y); + width = width - 1; + height = height - 1; + + try + { + /* To understand this code, it might be helpful to look at the + * images that are included with the JavaDoc, especially + * SoftBevelBorder-3.png. They are located in the "doc-files" + * subdirectory. + */ + g.setColor(a); + g.drawLine(0, 0, width - 1, 0); // a, horizontal + g.drawLine(0, 1, 2, 1); // a, horizontal + g.drawLine(0, 2, 0, height - 1); // a, vertical + + g.setColor(b); + g.drawLine(width, 0, width, 0); // b, horizontal + g.drawLine(2, 1, width - 1, 1); // b, horizontal + g.drawLine(1, 2, 2, 2); // b, horizontal + g.drawLine(1, 3, 1, height - 1); // b, vertical + g.drawLine(0, height - 1, 0, height); // b, vertical + + g.setColor(c); + g.drawLine(width - 1, height - 1, // c, one pixel + width - 1, height - 1); + + g.setColor(d); + g.drawLine(2, height, width, height); // d, horizontal + g.drawLine(width, 2, width, height - 1); // d, vertical + } + finally + { + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} + diff --git a/libjava/classpath/javax/swing/border/TitledBorder.java b/libjava/classpath/javax/swing/border/TitledBorder.java new file mode 100644 index 0000000..30e4bcd --- /dev/null +++ b/libjava/classpath/javax/swing/border/TitledBorder.java @@ -0,0 +1,1155 @@ +/* TitledBorder.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Shape; + +import javax.swing.UIManager; + + +/** + * A border that paints a title on top of another border. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class TitledBorder + extends AbstractBorder +{ + /** + * A value for the titlePosition property that vertically + * positions the title text at the default vertical position, which + * is in the middle of the top line of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int DEFAULT_POSITION = 0; + + + /** + * A value for the titlePosition property that vertically + * positions the title text above the top line of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int ABOVE_TOP = 1; + + + /** + * A value for the titlePosition property that vertically + * positions the title text at the middle of the top line + * of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int TOP = 2; + + + /** + * A value for the titlePosition property that vertically + * positions the title text below the top line of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int BELOW_TOP = 3; + + + /** + * A value for the titlePosition property that vertically + * positions the title text above the bottom line of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int ABOVE_BOTTOM = 4; + + + /** + * A value for the titlePosition property that vertically + * positions the title text at the center of the bottom line + * of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int BOTTOM = 5; + + + /** + * A value for the titlePosition property that vertically + * positions the title text below the bottom line of the border. + * + * @see #getTitlePosition() + * @see #setTitlePosition(int) + */ + public static final int BELOW_BOTTOM = 6; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with either the left or the + * right edge of the border, depending on the orientation of the + * component nested into the border. If the component orientation + * is left-to-right, the title text is aligned with the left edge; + * otherwise, it is aligned with the right edge. This is the same + * behavior as with {@link #LEADING}. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + * @see java.awt.ComponentOrientation#isLeftToRight() + */ + public static final int DEFAULT_JUSTIFICATION = 0; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with the left-hand edge of + * the border. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + */ + public static final int LEFT = 1; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with the center of the border. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + */ + public static final int CENTER = 2; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with the right-hand edge of + * the border. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + */ + public static final int RIGHT = 3; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with either the left or the + * right edge of the border, depending on the orientation of the + * component nested into the border. If the component orientation + * is left-to-right, the title text is aligned with the left edge; + * otherwise, it is aligned with the right edge. This is the same + * behavior as with {@link #DEFAULT_JUSTIFICATION}. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + * @see java.awt.ComponentOrientation#isLeftToRight() + */ + public static final int LEADING = 4; + + + /** + * A value for the titleJustification property that + * horizontally aligns the title text with either the right or the + * left edge of the border, depending on the orientation of the + * component nested into the border. If the component orientation + * is left-to-right, the title text is aligned with the right edge; + * otherwise, it is aligned with the left edge. + * + * @see #getTitleJustification() + * @see #setTitleJustification(int) + * @see java.awt.ComponentOrientation#isLeftToRight() + */ + public static final int TRAILING = 5; + + + /** + * The number of pixels between the inside of {@link #border} + * and the bordered component. + */ + protected static final int EDGE_SPACING = 2; + + + /** + * The number of pixels between the outside of this TitledBorder + * and the beginning (if left-aligned) or end (if right-aligned) + * of the title text. + */ + protected static final int TEXT_INSET_H = 5; + + + /** + * The number of pixels between the title text and {@link #border}. + * This value is only relevant if the title text does not intersect + * {@link #border}. No intersection occurs if {@link #titlePosition} + * is one of {@link #ABOVE_TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, + * or {@link #BELOW_BOTTOM}. + */ + protected static final int TEXT_SPACING = 2; + + + /** + * Determined using the serialver tool of Apple/Sun JDK 1.3.1 + * on MacOS X 10.1.5. + */ + static final long serialVersionUID = 8012999415147721601L; + + + /** + * The title, or null to display no title. + */ + protected String title; + + + /** + * The border underneath the title. If this value is + * null, the border will be retrieved from the {@link + * javax.swing.UIManager}’s defaults table using the key + * TitledBorder.border. + */ + protected Border border; + + + /** + * The vertical position of the title text relative to the border, + * which is one of {@link #ABOVE_TOP}, {@link #TOP}, {@link + * #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link + * #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}. + */ + protected int titlePosition; + + + /** + * The horizontal alignment of the title text in relation to the + * border, which is one of {@link #LEFT}, {@link #CENTER}, {@link + * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link + * #DEFAULT_JUSTIFICATION}. + */ + protected int titleJustification; + + + /** + * The font for displaying the title text. If this value is + * null, the font will be retrieved from the {@link + * javax.swing.UIManager}’s defaults table using the key + * TitledBorder.font. + */ + protected Font titleFont; + + + /** + * The color for displaying the title text. If this value is + * null, the color will be retrieved from the {@link + * javax.swing.UIManager}’s defaults table using the key + * TitledBorder.titleColor. + */ + protected Color titleColor; + + + /** + * Constructs a TitledBorder given the text of its title. + * + * @param title the title text, or null to use no title text. + */ + public TitledBorder(String title) + { + this(/* border */ null, + title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION, + /* titleFont */ null, /* titleColor */ null); + } + + + /** + * Constructs an initially untitled TitledBorder given another border. + * + * @param border the border underneath the title, or null + * to use a default from the current look and feel. + */ + public TitledBorder(Border border) + { + this(border, /* title */ "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION, + /* titleFont */ null, /* titleColor */ null); + } + + + /** + * Constructs a TitledBorder given its border and title text. + * + * @param border the border underneath the title, or null + * to use a default from the current look and feel. + * + * @param title the title text, or null to use no title + * text. + */ + public TitledBorder(Border border, String title) + { + this(border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION, + /* titleFont */ null, /* titleColor */ null); + } + + + /** + * Constructs a TitledBorder given its border, title text, horizontal + * alignment, and vertical position. + * + * @param border the border underneath the title, or null + * to use a default from the current look and feel. + * + * @param title the title text, or null to use no title + * text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING}, + * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}. + + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP}, + * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM}, + * or {@link #DEFAULT_POSITION}. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorder(Border border, String title, int titleJustification, + int titlePosition) + { + this(border, title, titleJustification, titlePosition, + /* titleFont */ null, /* titleColor */ null); + } + + + /** + * Constructs a TitledBorder given its border, title text, horizontal + * alignment, vertical position, and font. + * + * @param border the border underneath the title, or null + * to use a default from the current look and feel. + * + * @param title the title text, or null to use no title + * text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING}, + * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP}, + * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM}, + * or {@link #DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or null + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorder(Border border, String title, int titleJustification, + int titlePosition, Font titleFont) + { + this(border, title, titleJustification, titlePosition, titleFont, + /* titleColor */ null); + } + + + /** + * Constructs a TitledBorder given its border, title text, horizontal + * alignment, vertical position, font, and color. + * + * @param border the border underneath the title, or null + * to use a default from the current look and feel. + * + * @param title the title text, or null to use no title + * text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING}, + * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP}, + * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM}, + * or {@link #DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or null + * to use a default from the current look and feel. + * + * @param titleColor the color for the title text, or null + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorder(Border border, String title, int titleJustification, + int titlePosition, Font titleFont, Color titleColor) + { + this.border = border; + this.title = title; + + /* Invoking the setter methods ensures that the newly constructed + * TitledBorder has valid property values. + */ + setTitleJustification(titleJustification); + setTitlePosition(titlePosition); + + this.titleFont = titleFont; + this.titleColor = titleColor; + } + + + /** + * Paints the border and the title text. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Measurements mes = getMeasurements(c); + Font oldFont = g.getFont(); + Color oldColor = g.getColor(); + + /** + * A local helper class for painting the border without changing + * any pixels inside the rectangle of the title text. + */ + class BorderPainter + { + private Component c; + private Border b; + private int x, y, width, height; + + /** + * Constructs a BorderPainter. + * + * @param c the component whose border is being painted. + * @param b the border object. + * @param x the x coordinate of the rectangle delimiting the border. + * @param y the y coordinate of the rectangle delimiting the border. + * @param width the width of the rectangle delimiting the border. + * @param height the width of the rectangle delimiting the border. + */ + public BorderPainter(Component c, Border b, + int x, int y, int width, int height) + { + this.c = c; + this.b = b; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + + /** + * Paints the entire border. + */ + public void paint(Graphics g) + { + if (b != null) + b.paintBorder(c, g, x, y, width - 1, height - 1); + } + + + /** + * Paints the border, clipping the drawing operation to a + * given rectangular area. + */ + private void paint(Graphics g, + int clipX, int clipY, int clipWidth, int clipHeight) + { + Shape oldClip = g.getClip(); + try + { + g.clipRect(clipX, clipY, clipWidth, clipHeight); + paint(g); + } + finally + { + g.setClip(oldClip); + } + } + + + /** + * Paints the border without affecting a given rectangular area. + * This is used for painting the border without drawing anything + * underneath the title text. + * + *

Since we do not want to introduce unnecessary dependencies + * on Java 2D, we perform the clipping without constructive geometry + * (provided by java.awt.geom.Area). Instead, the border’s + * bounding rectangle is split into smaller parts, which are then + * clipped and painted individually.: + * + *

+       *    +--------------------+          +--------------------+
+       *    |                    |          |        1           |
+       *    |   +--------+       |          +---+--------+-------+
+       *    |   | hole   |       |  |====>  | 2 | hole   |   3   |
+       *    |   +--------+       |          |---+--------+-------+
+       *    |                    |          |        4           |
+       *    +--------------------+          +--------------------+
+ * + */ + public void paintExcept(Graphics g, + int holeX, int holeY, int holeWidth, int holeHeight) + { + int stripeHeight; + + stripeHeight = holeY - y; + if (stripeHeight > 0) + paint(g, x, y, width, stripeHeight); // patch #1 in the image above + + stripeHeight = holeHeight; + if (stripeHeight > 0) + { + paint(g, x, holeY, holeX - x, stripeHeight); // patches #2 and #3 + paint(g, holeX + holeWidth, holeY, width - (holeX + holeWidth), stripeHeight); + } + + stripeHeight = height - (holeY - y + holeHeight); + if (stripeHeight > 0) + paint(g, x, y + height - stripeHeight, width, stripeHeight); // #4 + } + }; + + BorderPainter bp; + int textX, textY, borderWidth, borderHeight; + + borderWidth = width - (mes.borderSpacing.left + mes.borderSpacing.right); + borderHeight = height - (mes.borderSpacing.top + mes.borderSpacing.bottom); + bp = new BorderPainter(c, getBorder(), + x + mes.borderSpacing.left, y + mes.borderSpacing.top, + borderWidth, borderHeight); + + switch (getRealTitleJustification(c)) + { + case LEFT: + textX = x + TEXT_INSET_H; + break; + + case CENTER: + textX = x + (borderWidth - mes.textWidth) / 2; + break; + + case RIGHT: + textX = x + borderWidth - (mes.textWidth + TEXT_INSET_H); + break; + + default: + throw new IllegalStateException(); + } + + switch (titlePosition) + { + case ABOVE_TOP: + textY = y; + break; + + case TOP: + case DEFAULT_POSITION: + default: + textY = y + mes.borderSpacing.top + mes.borderInsets.top - mes.textAscent; + break; + + case BELOW_TOP: + textY = y + mes.borderSpacing.top + mes.borderInsets.top + TEXT_SPACING; + break; + + case ABOVE_BOTTOM: + textY = y + height - mes.borderSpacing.bottom - mes.borderInsets.bottom + - TEXT_SPACING - (mes.textAscent + mes.textDescent); + break; + + case BOTTOM: + case BELOW_BOTTOM: + textY = y + height - (mes.textAscent + mes.textDescent); + break; + } + + if (mes.trimmedText == null) + bp.paint(g); + else + { + try + { + g.setFont(mes.font); + g.setColor(getTitleColor()); + g.drawString(mes.trimmedText, textX, textY + mes.textAscent); + } + finally + { + g.setFont(oldFont); + g.setColor(oldColor); + } + bp.paintExcept(g, textX - 2, textY, + mes.textWidth + 2, mes.textAscent + mes.textDescent); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets() + */ + public Insets getBorderInsets(Component c, Insets insets) + { + return getMeasurements(c).getContentInsets(insets); + } + + + /** + * Returns false, indicating that there are pixels inside + * the area of this border where the background shines through. + * + * @return false. + */ + public boolean isBorderOpaque() + { + /* Note that the AbstractBorder.isBorderOpaque would also return + * false, so there is actually no need to override the inherited + * implementation. However, GNU Classpath strives for exact + * compatibility with the Sun reference implementation, which + * overrides isBorderOpaque for unknown reasons. + */ + return false; + } + + + /** + * Returns the text of the title. + * + * @return the title text, or null if no title is + * displayed. + */ + public String getTitle() + { + return title; + } + + + /** + * Retrieves the border underneath the title. If no border has been + * set, or if it has been set tonull, the current + * {@link javax.swing.LookAndFeel} will be asked for a border + * using the key TitledBorder.border. + * + * @return a border, or null if the current LookAndFeel + * does not provide a border for the key + * TitledBorder.border. + * + * @see javax.swing.UIManager#getBorder(Object) + */ + public Border getBorder() + { + if (border != null) + return border; + + return UIManager.getBorder("TitledBorder.border"); + } + + + /** + * Returns the vertical position of the title text in relation + * to the border. + * + * @return one of the values {@link #ABOVE_TOP}, {@link #TOP}, + * {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, + * {@link #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}. + */ + public int getTitlePosition() + { + return titlePosition; + } + + + /** + * Returns the horizontal alignment of the title text in relation to + * the border. + * + * @return one of the values {@link #LEFT}, {@link #CENTER}, {@link + * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link + * #DEFAULT_JUSTIFICATION}. + */ + public int getTitleJustification() + { + return titleJustification; + } + + + /** + * Retrieves the font for displaying the title text. If no font has + * been set, or if it has been set tonull, the current + * {@link javax.swing.LookAndFeel} will be asked for a font + * using the key TitledBorder.font. + * + * @return a font, or null if the current LookAndFeel + * does not provide a font for the key + * TitledBorder.font. + * + * @see javax.swing.UIManager#getFont(Object) + */ + public Font getTitleFont() + { + if (titleFont != null) + return titleFont; + + return UIManager.getFont("TitledBorder.font"); + } + + + /** + * Retrieves the color for displaying the title text. If no color has + * been set, or if it has been set tonull, the current + * {@link javax.swing.LookAndFeel} will be asked for a color + * using the key TitledBorder.titleColor. + * + * @return a color, or null if the current LookAndFeel + * does not provide a color for the key + * TitledBorder.titleColor. + * + * @see javax.swing.UIManager#getColor(Object) + */ + public Color getTitleColor() + { + if (titleColor != null) + return titleColor; + + return UIManager.getColor("TitledBorder.titleColor"); + } + + + /** + * Sets the text of the title. + * + * @param title the new title text, or null for displaying + * no text at all. + */ + public void setTitle(String title) + { + // Swing borders are not JavaBeans, thus no need to fire an event. + this.title = title; + } + + + /** + * Sets the border underneath the title. + * + * @param border a border, or null to use the + * border that is supplied by the current LookAndFeel. + * + * @see #getBorder() + */ + public void setBorder(Border border) + { + // Swing borders are not JavaBeans, thus no need to fire an event. + this.border = border; + } + + + /** + * Sets the vertical position of the title text in relation + * to the border. + * + * @param titlePosition one of the values {@link #ABOVE_TOP}, + * {@link #TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, + * {@link #BOTTOM}, {@link #BELOW_BOTTOM}, + * or {@link #DEFAULT_POSITION}. + * + * @throws IllegalArgumentException if an unsupported value is passed + * for titlePosition. + */ + public void setTitlePosition(int titlePosition) + { + if ((titlePosition < DEFAULT_POSITION) || (titlePosition > BELOW_BOTTOM)) + throw new IllegalArgumentException(); + + // Swing borders are not JavaBeans, thus no need to fire an event. + this.titlePosition = titlePosition; + } + + + /** + * Sets the horizontal alignment of the title text in relation to the border. + * + * @param titleJustification the new alignment, which must be one of + * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING}, + * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}. + * + * @throws IllegalArgumentException if an unsupported value is passed + * for titleJustification. + */ + public void setTitleJustification(int titleJustification) + { + if ((titleJustification < DEFAULT_JUSTIFICATION) + || (titleJustification > TRAILING)) + throw new IllegalArgumentException(); + + // Swing borders are not JavaBeans, thus no need to fire an event. + this.titleJustification = titleJustification; + } + + + /** + * Sets the font for displaying the title text. + * + * @param titleFont the font, or null to use the font + * provided by the current {@link javax.swing.LookAndFeel}. + * + * @see #getTitleFont() + */ + public void setTitleFont(Font titleFont) + { + // Swing borders are not JavaBeans, thus no need to fire an event. + this.titleFont = titleFont; + } + + + /** + * Sets the color for displaying the title text. + * + * @param titleColor the color, or null to use the color + * provided by the current {@link javax.swing.LookAndFeel}. + * + * @see #getTitleColor() + */ + public void setTitleColor(Color titleColor) + { + // Swing borders are not JavaBeans, thus no need to fire an event. + this.titleColor = titleColor; + } + + + /** + * Calculates the minimum size needed for displaying the border + * and its title. + * + * @param c the Component for which this TitledBorder consitutes + * a border. + */ + public Dimension getMinimumSize(Component c) + { + return getMeasurements(c).getMinimumSize(); + } + + + /** + * Returns the font that is used for displaying the title text for + * a given Component. + * + * @param c the Component for which this TitledBorder is the border. + * + * @return The font returned by {@link #getTitleFont()}, or a fallback + * if {@link #getTitleFont()} returned null. + */ + protected Font getFont(Component c) + { + Font f; + + f = getTitleFont(); + if (f != null) + return f; + + return new Font("Dialog", Font.PLAIN, 12); + } + + + /** + * Returns the horizontal alignment of the title text in relation to + * the border, mapping the component-dependent alignment constants + * {@link #LEADING}, {@link #TRAILING} and {@link #DEFAULT_JUSTIFICATION} + * to the correct value according to the embedded component’s + * orientation. + * + * @param c the Component for which this TitledBorder is the border. + * + * @return one of the values {@link #LEFT}, {@link #CENTER}, or {@link + * #RIGHT}. + */ + private int getRealTitleJustification(Component c) + { + switch (titleJustification) + { + case DEFAULT_JUSTIFICATION: + case LEADING: + if ((c == null) || c.getComponentOrientation().isLeftToRight()) + return LEFT; + else + return RIGHT; + + case TRAILING: + if ((c == null) || c.getComponentOrientation().isLeftToRight()) + return RIGHT; + else + return LEFT; + + default: + return titleJustification; + } + } + + + /** + * Performs various measurements for the current state of this TitledBorder + * and the given Component. + */ + private Measurements getMeasurements(Component c) + { + Measurements m = new Measurements(); + FontMetrics fmet; + + m.font = getFont(c); + fmet = c.getFontMetrics(m.font); + m.border = getBorder(); + if (m.border != null) + m.borderInsets = m.border.getBorderInsets(c); + else + m.borderInsets = new Insets(0, 0, 0, 0); + + if (title != null) + { + m.trimmedText = title.trim(); + if (m.trimmedText.length() == 0) + m.trimmedText = null; + } + + m.textAscent = fmet.getAscent(); + m.textDescent = fmet.getDescent(); + if (m.trimmedText != null) + m.textWidth = fmet.stringWidth(m.trimmedText) + 3; + + m.edgeSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING, EDGE_SPACING); + m.borderSpacing = new Insets(0, 0, 0, 0); + + switch (titlePosition) + { + case ABOVE_TOP: + m.borderSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING; + break; + + case BELOW_TOP: + m.edgeSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING; + break; + + case ABOVE_BOTTOM: + m.edgeSpacing.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; + break; + + case BELOW_BOTTOM: + m.borderSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING; + break; + + default: + m.borderSpacing.top += m.textAscent; + } + + return m; + } + + + /** + * A private helper class for holding the result of measuring the + * distances of a TitledBorder. While it would be possible to cache + * these objects, it does not seem to be worth the effort. Note that + * invalidating the cache would be tricky, especially since there is + * no notification mechanism that would inform the cache when + * border has changed, so it would return different insets. + */ + private static class Measurements + { + /** + * The font used for displaying the title text. Note that it can + * well be that the TitledBorder’s font is null, + * which means that the font is to be retrieved from the current + * LookAndFeel. In this case, this font field will + * contain the result of the retrieval. Therefore, it is safe + * to assume that his font field will never have + * a null value. + */ + Font font; + + + /** + * The number of pixels between the base line and the top of the + * text box. + */ + int textAscent; + + + /** + * The number of pixels between the base line and the bottom of + * the text box. + */ + int textDescent; + + + /** + * The title text after removing leading and trailing white space + * characters. If the title consists only of white space, the + * value of trimmedText will be null. + */ + String trimmedText; + + + /** + * The width of the trimmed title text in pixels. + */ + int textWidth; + + + /** + * The border that constitues the interior border + * underneath the title text. + */ + Border border; + + + /** + * The distance between the TitledBorder and the interior border. + */ + Insets borderSpacing; + + + /** + * The width of the interior border, as returned by + * border.getBorderInsets(). + */ + Insets borderInsets; + + + /** + * The distance between the interior border and the nested + * Component for which this TitledBorder is a border. + */ + Insets edgeSpacing; + + + /** + * Determines the insets of the nested component when it has a + * TitledBorder as its border. Used by {@link + * TitledBorder#getBorderInsets()}. + * + * @param i an Insets object for storing the results into, or + * null to cause the creation of a + * new instance. + * + * @return the i object, or a new Insets object + * if null was passed for i. + */ + public Insets getContentInsets(Insets i) + { + 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; + return i; + } + + + /** + * Calculates the minimum size needed for displaying the border + * and its title. Used by {@link TitledBorder#getMiminumSize()}. + */ + public Dimension getMinimumSize() + { + int width; + Insets insets; + + insets = getContentInsets(null); + 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/border/doc-files/BevelBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-1.png new file mode 100644 index 0000000..8c3e4b2 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/BevelBorder-2.png b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-2.png new file mode 100644 index 0000000..ac52d47 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-2.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/BevelBorder-3.png b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-3.png new file mode 100644 index 0000000..dd531ff Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/BevelBorder-3.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/EmptyBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/EmptyBorder-1.png new file mode 100644 index 0000000..2f21140 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/EmptyBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-1.png new file mode 100644 index 0000000..6b1085c1 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-2.png b/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-2.png new file mode 100644 index 0000000..36b0705 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/EtchedBorder-2.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/LineBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/LineBorder-1.png new file mode 100644 index 0000000..45b8afc Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/LineBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-1.png new file mode 100644 index 0000000..fc49f4b Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-2.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-2.png new file mode 100644 index 0000000..9c2c8d9 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-2.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-3.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-3.png new file mode 100644 index 0000000..62089ea Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-3.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-4.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-4.png new file mode 100644 index 0000000..bffbcc8 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-4.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-5.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-5.png new file mode 100644 index 0000000..807eee8 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-5.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/MatteBorder-6.png b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-6.png new file mode 100644 index 0000000..2c4ce1e Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/MatteBorder-6.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-1.png b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-1.png new file mode 100644 index 0000000..4404bf9 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-1.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-2.png b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-2.png new file mode 100644 index 0000000..ebd9849 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-2.png differ diff --git a/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-3.png b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-3.png new file mode 100644 index 0000000..9f939b7 Binary files /dev/null and b/libjava/classpath/javax/swing/border/doc-files/SoftBevelBorder-3.png differ diff --git a/libjava/classpath/javax/swing/border/package.html b/libjava/classpath/javax/swing/border/package.html new file mode 100644 index 0000000..de8479a --- /dev/null +++ b/libjava/classpath/javax/swing/border/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.border + + +

Provides borders for use by components in the javax.swing +package.

+ + + diff --git a/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java new file mode 100644 index 0000000..d55346a --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java @@ -0,0 +1,162 @@ +/* AbstractColorChooserPanel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.awt.Graphics; + +import javax.swing.Icon; +import javax.swing.JColorChooser; +import javax.swing.JPanel; + +/** + * AbstractColorChooserPanel + * + * @author Andrew Selkirk + * @version 1.0 + */ +public abstract class AbstractColorChooserPanel extends JPanel +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -977469671210173863L; + + /** The chooser associated with this panel. */ + private JColorChooser chooser; + + /** + * This is the constructor for the AbstractColorChooserPanel. + */ + public AbstractColorChooserPanel() + { + } // AbstractColorChooserPanel() + + /** + * This method returns the name displayed in the tab for this chooser panel. + * + * @return The name displayed in the JTabbedPane's tabs. + */ + public abstract String getDisplayName(); + + /** + * This method updates the chooser panel when the JColorChooser's color has + * changed. + */ + public abstract void updateChooser(); + + /** + * This method constructs and does any initialization necessary for the + * chooser panel. + */ + protected abstract void buildChooser(); + + /** + * This method sets the small icon used in the JTabbedPane for this chooser + * panel. + * + * @return The small icon used in the JTabbedPane. + */ + public abstract Icon getSmallDisplayIcon(); + + /** + * This method sets the large icon useed in the jTabbedPane for this chooser + * panel. + * + * @return The large icon. + */ + public abstract Icon getLargeDisplayIcon(); + + /** + * This method installs the chooser panel for the given JColorChooser. + * + * @param chooser The JColorChooser that will have this panel installed. + */ + public void installChooserPanel(JColorChooser chooser) + { + this.chooser = chooser; + buildChooser(); + } // installChooserPanel() + + /** + * This method removes the chooser panel from the given JColorChooser and + * does any necessary clean up for the chooser panel. + * + * @param chooser The JColorChooser that is having this panel removed. + */ + public void uninstallChooserPanel(JColorChooser chooser) + { + this.chooser = null; + } // uninstallChooserPanel() + + /** + * This method returns the ColorSelectionModel for the JColorChooser + * associated with this chooser panel. + * + * @return The ColorSelectionModel for the JColorChooser associated with + * this chooser panel. + */ + public ColorSelectionModel getColorSelectionModel() + { + if (chooser != null) + return chooser.getSelectionModel(); + return null; + } // getColorSelectionModel() + + /** + * This method returns the current color stored in the model for this + * chooser panel. + * + * @return The current color. + */ + protected Color getColorFromModel() + { + if (chooser != null) + return chooser.getColor(); + return null; + } // getColorFromModel() + + /** + * This method paints the chooser panel. + * + * @param graphics The Graphics object to paint with. + */ + public void paint(Graphics graphics) + { + super.paint(graphics); + } // paint() +} // AbstractColorChooserPanel diff --git a/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java b/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java new file mode 100644 index 0000000..77e319c --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java @@ -0,0 +1,85 @@ +/* ColorChooserComponentFactory.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.colorchooser; + +import javax.swing.JComponent; + + +/** + * ColorChooserComponentFactory + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class ColorChooserComponentFactory +{ + /** + * Constructor ColorChooserComponentFactory + */ + private ColorChooserComponentFactory() + { + } // ColorChooserComponentFactory() + + /** + * This method returns the three default chooser panels to be used in + * JColorChooser. + * + * @return The default chooser panels. + */ + public static AbstractColorChooserPanel[] getDefaultChooserPanels() + { + AbstractColorChooserPanel[] values = + { + new DefaultSwatchChooserPanel(), + new DefaultHSBChooserPanel(), + new DefaultRGBChooserPanel() + }; + return values; + } + + /** + * This method returns the default preview panel to be used with + * JColorChoosers. + * + * @return The default preview panel. + */ + public static JComponent getPreviewPanel() + { + return new DefaultPreviewPanel(); + } // getPreviewPanel() +} // ColorChooserComponentFactory diff --git a/libjava/classpath/javax/swing/colorchooser/ColorSelectionModel.java b/libjava/classpath/javax/swing/colorchooser/ColorSelectionModel.java new file mode 100644 index 0000000..5f30708 --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/ColorSelectionModel.java @@ -0,0 +1,81 @@ +/* ColorSelectionModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.Color; + +import javax.swing.event.ChangeListener; + +/** + * ColorSelectionModel + * @author Andrew Selkirk + * @version 1.0 + */ +public interface ColorSelectionModel { + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getSelectedColor + * @returns Color + */ + Color getSelectedColor(); + + /** + * setSelectedColor + * @param color TODO + */ + void setSelectedColor(Color color); + + /** + * addChangeListener + * @param listener TODO + */ + void addChangeListener(ChangeListener listener); + + /** + * removeChangeListener + * @param listener TODO + */ + void removeChangeListener(ChangeListener listener); + + +} // ColorSelectionModel diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultColorSelectionModel.java b/libjava/classpath/javax/swing/colorchooser/DefaultColorSelectionModel.java new file mode 100644 index 0000000..aae2bed --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/DefaultColorSelectionModel.java @@ -0,0 +1,163 @@ +/* DefaultColorSelectionModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.io.Serializable; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * This is the default implementation of the ColorSelectionModel interface + * that JColorChoosers use. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class DefaultColorSelectionModel implements ColorSelectionModel, + Serializable +{ + /** DOCUMENT ME! */ + private static final long serialVersionUID = -8117143602864778804L; + + /** The currently selected color. */ + private Color selectedColor; + + /** The ChangeEvent fired to all ChangeListeners. */ + protected transient ChangeEvent changeEvent = new ChangeEvent(this); + + /** The list of listeners. */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Creates a new color selection model with the default white color. + */ + public DefaultColorSelectionModel() + { + this(Color.white); + } + + /** + * Creates a new color selection model with a given selected color. + * + * @param color The initial color. + * + * @throws Error If the color is null. + */ + public DefaultColorSelectionModel(Color color) + { + super(); + if (color == null) + throw new Error("ColorSelectionModel cannot be set to have null color."); + this.selectedColor = color; + } + + /** + * Returns the selected color. + * + * @return The selected color. + */ + public Color getSelectedColor() + { + return selectedColor; + } + + /** + * This method sets the color. + * + * @param color The color to set. + * + * @throws Error If the color is set. + */ + public void setSelectedColor(Color color) + { + if (color == null) + throw new Error("ColorSelectionModel cannot be set to have null color."); + if (color != selectedColor) + { + this.selectedColor = color; + fireStateChanged(); + } + } + + /** + * Adds a listener to this model. + * + * @param listener The listener to add. + */ + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + /** + * Removes a listener from this model. + * + * @param listener The listener to remove. + */ + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + /** + * Returns all currently added ChangeListener objects. + * + * @return Array of ChangeListener objects. + */ + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + /** + * Calls all the stateChanged() method of all added + * ChangeListener objects with changeEvent as + * argument. + */ + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for (int i = 0; i < listeners.length; i++) + listeners[i].stateChanged(changeEvent); + } +} diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultHSBChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/DefaultHSBChooserPanel.java new file mode 100644 index 0000000..71d6c75 --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/DefaultHSBChooserPanel.java @@ -0,0 +1,891 @@ +/* DefaultHSBChooserPanel.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.image.MemoryImageSource; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JColorChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * This is the Default HSB Panel displayed in the JColorChooser. + */ +class DefaultHSBChooserPanel extends AbstractColorChooserPanel +{ + /** The gradient image displayed. + * This is package-private to avoid an accessor method. */ + transient Image gradientImage; + + /** The Panel that holds the gradient image. */ + private transient JPanel gradientPanel; + + /** The track gradient image. + * This is package-private to avoid an accessor method. */ + transient Image trackImage; + + /** The panel that holds the track. */ + private transient JPanel trackPanel; + + /** The slider for the locked HSB value. + * This is package-private to avoid an accessor method. */ + transient JSlider slider; + + /** The RadioButton that controls the Hue. + * This is package-private to avoid an accessor method. */ + transient JRadioButton hRadio; + + /** The RadioButton that controls the Saturation. + * This is package-private to avoid an accessor method. */ + transient JRadioButton sRadio; + + /** The RadioButton that controls the Brightness. + * This is package-private to avoid an accessor method. */ + transient JRadioButton bRadio; + + /** The JSpinner that controls the Hue. + * This is package-private to avoid an accessor method. */ + transient JSpinner hSpinner; + + /** The JSpinner that controls the Saturation. + * This is package-private to avoid an accessor method. */ + transient JSpinner sSpinner; + + /** The JSpinner that controls the Brightness. + * This is package-private to avoid an accessor method. */ + transient JSpinner bSpinner; + + /** The default width of the gradient image. */ + private static final int imgWidth = 200; + + /** The default height of the gradient image. */ + private static final int imgHeight = 200; + + /** The default width of the track gradient. */ + private static final int trackWidth = 30; + + /** The JLabel for Red. */ + private static final JLabel R = new JLabel("R"); + + /** The JLabel for Green. */ + private static final JLabel G = new JLabel("G"); + + /** The JLabel for Blue. */ + private static final JLabel B = new JLabel("B"); + + // FIXME: Should be textfields. + + /** The JLabel that displays the value of Red. */ + private transient JLabel rFull; + + /** The JLabel that displays the value of Green. */ + private transient JLabel gFull; + + /** The JLabel that displays the value of Blue. */ + private transient JLabel bFull; + + /** The point that is displayed in the gradient image. + * Package-private to avoid an accessor method. + */ + transient Point gradientPoint = new Point(); + + /** + * This indicates that the change to the slider or point is triggered + * internally. + * This is package-private to avoid an accessor method. + */ + transient boolean internalChange = false; + + /** This indicates that the change to the spinner is triggered + * internally. + * This is package-private to avoid an accessor method. */ + transient boolean spinnerTrigger = false; + + /** This int identifies which spinner is currently locked. + * This is package-private to avoid an accessor method. */ + transient int locked = -1; + + /** This value indicates that the Hue spinner is locked. */ + static final int HLOCKED = 0; + + /** This value indicates that the Saturation spinner is locked. */ + static final int SLOCKED = 1; + + /** This value indicates that the Brightness spinner is locked. */ + static final int BLOCKED = 2; + + /** + * This method indicates that the mouse event is in the process of being + * handled. + * This is package-private to avoid an accessor method. + */ + transient boolean handlingMouse; + + /** + * This helper class handles mouse events on the gradient image. + */ + class MainGradientMouseListener extends MouseAdapter + implements MouseMotionListener + { + /** + * This method is called when the mouse is pressed over the gradient + * image. The JColorChooser is then updated with new HSB values. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + gradientPoint = e.getPoint(); + update(e.getPoint()); + } + + /** + * This method is called when the mouse is dragged over the gradient + * image. The JColorChooser is then updated with the new HSB values. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + Point p = e.getPoint(); + if (p.x < 0 || p.y < 0 || p.y > imgHeight || p.x > imgWidth) + return; + + gradientPoint = p; + update(p); + } + + /** + * This method is called when the mouse is moved over the gradient image. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Do nothing. + } + + /** + * This method updates the JColorChooser with the new values. + * + * @param p The Point where the MouseEvent occurred. + */ + private void update(Point p) + { + handlingMouse = true; + if (hSpinner.isEnabled()) + updateH(p); + else if (sSpinner.isEnabled()) + updateS(p); + else + updateB(p); + handlingMouse = false; + } + + /** + * This method updates the SB values if Hue is locked. + * + * @param p The point where the MouseEvent occurred. + */ + private void updateH(Point p) + { + float s = (imgWidth - p.x * 1f) / imgWidth; + float b = (imgHeight - p.y * 1f) / imgHeight; + + // Avoid two changes to the model by changing internalChange to true. + internalChange = true; + sSpinner.setValue(new Integer((int) (s * 100))); + internalChange = false; + bSpinner.setValue(new Integer((int) (b * 100))); + + revalidate(); + } + + /** + * This method updates the HB values if Saturation is locked. + * + * @param p The point where the MouseEvent occurred. + */ + private void updateS(Point p) + { + float h = p.x * 1f / imgWidth; + float b = (imgHeight - p.y * 1f) / imgHeight; + + internalChange = true; + hSpinner.setValue(new Integer((int) (h * 365))); + internalChange = false; + bSpinner.setValue(new Integer((int) (b * 100))); + + revalidate(); + } + + /** + * This method updates the HS values if Brightness is locked. + * + * @param p The point where the MouseEvent occurred. + */ + private void updateB(Point p) + { + float h = p.x * 1f / imgWidth; + float s = (imgHeight - p.y * 1f) / imgHeight; + + internalChange = true; + hSpinner.setValue(new Integer((int) (h * 365))); + internalChange = false; + sSpinner.setValue(new Integer((int) (s * 100))); + + revalidate(); + } + } + + /** + * This method listens for slider value changes. + */ + class SliderChangeListener implements ChangeListener + { + /** + * This method is called when the slider value changes. It should change + * the color of the JColorChooser. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (internalChange) + return; + + Integer value = new Integer(slider.getValue()); + + switch (locked) + { + case HLOCKED: + hSpinner.setValue(value); + break; + case SLOCKED: + sSpinner.setValue(value); + break; + case BLOCKED: + bSpinner.setValue(value); + break; + } + } + } + + /** + * This helper class determines the active JSpinner. + */ + class RadioStateListener implements ChangeListener + { + /** + * This method is called when there is a new JRadioButton that was + * selected. As a result, it should activate the associated JSpinner. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + JSpinner change; + if (e.getSource() == hRadio) + { + locked = HLOCKED; + change = hSpinner; + } + else if (e.getSource() == sRadio) + { + locked = SLOCKED; + change = sSpinner; + } + else + { + locked = BLOCKED; + change = bSpinner; + } + + change.setEnabled(((AbstractButton) e.getSource()).isSelected()); + updateSlider(); + updateTrack(); + updateImage(); + repaint(); + } + } + + /** + * This class listens to the JSpinners for changes. + */ + class ImageScrollListener implements ChangeListener + { + /** + * This method is called whenever one of the JSpinner values change. The + * JColorChooser should be updated with the new HSB values. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (internalChange) + return; + + float h = ((Number) hSpinner.getValue()).intValue() / 360f; + float s = ((Number) sSpinner.getValue()).intValue() / 100f; + float b = ((Number) bSpinner.getValue()).intValue() / 100f; + + spinnerTrigger = true; + getColorSelectionModel().setSelectedColor(new Color(Color.HSBtoRGB(h, s, + b))); + spinnerTrigger = false; + + if (! handlingMouse && slider != null && ! slider.getValueIsAdjusting()) + { + updateImage(); + updateTrack(); + } + repaint(); + } + } + + /** + * Creates a new DefaultHSBChooserPanel object. + */ + DefaultHSBChooserPanel() + { + super(); + } + + /** + * This method returns the name displayed by the JColorChooser tab that + * holds this panel. + * + * @return The name displayed in the JColorChooser tab. + */ + public String getDisplayName() + { + return "HSB"; + } + + /** + * This method updates the various components inside the HSBPanel (the + * JSpinners, the JSlider, and the gradient image point) with updated + * values when the JColorChooser color value changes. + */ + public void updateChooser() + { + Color c = getColorSelectionModel().getSelectedColor(); + + float[] hsbVals = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), + null); + + internalChange = true; + + if (! spinnerTrigger) + { + hSpinner.setValue(new Integer((int) (hsbVals[0] * 360))); + sSpinner.setValue(new Integer((int) (hsbVals[1] * 100))); + bSpinner.setValue(new Integer((int) (hsbVals[2] * 100))); + } + + switch (locked) + { + case HLOCKED: + if (slider != null) + slider.setValue(((Number) hSpinner.getValue()).intValue()); + if (! handlingMouse) + { + gradientPoint.x = (int) ((1 + - ((Number) sSpinner.getValue()).intValue() / 100f) * imgWidth); + gradientPoint.y = (int) ((1 + - ((Number) bSpinner.getValue()).intValue() / 100f) * imgHeight); + } + break; + case SLOCKED: + if (slider != null) + slider.setValue(((Number) sSpinner.getValue()).intValue()); + if (! handlingMouse) + { + gradientPoint.x = (int) (((Number) hSpinner.getValue()).intValue() / 360f * imgWidth); + gradientPoint.y = (int) ((1 + - ((Number) bSpinner.getValue()).intValue() / 100f) * imgHeight); + } + break; + case BLOCKED: + if (slider != null) + slider.setValue(((Number) bSpinner.getValue()).intValue()); + if (! handlingMouse) + { + gradientPoint.x = (int) (((Number) hSpinner.getValue()).intValue() / 360f * imgWidth); + gradientPoint.y = (int) ((1 + - ((Number) sSpinner.getValue()).intValue() / 100f) * imgHeight); + } + break; + } + internalChange = false; + + if (! handlingMouse && slider != null && ! slider.getValueIsAdjusting()) + updateImage(); + + if (! handlingMouse || locked != HLOCKED) + updateTrack(); + updateTextFields(); + } + + /** + * This method builds the DefaultHSBChooserPanel. + */ + protected void buildChooser() + { + setLayout(new BorderLayout()); + + add(buildRightPanel(), BorderLayout.EAST); + + JPanel container = new JPanel(); + container.setLayout(new BorderLayout()); + + gradientPanel = new JPanel() + { + public Dimension getPreferredSize() + { + return new Dimension(imgWidth, imgHeight); + } + + public void paint(Graphics g) + { + if (gradientImage != null) + g.drawImage(gradientImage, 0, 0, this); + + Color saved = g.getColor(); + g.setColor(Color.WHITE); + g.drawOval(gradientPoint.x - 3, gradientPoint.y - 3, 6, 6); + g.setColor(saved); + } + }; + + MouseAdapter ml = new MainGradientMouseListener(); + gradientPanel.addMouseListener(ml); + gradientPanel.addMouseMotionListener((MouseMotionListener) ml); + + trackPanel = new JPanel() + { + public Dimension getPreferredSize() + { + return new Dimension(trackWidth, imgHeight); + } + + public void paint(Graphics g) + { + if (trackImage != null) + g.drawImage(trackImage, 0, 0, this); + } + }; + + slider = new JSlider(); + slider.setPaintTrack(false); + slider.setPaintTicks(false); + + slider.setOrientation(SwingConstants.VERTICAL); + + updateSlider(); + + container.add(gradientPanel, BorderLayout.WEST); + container.add(slider, BorderLayout.CENTER); + container.add(trackPanel, BorderLayout.EAST); + + add(container, BorderLayout.WEST); + slider.addChangeListener(new SliderChangeListener()); + repaint(); + } + + /** + * This method uninstalls the DefaultHSBPanel. + * + * @param chooser The JColorChooser to remove this panel from. + */ + public void uninstallChooserPanel(JColorChooser chooser) + { + trackImage = null; + gradientImage = null; + gradientPanel = null; + slider = null; + + hSpinner = null; + sSpinner = null; + bSpinner = null; + + hRadio = null; + sRadio = null; + bRadio = null; + + removeAll(); + super.uninstallChooserPanel(chooser); + } + + /** + * This helper method creates the right side panel (the panel with the + * Spinners and TextFields). + * + * @return The right side panel. + */ + private Container buildRightPanel() + { + JPanel container = new JPanel(); + container.setLayout(new GridLayout(6, 2)); + + hRadio = new JRadioButton("H"); + sRadio = new JRadioButton("S"); + bRadio = new JRadioButton("B"); + + ButtonGroup group = new ButtonGroup(); + group.add(hRadio); + group.add(sRadio); + group.add(bRadio); + + hSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 359, 1)); + sSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1)); + bSpinner = new JSpinner(new SpinnerNumberModel(100, 0, 100, 1)); + + hSpinner.setEnabled(false); + sSpinner.setEnabled(false); + bSpinner.setEnabled(false); + + ChangeListener cl = new RadioStateListener(); + ChangeListener scroll = new ImageScrollListener(); + + hRadio.addChangeListener(cl); + sRadio.addChangeListener(cl); + bRadio.addChangeListener(cl); + + hSpinner.addChangeListener(scroll); + sSpinner.addChangeListener(scroll); + bSpinner.addChangeListener(scroll); + + hRadio.setSelected(true); + + container.add(hRadio); + container.add(hSpinner); + + container.add(sRadio); + container.add(sSpinner); + + container.add(bRadio); + container.add(bSpinner); + + rFull = new JLabel("red full"); + gFull = new JLabel("green full"); + bFull = new JLabel("blue full"); + + container.add(R); + container.add(rFull); + + container.add(G); + container.add(gFull); + + container.add(B); + container.add(bFull); + + return container; + } + + /** + * This method returns the small display icon. + * + * @return The small display icon. + */ + public Icon getSmallDisplayIcon() + { + return null; + } + + /** + * This method returns the large display icon. + * + * @return The large display icon. + */ + public Icon getLargeDisplayIcon() + { + return null; + } + + /** + * This method paints the chooser panel. + * + * @param g The graphics object to paint with. + */ + public void paint(Graphics g) + { + super.paint(g); + } + + /** + * This method updates the gradient image with a new one taking the Hue + * value as the constant. + */ + private void updateHLockImage() + { + int index = 0; + int[] pix = new int[imgWidth * imgHeight]; + float hValue = ((Number) hSpinner.getValue()).intValue() / 360f; + + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < imgWidth; i++) + pix[index++] = Color.HSBtoRGB(hValue, (imgWidth - i * 1f) / imgWidth, + (imgHeight - j * 1f) / imgHeight) + | (255 << 24); + + gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight, + pix, 0, imgWidth)); + } + + /** + * This method updates the gradient image with a new one taking the + * Brightness value as the constant. + */ + private void updateBLockImage() + { + int[] pix = new int[imgWidth * imgHeight]; + float bValue = ((Number) bSpinner.getValue()).intValue() / 100f; + + int index = 0; + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < imgWidth; i++) + pix[index++] = Color.HSBtoRGB(i * 1f / imgWidth, + (imgHeight - j * 1f) / imgHeight, bValue) + | (255 << 24); + + gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight, + pix, 0, imgWidth)); + } + + /** + * This method updates the gradient image with a new one taking the + * Saturation value as the constant. + */ + private void updateSLockImage() + { + int[] pix = new int[imgWidth * imgHeight]; + float sValue = ((Number) sSpinner.getValue()).intValue() / 100f; + + int index = 0; + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < imgWidth; i++) + pix[index++] = Color.HSBtoRGB(i * 1f / imgWidth, sValue, + (imgHeight - j * 1f) / imgHeight) + | (255 << 24); + gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight, + pix, 0, imgWidth)); + } + + /** + * This method calls the appropriate method to update the gradient image + * depending on which HSB value is constant. + * This is package-private to avoid an accessor method. + */ + void updateImage() + { + switch (locked) + { + case HLOCKED: + updateHLockImage(); + break; + case SLOCKED: + updateSLockImage(); + break; + case BLOCKED: + updateBLockImage(); + break; + } + } + + /** + * This method updates the TextFields with the correct RGB values. + */ + private void updateTextFields() + { + int c = getColorSelectionModel().getSelectedColor().getRGB(); + + rFull.setText("" + (c >> 16 & 0xff)); + gFull.setText("" + (c >> 8 & 0xff)); + bFull.setText("" + (c & 0xff)); + + repaint(); + } + + /** + * This method updates the slider in response to making a different HSB + * property the constant. + * This is package-private to avoid an accessor method. + */ + void updateSlider() + { + if (slider == null) + return; + + slider.setMinimum(0); + if (locked == HLOCKED) + { + slider.setMaximum(359); + ; + slider.setValue(((Number) hSpinner.getValue()).intValue()); + slider.setInverted(true); + } + else + { + slider.setMaximum(100); + slider.setInverted(false); + if (sRadio.isSelected()) + slider.setValue(((Number) sSpinner.getValue()).intValue()); + else + slider.setValue(((Number) bSpinner.getValue()).intValue()); + } + repaint(); + } + + /** + * This method updates the track gradient image depending on which HSB + * property is constant. + * This is package-private to avoid an accessor method. + */ + void updateTrack() + { + switch (locked) + { + case HLOCKED: + updateHTrack(); + break; + case SLOCKED: + updateSTrack(); + break; + case BLOCKED: + updateBTrack(); + break; + } + } + + /** + * This method updates the track gradient image if the Hue value is allowed + * to change (according to the JRadioButtons). + */ + private void updateHTrack() + { + int trackIndex = 0; + int[] trackPix = new int[trackWidth * imgHeight]; + + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < trackWidth; i++) + trackPix[trackIndex++] = Color.HSBtoRGB(j * 1f / imgHeight, 1f, 1f) + | (255 << 24); + + trackImage = createImage(new MemoryImageSource(trackWidth, imgHeight, + trackPix, 0, trackWidth)); + } + + /** + * This method updates the track gradient image if the Saturation value is + * allowed to change (according to the JRadioButtons). + */ + private void updateSTrack() + { + int[] trackPix = new int[trackWidth * imgHeight]; + + float hValue = ((Number) hSpinner.getValue()).intValue() / 360f; + float bValue = ((Number) bSpinner.getValue()).intValue() / 100f; + + int trackIndex = 0; + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < trackWidth; i++) + trackPix[trackIndex++] = Color.HSBtoRGB(hValue, + (imgHeight - j * 1f) / imgHeight, + bValue) | (255 << 24); + + trackImage = createImage(new MemoryImageSource(trackWidth, imgHeight, + trackPix, 0, trackWidth)); + } + + /** + * This method updates the track gradient image if the Brightness value is + * allowed to change (according to the JRadioButtons). + */ + private void updateBTrack() + { + int[] trackPix = new int[trackWidth * imgHeight]; + + float hValue = ((Number) hSpinner.getValue()).intValue() / 360f; + float sValue = ((Number) sSpinner.getValue()).intValue() / 100f; + + int trackIndex = 0; + for (int j = 0; j < imgHeight; j++) + for (int i = 0; i < trackWidth; i++) + trackPix[trackIndex++] = Color.HSBtoRGB(hValue, sValue, + (imgHeight - j * 1f) / imgHeight) + | (255 << 24); + + trackImage = createImage(new MemoryImageSource(trackWidth, imgHeight, + trackPix, 0, trackWidth)); + } + + /** + * This method returns the HSB values for the currently selected color. + * + * @return The HSB values for the currently selected color. + */ + private float[] getHSBValues() + { + Color c = getColorFromModel(); + float[] f = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + return f; + } +} diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultPreviewPanel.java b/libjava/classpath/javax/swing/colorchooser/DefaultPreviewPanel.java new file mode 100644 index 0000000..2462add --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/DefaultPreviewPanel.java @@ -0,0 +1,318 @@ +/* DefaultPreviewPanel.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +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 javax.swing.JColorChooser; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; + +/** + * This is the default preview panel for the JColorChooser. The default + * preview panel is responsible for displaying the currently selected color + * of the JColorChooser. + */ +class DefaultPreviewPanel extends JPanel +{ + /** + * This is the border around the preview panel. + */ + class PreviewBorder implements Border + { + /** This is the value of the top, bottom, top, and right inset. */ + private static final int edge = 20; + + /** + * This is the distance from the top left corner of the border to the + * text. + */ + private static final int lead = 5; + + /** This is the horizontal gap between the text and the border. */ + private static final int gap = 3; + + /** + * This method returns the border insets for the given Component. + * + * @param c The Component to retrieve insets for. + * + * @return The insets for the given Component. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(edge, edge, edge, edge); + } + + /** + * This method returns whether the border is responsible for painting its + * own background. + * + * @return Whether the border is responsible for painting its own + * background. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method paints the border for the given component with the graphics + * object using the given properties. + * + * @param c The Component to paint the border for. + * @param g The Graphics object to paint with. + * @param x The x location to paint at. + * @param y The y location 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) + { + Color saved = g.getColor(); + FontMetrics fm = g.getFontMetrics(); + + g.setColor(Color.BLACK); + g.drawLine(x + edge / 2, y + edge / 2, x + edge / 2, + y + height - edge / 2); + g.drawLine(x + edge / 2, y + height - edge / 2, x + width - edge / 2, + y + height - edge / 2); + g.drawLine(x + width - edge / 2, y + edge / 2, x + width - edge / 2, + y + height - edge / 2); + g.drawLine(x + edge / 2, y + edge / 2, x + edge / 2 + lead, y + edge / 2); + + int strwidth = fm.stringWidth("Preview"); + + g.drawString("Preview", x + edge / 2 + lead + gap, + y + edge / 2 + fm.getAscent() / 2); + + g.drawLine(x + lead + edge / 2 + strwidth + gap * 2, y + edge / 2, + x + width - edge / 2, y + edge / 2); + + g.setColor(saved); + } + } + + /** A standard large gap size. */ + private static int largeGap = 6; + + /** A standard small gap size. */ + private static int smallGap = 2; + + /** The size of each side of the square. */ + private static int squareSize = 36; + + /** This padding between the text and the edge of its box. */ + private static int textPadding = 4; + + /** The width of the right most rectangles. */ + private static int rightSideRectWidth = 60; + + /** The sample text. */ + private static String sample = "Sample Text Sample Text"; + + /** + * Creates a new DefaultPreviewPanel object. + */ + DefaultPreviewPanel() + { + super(); + setBorder(new PreviewBorder()); + } + + /** + * This method paints the default preview panel with the given Graphics + * object. + * + * @param g The Graphics object. + */ + public void paint(Graphics g) + { + super.paint(g); + Color currentColor = null; + JColorChooser chooser = (JColorChooser) SwingUtilities.getAncestorOfClass(JColorChooser.class, + this); + if (chooser != null) + currentColor = chooser.getColor(); + + Color saved = g.getColor(); + Insets insets = getInsets(); + + int down = insets.top + squareSize + largeGap; + int currX = insets.left; + + paintSquare(g, currX, insets.top, Color.WHITE, currentColor, Color.WHITE, + -1, -1, -1); + paintSquare(g, currX, down, currentColor, null, null, -1, -1, -1); + + currX += squareSize + largeGap; + + paintSquare(g, currX, insets.top, Color.BLACK, currentColor, Color.WHITE, + -1, -1, -1); + paintSquare(g, currX, down, Color.WHITE, currentColor, null, -1, -1, -1); + + currX += squareSize + largeGap; + + paintSquare(g, currX, insets.top, Color.WHITE, currentColor, Color.BLACK, + -1, -1, -1); + paintSquare(g, currX, down, Color.BLACK, currentColor, null, -1, -1, -1); + + FontMetrics fm = g.getFontMetrics(); + int strWidth = fm.stringWidth(sample); + int strHeight = fm.getHeight(); + + currX += squareSize + largeGap; + + int boxWidth = 2 * textPadding + strWidth; + int boxHeight = 2 * textPadding + strHeight; + + int first = insets.top + textPadding; + int second = insets.top + boxHeight + smallGap; + int third = insets.top + 2 * (boxHeight + smallGap); + + g.setColor(Color.WHITE); + g.fillRect(currX, third, boxWidth, boxHeight); + + g.setColor(currentColor); + g.drawString(sample, currX + textPadding, + first + textPadding + fm.getAscent()); + + g.fillRect(currX, second, boxWidth, boxHeight); + + g.drawString(sample, currX + textPadding, + third + textPadding + fm.getAscent()); + + g.setColor(Color.BLACK); + g.drawString(sample, currX + textPadding, + second + textPadding + fm.getAscent()); + + currX += boxWidth + largeGap; + + g.setColor(Color.WHITE); + g.fillRect(currX, insets.top, rightSideRectWidth, squareSize + + largeGap / 2); + + g.setColor(currentColor); + g.fillRect(currX, insets.top + squareSize + largeGap / 2, + rightSideRectWidth, squareSize + largeGap / 2); + + g.setColor(saved); + } + + /** + * This method creates and paints a square. The square has two smaller + * squares inside of it. Each of the three squares has their sizes + * determined by the size arguments. If the size is not given (by passing + * in -1), then the size is determined automatically. + * + * @param g The Graphics object to paint with. + * @param x The x location to paint at. + * @param y The y location to paint at. + * @param first The color of the first square. + * @param second The color of the second square. + * @param third The color of the third square. + * @param firstSize The size of the first square. + * @param secondSize The size of the second square. + * @param thirdSize The size of the third square. + */ + private void paintSquare(Graphics g, int x, int y, Color first, + Color second, Color third, int firstSize, + int secondSize, int thirdSize) + { + Color saved = g.getColor(); + if (firstSize == -1) + firstSize = squareSize; + if (secondSize == -1) + secondSize = squareSize * 2 / 3; + if (thirdSize == -1) + thirdSize = squareSize / 3; + int secondOffset = (firstSize - secondSize) / 2; + int thirdOffset = (firstSize - thirdSize) / 2; + + if (first == null) + return; + g.setColor(first); + g.fillRect(x, y, firstSize, firstSize); + if (second == null) + return; + g.setColor(second); + g.fillRect(x + secondOffset, y + secondOffset, secondSize, secondSize); + if (third == null) + return; + g.setColor(third); + g.fillRect(x + thirdOffset, y + thirdOffset, thirdSize, thirdSize); + + g.setColor(saved); + } + + /** + * This method returns the preferred size of the default preview panel. + * + * @return The preferred size of the default preview panel. + */ + public Dimension getPreferredSize() + { + Graphics g = getGraphics(); + FontMetrics fm = g.getFontMetrics(); + g.dispose(); + + int strWidth = fm.stringWidth(sample); + int strHeight = fm.getHeight(); + + int h1 = (strHeight + 2 * textPadding) * 3 + 2 * smallGap; + int h2 = 2 * squareSize + largeGap; + + int height = Math.max(h1, h2); + + int width = 3 * (squareSize + largeGap) + strWidth + 2 * textPadding + + largeGap + rightSideRectWidth; + + Insets insets = getInsets(); + + return new Dimension(width + insets.right + insets.left, + height + insets.top + insets.bottom); + } +} diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultRGBChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/DefaultRGBChooserPanel.java new file mode 100644 index 0000000..39a1732 --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/DefaultRGBChooserPanel.java @@ -0,0 +1,402 @@ +/* DefaultRGHChooserPanel.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; + +import javax.swing.Icon; +import javax.swing.JColorChooser; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * This is the default RGB panel for the JColorChooser. The color is selected + * using three sliders that represent the RGB values. + */ +class DefaultRGBChooserPanel extends AbstractColorChooserPanel +{ + /** + * This class handles the slider value changes for all three sliders. + */ + class SliderHandler implements ChangeListener + { + /** + * This method is called whenever any of the slider values change. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (updateChange) + return; + + int color = R.getValue() << 16 | G.getValue() << 8 | B.getValue(); + + sliderChange = true; + getColorSelectionModel().setSelectedColor(new Color(color)); + sliderChange = false; + } + } + + /** + * This class handles the Spinner values changing. + */ + class SpinnerHandler implements ChangeListener + { + /** + * This method is called whenever any of the JSpinners change values. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (updateChange) + return; + + int red = ((Number) RSpinner.getValue()).intValue(); + int green = ((Number) GSpinner.getValue()).intValue(); + int blue = ((Number) BSpinner.getValue()).intValue(); + + int color = red << 16 | green << 8 | blue; + + spinnerChange = true; + getColorSelectionModel().setSelectedColor(new Color(color)); + spinnerChange = false; + } + } + + /** Whether the color change was initiated by the spinners. + * This is package-private to avoid an accessor method. */ + transient boolean spinnerChange = false; + + /** Whether the color change was initiated by the sliders. + * This is package-private to avoid an accessor method. */ + transient boolean sliderChange = false; + + /** + * Whether the change was forced by the chooser (meaning the color has + * already been changed). + * This is package-private to avoid an accessor method. + */ + transient boolean updateChange = false; + + /** The ChangeListener for the sliders. */ + private transient ChangeListener colorChanger; + + /** The ChangeListener for the spinners. */ + private transient ChangeListener spinnerHandler; + + /** The slider that handles the red values. + * This is package-private to avoid an accessor method. */ + transient JSlider R; + + /** The slider that handles the green values. + * This is package-private to avoid an accessor method. */ + transient JSlider G; + + /** The slider that handles the blue values. + * This is package-private to avoid an accessor method. */ + transient JSlider B; + + /** The label for the red slider. */ + private transient JLabel RLabel; + + /** The label for the green slider. */ + private transient JLabel GLabel; + + /** The label for the blue slider. */ + private transient JLabel BLabel; + + /** The spinner that handles the red values. + * This is package-private to avoid an accessor method. */ + transient JSpinner RSpinner; + + /** The spinner that handles the green values. + * This is package-private to avoid an accessor method. */ + transient JSpinner GSpinner; + + /** The spinner that handles the blue values. + * This is package-private to avoid an accessor method. */ + transient JSpinner BSpinner; + + /** + * Creates a new DefaultRGBChooserPanel object. + */ + public DefaultRGBChooserPanel() + { + super(); + } + + /** + * This method returns the name displayed in the JTabbedPane. + * + * @return The name displayed in the JTabbedPane. + */ + public String getDisplayName() + { + return "RGB"; + } + + /** + * This method updates the chooser panel with the new color chosen in the + * JColorChooser. + */ + public void updateChooser() + { + Color c = getColorFromModel(); + int rgb = c.getRGB(); + + int red = rgb >> 16 & 0xff; + int green = rgb >> 8 & 0xff; + int blue = rgb & 0xff; + + updateChange = true; + + if (! sliderChange) + { + if (R != null) + R.setValue(red); + if (G != null) + G.setValue(green); + if (B != null) + B.setValue(blue); + } + if (! spinnerChange) + { + if (GSpinner != null) + GSpinner.setValue(new Integer(green)); + if (RSpinner != null) + RSpinner.setValue(new Integer(red)); + if (BSpinner != null) + BSpinner.setValue(new Integer(blue)); + } + + updateChange = false; + + revalidate(); + repaint(); + } + + /** + * This method builds the chooser panel. + */ + protected void buildChooser() + { + setLayout(new GridBagLayout()); + + RLabel = new JLabel("Red"); + RLabel.setDisplayedMnemonic('d'); + GLabel = new JLabel("Green"); + GLabel.setDisplayedMnemonic('n'); + BLabel = new JLabel("Blue"); + BLabel.setDisplayedMnemonic('B'); + + R = new JSlider(SwingConstants.HORIZONTAL, 0, 255, 255); + G = new JSlider(SwingConstants.HORIZONTAL, 0, 255, 255); + B = new JSlider(SwingConstants.HORIZONTAL, 0, 255, 255); + + R.setPaintTicks(true); + R.setSnapToTicks(false); + G.setPaintTicks(true); + G.setSnapToTicks(false); + B.setPaintTicks(true); + B.setSnapToTicks(false); + + R.setLabelTable(R.createStandardLabels(85)); + R.setPaintLabels(true); + G.setLabelTable(G.createStandardLabels(85)); + G.setPaintLabels(true); + B.setLabelTable(B.createStandardLabels(85)); + B.setPaintLabels(true); + + R.setMajorTickSpacing(85); + G.setMajorTickSpacing(85); + B.setMajorTickSpacing(85); + + R.setMinorTickSpacing(17); + G.setMinorTickSpacing(17); + B.setMinorTickSpacing(17); + + RSpinner = new JSpinner(new SpinnerNumberModel(R.getValue(), + R.getMinimum(), + R.getMaximum(), 1)); + GSpinner = new JSpinner(new SpinnerNumberModel(G.getValue(), + G.getMinimum(), + G.getMaximum(), 1)); + BSpinner = new JSpinner(new SpinnerNumberModel(B.getValue(), + B.getMinimum(), + B.getMaximum(), 1)); + + RLabel.setLabelFor(R); + GLabel.setLabelFor(G); + BLabel.setLabelFor(B); + + GridBagConstraints bag = new GridBagConstraints(); + bag.fill = GridBagConstraints.VERTICAL; + + bag.gridx = 0; + bag.gridy = 0; + add(RLabel, bag); + + bag.gridx = 1; + add(R, bag); + + bag.gridx = 2; + add(RSpinner, bag); + + bag.gridx = 0; + bag.gridy = 1; + add(GLabel, bag); + + bag.gridx = 1; + add(G, bag); + + bag.gridx = 2; + add(GSpinner, bag); + + bag.gridx = 0; + bag.gridy = 2; + add(BLabel, bag); + + bag.gridx = 1; + add(B, bag); + + bag.gridx = 2; + add(BSpinner, bag); + + installListeners(); + } + + /** + * This method uninstalls the chooser panel from the JColorChooser. + * + * @param chooser The JColorChooser to remove this chooser panel from. + */ + public void uninstallChooserPanel(JColorChooser chooser) + { + uninstallListeners(); + removeAll(); + + R = null; + G = null; + B = null; + + RSpinner = null; + GSpinner = null; + BSpinner = null; + + super.uninstallChooserPanel(chooser); + } + + /** + * This method uninstalls any listeners that were added by the chooser + * panel. + */ + private void uninstallListeners() + { + R.removeChangeListener(colorChanger); + G.removeChangeListener(colorChanger); + B.removeChangeListener(colorChanger); + + colorChanger = null; + + RSpinner.removeChangeListener(spinnerHandler); + GSpinner.removeChangeListener(spinnerHandler); + BSpinner.removeChangeListener(spinnerHandler); + + spinnerHandler = null; + } + + /** + * This method installs any listeners that the chooser panel needs to + * operate. + */ + private void installListeners() + { + colorChanger = new SliderHandler(); + + R.addChangeListener(colorChanger); + G.addChangeListener(colorChanger); + B.addChangeListener(colorChanger); + + spinnerHandler = new SpinnerHandler(); + + RSpinner.addChangeListener(spinnerHandler); + GSpinner.addChangeListener(spinnerHandler); + BSpinner.addChangeListener(spinnerHandler); + } + + /** + * This method returns the small display icon. + * + * @return The small display icon. + */ + public Icon getSmallDisplayIcon() + { + return null; + } + + /** + * This method returns the large display icon. + * + * @return The large display icon. + */ + public Icon getLargeDisplayIcon() + { + return null; + } + + /** + * This method paints the default RGB chooser panel. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + super.paint(g); + } +} diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java new file mode 100644 index 0000000..f28af4c --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java @@ -0,0 +1,893 @@ +/* DefaultSwatchChooserPanel.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.colorchooser; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.Icon; +import javax.swing.JColorChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * This class is the DefaultSwatchChooserPanel. This chooser panel displays a + * set of colors that can be picked. Recently picked items will go into a + * side panel so the user can see the history of the chosen colors. + */ +class DefaultSwatchChooserPanel extends AbstractColorChooserPanel +{ + /** The main panel that holds the set of choosable colors. */ + MainSwatchPanel mainPalette; + + /** A panel that holds the recent colors. */ + RecentSwatchPanel recentPalette; + + /** The mouse handlers for the panels. */ + MouseListener mouseHandler; + + /** + * This the base class for all swatch panels. Swatch panels are panels that + * hold a set of blocks where colors are displayed. + */ + abstract static class SwatchPanel extends JPanel + { + /** The width of each block. */ + protected int cellWidth = 10; + + /** The height of each block. */ + protected int cellHeight = 10; + + /** The gap between blocks. */ + protected int gap = 1; + + /** The number of rows in the swatch panel. */ + protected int numRows; + + /** The number of columns in the swatch panel. */ + protected int numCols; + + /** + * Creates a new SwatchPanel object. + */ + SwatchPanel() + { + super(); + setBackground(Color.WHITE); + } + + /** + * This method returns the preferred size of the swatch panel based on the + * number of rows and columns and the size of each cell. + * + * @return The preferred size of the swatch panel. + */ + public Dimension getPreferredSize() + { + int height = numRows * cellHeight + (numRows - 1) * gap; + int width = numCols * cellWidth + (numCols - 1) * gap; + Insets insets = getInsets(); + + return new Dimension(width + insets.left + insets.right, + height + insets.top + insets.bottom); + } + + /** + * This method returns the color for the given position. + * + * @param x The x coordinate of the position. + * @param y The y coordinate of the position. + * + * @return The color at the given position. + */ + public abstract Color getColorForPosition(int x, int y); + + /** + * This method initializes the colors for the swatch panel. + */ + protected abstract void initializeColors(); + } + + /** + * This is the main swatch panel. This panel sits in the middle and allows a + * set of colors to be picked which will move to the recent swatch panel. + */ + static class MainSwatchPanel extends SwatchPanel + { + /** The color describing (204, 255, 255) */ + public static final Color C204255255 = new Color(204, 204, 255); + + /** The color describing (255, 204, 204) */ + public static final Color C255204204 = new Color(255, 204, 204); + + /** The color describing (204, 255, 204) */ + public static final Color C204255204 = new Color(204, 255, 204); + + /** The color describing (204, 204, 204) */ + public static final Color C204204204 = new Color(204, 204, 204); + + /** The color (153, 153, 255). */ + public static final Color C153153255 = new Color(153, 153, 255); + + /** The color (51, 51, 255). */ + public static final Color C051051255 = new Color(51, 51, 255); + + /** The color (153, 0, 153). */ + public static final Color C153000153 = new Color(153, 0, 153); + + /** The color (0, 51, 51). */ + public static final Color C000051051 = new Color(0, 51, 51); + + /** The color (51, 0, 51). */ + public static final Color C051000051 = new Color(51, 0, 51); + + /** The color (51, 51, 0). */ + public static final Color C051051000 = new Color(51, 51, 0); + + /** The color (102, 102, 0). */ + public static final Color C102102000 = new Color(102, 102, 0); + + /** The color (153, 255, 153). */ + public static final Color C153255153 = new Color(153, 255, 153); + + /** The color (102, 255, 102). */ + public static final Color C102255102 = new Color(102, 255, 102); + + /** The color (0, 102, 102). */ + public static final Color C000102102 = new Color(0, 102, 102); + + /** The color (102, 0, 102). */ + public static final Color C102000102 = new Color(102, 0, 102); + + /** The color (0, 153, 153). */ + public static final Color C000153153 = new Color(0, 153, 153); + + /** The color (153, 153, 0). */ + public static final Color C153153000 = new Color(153, 153, 0); + + /** The color (204, 204, 0). */ + public static final Color C204204000 = new Color(204, 204, 0); + + /** The color (204, 0, 204). */ + public static final Color C204000204 = new Color(204, 0, 204); + + /** The color (0, 204, 204). */ + public static final Color C000204204 = new Color(0, 204, 204); + + /** The color (51, 255, 51). */ + public static final Color C051255051 = new Color(51, 255, 51); + + /** The color (255, 51, 51). */ + public static final Color C255051051 = new Color(255, 51, 51); + + /** The color (255, 102, 102). */ + public static final Color C255102102 = new Color(255, 102, 102); + + /** The color (102, 102, 255). */ + public static final Color C102102255 = new Color(102, 102, 255); + + /** The color (255, 153, 153). */ + public static final Color C255153153 = new Color(255, 153, 153); + static Color[] colors = + { + // Row 1 + Color.WHITE, new Color(204, 255, 255), C204255255, C204255255, C204255255, + C204255255, C204255255, C204255255, C204255255, + C204255255, C204255255, new Color(255, 204, 255), + C255204204, C255204204, C255204204, C255204204, + C255204204, C255204204, C255204204, C255204204, + C255204204, new Color(255, 255, 204), C204255204, + C204255204, C204255204, C204255204, C204255204, + C204255204, C204255204, C204255204, C204255204, + + // Row 2 + C204204204, new Color(153, 255, 255), new Color(153, 204, 255), C153153255, + C153153255, C153153255, C153153255, C153153255, + C153153255, C153153255, new Color(204, 153, 255), + new Color(255, 153, 255), + new Color(255, 153, 204), C255153153, C255153153, + C255153153, C255153153, C255153153, C255153153, + C255153153, new Color(255, 204, 153), + new Color(255, 255, 153), + new Color(204, 255, 153), C153255153, C153255153, + C153255153, C153255153, C153255153, C153255153, + C153255153, new Color(153, 255, 204), + + // Row 3 + C204204204, new Color(102, 255, 255), new Color(102, 204, 255), + new Color(102, 153, 255), C102102255, C102102255, + C102102255, C102102255, C102102255, + new Color(153, 102, 255), + new Color(204, 102, 255), + new Color(255, 102, 255), + new Color(255, 102, 204), + new Color(255, 102, 153), C255102102, C255102102, + C255102102, C255102102, C255102102, + new Color(255, 153, 102), + new Color(255, 204, 102), + new Color(255, 255, 102), + new Color(204, 255, 102), + new Color(153, 255, 102), C102255102, C102255102, + C102255102, C102255102, C102255102, + new Color(102, 255, 153), + new Color(102, 255, 204), + + // Row 4 + new Color(153, 153, 153), new Color(51, 255, 255), new Color(51, 204, 255), + new Color(51, 153, 255), new Color(51, 102, 255), + C051051255, C051051255, C051051255, + new Color(102, 51, 255), new Color(153, 51, 255), + new Color(204, 51, 255), new Color(255, 51, 255), + new Color(255, 51, 204), new Color(255, 51, 153), + new Color(255, 51, 102), C255051051, C255051051, + C255051051, new Color(255, 102, 51), + new Color(255, 153, 51), new Color(255, 204, 51), + new Color(255, 255, 51), new Color(204, 255, 51), + new Color(153, 255, 51), new Color(102, 255, 51), + C051255051, C051255051, C051255051, + new Color(51, 255, 102), new Color(51, 255, 153), + new Color(51, 255, 204), + + // Row 5 + new Color(153, 153, 153), new Color(0, 255, 255), new Color(0, 204, 255), + new Color(0, 153, 255), new Color(0, 102, 255), + new Color(0, 51, 255), new Color(0, 0, 255), + new Color(51, 0, 255), new Color(102, 0, 255), + new Color(153, 0, 255), new Color(204, 0, 255), + new Color(255, 0, 255), new Color(255, 0, 204), + new Color(255, 0, 153), new Color(255, 0, 102), + new Color(255, 0, 51), new Color(255, 0, 0), + new Color(255, 51, 0), new Color(255, 102, 0), + new Color(255, 153, 0), new Color(255, 204, 0), + new Color(255, 255, 0), new Color(204, 255, 0), + new Color(153, 255, 0), new Color(102, 255, 0), + new Color(51, 255, 0), new Color(0, 255, 0), + new Color(0, 255, 51), new Color(0, 255, 102), + new Color(0, 255, 153), new Color(0, 255, 204), + + // Row 6 + new Color(102, 102, 102), C000204204, C000204204, new Color(0, 153, 204), + new Color(0, 102, 204), new Color(0, 51, 204), + new Color(0, 0, 204), new Color(51, 0, 204), + new Color(102, 0, 204), new Color(153, 0, 204), + C204000204, C204000204, C204000204, + new Color(204, 0, 153), new Color(204, 0, 102), + new Color(204, 0, 51), new Color(204, 0, 0), + new Color(204, 51, 0), new Color(204, 102, 0), + new Color(204, 153, 0), C204204000, C204204000, + C204204000, new Color(153, 204, 0), + new Color(102, 204, 0), new Color(51, 204, 0), + new Color(0, 204, 0), new Color(0, 204, 51), + new Color(0, 204, 102), new Color(0, 204, 153), + new Color(0, 204, 204), + + // Row 7 + new Color(102, 102, 102), C000153153, C000153153, C000153153, + new Color(0, 102, 153), new Color(0, 51, 153), + new Color(0, 0, 153), new Color(51, 0, 153), + new Color(102, 0, 153), C153000153, C153000153, + C153000153, C153000153, C153000153, + new Color(153, 0, 102), new Color(153, 0, 51), + new Color(153, 0, 0), new Color(153, 51, 0), + new Color(153, 102, 0), C153153000, C153153000, + C153153000, C153153000, C153153000, + new Color(102, 153, 0), new Color(51, 153, 0), + new Color(0, 153, 0), new Color(0, 153, 51), + new Color(0, 153, 102), C000153153, C000153153, + + // Row 8 + new Color(51, 51, 51), C000102102, C000102102, C000102102, C000102102, + new Color(0, 51, 102), new Color(0, 0, 102), + new Color(51, 0, 102), C102000102, C102000102, + C102000102, C102000102, C102000102, C102000102, + C102000102, new Color(102, 0, 51), + new Color(102, 0, 0), new Color(102, 51, 0), + C102102000, C102102000, C102102000, C102102000, + C102102000, C102102000, C102102000, + new Color(51, 102, 0), new Color(0, 102, 0), + new Color(0, 102, 51), C000102102, C000102102, + C000102102, + + // Row 9. + Color.BLACK, C000051051, C000051051, C000051051, C000051051, C000051051, + new Color(0, 0, 51), C051000051, C051000051, + C051000051, C051000051, C051000051, C051000051, + C051000051, C051000051, C051000051, + new Color(51, 0, 0), C051051000, C051051000, + C051051000, C051051000, C051051000, C051051000, + C051051000, C051051000, new Color(0, 51, 0), + C000051051, C000051051, C000051051, C000051051, + new Color(51, 51, 51) + }; + + /** + * Creates a new MainSwatchPanel object. + */ + MainSwatchPanel() + { + super(); + numCols = 31; + numRows = 9; + initializeColors(); + revalidate(); + } + + /** + * This method returns the color for the given position. + * + * @param x The x location for the position. + * @param y The y location for the position. + * + * @return The color for the given position. + */ + public Color getColorForPosition(int x, int y) + { + if (x % (cellWidth + gap) > cellWidth + || y % (cellHeight + gap) > cellHeight) + // position is located in gap. + return null; + + int row = y / (cellHeight + gap); + int col = x / (cellWidth + gap); + return colors[row * numCols + col]; + } + + /** + * This method initializes the colors for the main swatch panel. + */ + protected void initializeColors() + { + // Unnecessary + } + + /** + * This method paints the main graphics panel with the given Graphics + * object. + * + * @param graphics The Graphics object to paint with. + */ + public void paint(Graphics graphics) + { + int index = 0; + Insets insets = getInsets(); + int currX = insets.left; + int currY = insets.top; + Color saved = graphics.getColor(); + + for (int i = 0; i < numRows; i++) + { + for (int j = 0; j < numCols; j++) + { + graphics.setColor(colors[index++]); + graphics.fill3DRect(currX, currY, cellWidth, cellHeight, true); + currX += gap + cellWidth; + } + currX = insets.left; + currY += gap + cellHeight; + } + graphics.setColor(saved); + } + + /** + * This method returns the tooltip text for the given MouseEvent. + * + * @param e The MouseEvent to find tooltip text for. + * + * @return The tooltip text. + */ + public String getToolTipText(MouseEvent e) + { + Color c = getColorForPosition(e.getX(), e.getY()); + if (c == null) + return null; + return (c.getRed() + "," + c.getGreen() + "," + c.getBlue()); + } + } + + /** + * This class is the recent swatch panel. It holds recently selected colors. + */ + static class RecentSwatchPanel extends SwatchPanel + { + /** The array for storing recently stored colors. */ + Color[] colors; + + /** The default color. */ + public static final Color defaultColor = Color.GRAY; + + /** The index of the array that is the start. */ + int start = 0; + + /** + * Creates a new RecentSwatchPanel object. + */ + RecentSwatchPanel() + { + super(); + numCols = 5; + numRows = 7; + initializeColors(); + revalidate(); + } + + /** + * This method returns the color for the given position. + * + * @param x The x coordinate of the position. + * @param y The y coordinate of the position. + * + * @return The color for the given position. + */ + public Color getColorForPosition(int x, int y) + { + if (x % (cellWidth + gap) > cellWidth + || y % (cellHeight + gap) > cellHeight) + // position is located in gap. + return null; + + int row = y / (cellHeight + gap); + int col = x / (cellWidth + gap); + + return colors[getIndexForCell(row, col)]; + } + + /** + * This method initializes the colors for the recent swatch panel. + */ + protected void initializeColors() + { + colors = new Color[numRows * numCols]; + for (int i = 0; i < colors.length; i++) + colors[i] = defaultColor; + } + + /** + * This method returns the array index for the given row and column. + * + * @param row The row. + * @param col The column. + * + * @return The array index for the given row and column. + */ + private int getIndexForCell(int row, int col) + { + return ((row * numCols) + col + start) % (numRows * numCols); + } + + /** + * This method adds the given color to the beginning of the swatch panel. + * Package-private to avoid an accessor method. + * + * @param c The color to add. + */ + void addColorToQueue(Color c) + { + if (--start == -1) + start = numRows * numCols - 1; + + colors[start] = c; + } + + /** + * This method paints the panel with the given Graphics object. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + Color saved = g.getColor(); + Insets insets = getInsets(); + int currX = insets.left; + int currY = insets.top; + + for (int i = 0; i < numRows; i++) + { + for (int j = 0; j < numCols; j++) + { + g.setColor(colors[getIndexForCell(i, j)]); + g.fill3DRect(currX, currY, cellWidth, cellHeight, true); + currX += cellWidth + gap; + } + currX = insets.left; + currY += cellWidth + gap; + } + } + + /** + * This method returns the tooltip text for the given MouseEvent. + * + * @param e The MouseEvent. + * + * @return The tooltip text. + */ + public String getToolTipText(MouseEvent e) + { + Color c = getColorForPosition(e.getX(), e.getY()); + if (c == null) + return null; + return c.getRed() + "," + c.getGreen() + "," + c.getBlue(); + } + } + + /** + * This class handles mouse events for the two swatch panels. + */ + class MouseHandler extends MouseAdapter + { + /** + * This method is called whenever the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + SwatchPanel panel = (SwatchPanel) e.getSource(); + Color c = panel.getColorForPosition(e.getX(), e.getY()); + recentPalette.addColorToQueue(c); + DefaultSwatchChooserPanel.this.getColorSelectionModel().setSelectedColor(c); + DefaultSwatchChooserPanel.this.repaint(); + } + } + + /** + * This is the layout manager for the main panel. + */ + static class MainPanelLayout implements LayoutManager + { + /** + * This method is called when a new component is added to the container. + * + * @param name The name of the component. + * @param comp The added component. + */ + public void addLayoutComponent(String name, Component comp) + { + } + + /** + * This method is called to set the size and position of the child + * components for the given container. + * + * @param parent The container to lay out. + */ + public void layoutContainer(Container parent) + { + Component[] comps = parent.getComponents(); + Insets insets = parent.getInsets(); + Dimension[] pref = new Dimension[comps.length]; + + int xpos = 0; + int ypos = 0; + int maxHeight = 0; + int totalWidth = 0; + + for (int i = 0; i < comps.length; i++) + { + pref[i] = comps[i].getPreferredSize(); + if (pref[i] == null) + return; + maxHeight = Math.max(maxHeight, pref[i].height); + totalWidth += pref[i].width; + } + + ypos = (parent.getSize().height - maxHeight) / 2 + insets.top; + xpos = insets.left + (parent.getSize().width - totalWidth) / 2; + + for (int i = 0; i < comps.length; i++) + { + if (pref[i] == null) + continue; + comps[i].setBounds(xpos, ypos, pref[i].width, pref[i].height); + xpos += pref[i].width; + } + } + + /** + * This method is called when a component is removed from the container. + * + * @param comp The component that was removed. + */ + public void removeLayoutComponent(Component comp) + { + } + + /** + * This methods calculates the minimum layout size for the container. + * + * @param parent The container. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + /** + * This method returns the preferred layout size for the given container. + * + * @param parent The container. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + int xmax = 0; + int ymax = 0; + + Component[] comps = parent.getComponents(); + Dimension pref; + + for (int i = 0; i < comps.length; i++) + { + pref = comps[i].getPreferredSize(); + if (pref == null) + continue; + xmax += pref.width; + ymax = Math.max(ymax, pref.height); + } + + Insets insets = parent.getInsets(); + + return new Dimension(insets.left + insets.right + xmax, + insets.top + insets.bottom + ymax); + } + } + + /** + * This is the layout manager for the recent swatch panel. + */ + static class RecentPanelLayout implements LayoutManager + { + /** + * This method is called when a component is added to the container. + * + * @param name The name of the component. + * @param comp The added component. + */ + public void addLayoutComponent(String name, Component comp) + { + // Nothing needs to be done. + } + + /** + * This method sets the size and position of the child components of the + * given container. + * + * @param parent The container to lay out. + */ + public void layoutContainer(Container parent) + { + Component[] comps = parent.getComponents(); + Dimension parentSize = parent.getSize(); + Insets insets = parent.getInsets(); + int currY = insets.top; + Dimension pref; + + for (int i = 0; i < comps.length; i++) + { + pref = comps[i].getPreferredSize(); + if (pref == null) + continue; + comps[i].setBounds(insets.left, currY, pref.width, pref.height); + currY += pref.height; + } + } + + /** + * This method calculates the minimum layout size for the given container. + * + * @param parent The container. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + /** + * This method calculates the preferred layout size for the given + * container. + * + * @param parent The container. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + int width = 0; + int height = 0; + Insets insets = parent.getInsets(); + Component[] comps = parent.getComponents(); + Dimension pref; + for (int i = 0; i < comps.length; i++) + { + pref = comps[i].getPreferredSize(); + if (pref != null) + { + width = Math.max(width, pref.width); + height += pref.height; + } + } + + return new Dimension(width + insets.left + insets.right, + height + insets.top + insets.bottom); + } + + /** + * This method is called whenever a component is removed from the + * container. + * + * @param comp The removed component. + */ + public void removeLayoutComponent(Component comp) + { + // Nothing needs to be done. + } + } + + /** + * Creates a new DefaultSwatchChooserPanel object. + */ + DefaultSwatchChooserPanel() + { + super(); + } + + /** + * This method updates the chooser panel with the new value from the + * JColorChooser. + */ + public void updateChooser() + { + } + + /** + * This method builds the chooser panel. + */ + protected void buildChooser() + { + // The structure of the swatch panel is: + // One large panel (minus the insets). + // Inside that panel, there are two panels, one holds the palette. + // The other holds the label and the recent colors palette. + // The two palettes are two custom swatch panels. + setLayout(new MainPanelLayout()); + + JPanel mainPaletteHolder = new JPanel(); + JPanel recentPaletteHolder = new JPanel(); + + mainPalette = new MainSwatchPanel(); + recentPalette = new RecentSwatchPanel(); + JLabel label = new JLabel("Recent:"); + + mouseHandler = new MouseHandler(); + mainPalette.addMouseListener(mouseHandler); + recentPalette.addMouseListener(mouseHandler); + + mainPaletteHolder.setLayout(new BorderLayout()); + mainPaletteHolder.add(mainPalette, BorderLayout.CENTER); + + recentPaletteHolder.setLayout(new RecentPanelLayout()); + recentPaletteHolder.add(label); + recentPaletteHolder.add(recentPalette); + + JPanel main = new JPanel(); + main.add(mainPaletteHolder); + main.add(recentPaletteHolder); + + this.add(main); + } + + /** + * This method removes the chooser panel from the JColorChooser. + * + * @param chooser The JColorChooser this panel is being removed from. + */ + public void uninstallChooserPanel(JColorChooser chooser) + { + recentPalette = null; + mainPalette = null; + + removeAll(); + super.uninstallChooserPanel(chooser); + } + + /** + * This method returns the JTabbedPane displayed name. + * + * @return The name displayed in the JTabbedPane. + */ + public String getDisplayName() + { + return "Swatches"; + } + + /** + * This method returns the small display icon. + * + * @return The small display icon. + */ + public Icon getSmallDisplayIcon() + { + return null; + } + + /** + * This method returns the large display icon. + * + * @return The large display icon. + */ + public Icon getLargeDisplayIcon() + { + return null; + } + + /** + * This method paints the chooser panel with the given Graphics object. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + super.paint(g); + } + + /** + * This method returns the tooltip text for the given MouseEvent. + * + * @param e The MouseEvent. + * + * @return The tooltip text. + */ + public String getToolTipText(MouseEvent e) + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/colorchooser/package.html b/libjava/classpath/javax/swing/colorchooser/package.html new file mode 100644 index 0000000..c04e96e --- /dev/null +++ b/libjava/classpath/javax/swing/colorchooser/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.colorchooser + + +

Provides support classes for the {@link javax.swing.JColorChooser} +component.

+ + + diff --git a/libjava/classpath/javax/swing/event/AncestorEvent.java b/libjava/classpath/javax/swing/event/AncestorEvent.java new file mode 100644 index 0000000..d06c6e3 --- /dev/null +++ b/libjava/classpath/javax/swing/event/AncestorEvent.java @@ -0,0 +1,100 @@ +/* AncestorEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.awt.AWTEvent; +import java.awt.Container; + +import javax.swing.JComponent; + +/** + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class AncestorEvent extends AWTEvent +{ + private static final long serialVersionUID = -8079801679695605002L; + + public static final int ANCESTOR_ADDED = 1; + public static final int ANCESTOR_REMOVED = 2; + public static final int ANCESTOR_MOVED = 3; + + private JComponent sourceComponent; + private Container ancestor; + private Container ancestorParent; + + /** + * @param source Source component + * @param id ID + * @param ancestor ancestor + * @param ancestorParent parent ancestor + */ + public AncestorEvent(JComponent source, int id, Container ancestor, + Container ancestorParent) + { + super(source, id); + this.sourceComponent = source; + this.ancestor = ancestor; + this.ancestorParent = ancestorParent; + } + + /** + * Returns the ancestor of this event. + */ + public Container getAncestor() + { + return ancestor; + } + + /** + * Returns the ancester parent of this event. + */ + public Container getAncestorParent() + { + return ancestorParent; + } + + /** + * Returns the source of this event. + */ + public JComponent getComponent() + { + return sourceComponent; + } +} diff --git a/libjava/classpath/javax/swing/event/AncestorListener.java b/libjava/classpath/javax/swing/event/AncestorListener.java new file mode 100644 index 0000000..61d5aed --- /dev/null +++ b/libjava/classpath/javax/swing/event/AncestorListener.java @@ -0,0 +1,69 @@ +/* AncestorListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * AncestorListener Interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface AncestorListener extends EventListener { + + /** + * Ancestor Added + * @param event Ancestor Event + */ + void ancestorAdded(AncestorEvent event); + + /** + * Ancestor Removed + * @param event Ancestor Event + */ + void ancestorRemoved(AncestorEvent event); + + /** + * Ancestor Moved + * @param event Ancestor Event + */ + void ancestorMoved(AncestorEvent event); + + +} // AncestorListener diff --git a/libjava/classpath/javax/swing/event/CaretEvent.java b/libjava/classpath/javax/swing/event/CaretEvent.java new file mode 100644 index 0000000..c4870a8 --- /dev/null +++ b/libjava/classpath/javax/swing/event/CaretEvent.java @@ -0,0 +1,79 @@ +/* CaretEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventObject; + +/** + * CaretEvent + * @author Andrew Selkirk + */ +public abstract class CaretEvent extends EventObject { + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * CaretEvent constructor + * @param source Source object + */ + public CaretEvent(Object source) { + super(source); + } // CaretEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * Get caret location + * @returns the dot + */ + public abstract int getDot(); + + /** + * Get mark + * @returns the mark + */ + public abstract int getMark(); + + +} // CaretEvent diff --git a/libjava/classpath/javax/swing/event/CaretListener.java b/libjava/classpath/javax/swing/event/CaretListener.java new file mode 100644 index 0000000..aeee434 --- /dev/null +++ b/libjava/classpath/javax/swing/event/CaretListener.java @@ -0,0 +1,56 @@ +/* CaretListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * CaretListener public interface + * @author Andrew Selkirk + */ +public interface CaretListener extends EventListener { + + /** + * Caret position has been updated + * @param event Caret Event + */ + void caretUpdate(CaretEvent event); + + +} // CaretListener diff --git a/libjava/classpath/javax/swing/event/CellEditorListener.java b/libjava/classpath/javax/swing/event/CellEditorListener.java new file mode 100644 index 0000000..d2dd5ba --- /dev/null +++ b/libjava/classpath/javax/swing/event/CellEditorListener.java @@ -0,0 +1,62 @@ +/* CellEditorListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * CellEditorListener public interface + * @author Andrew Selkirk + */ +public interface CellEditorListener extends EventListener { + + /** + * Editing has been canceled + * @param event Change Event + */ + void editingCanceled(ChangeEvent event); + + /** + * Editing has been stopped + * @param event Change Event + */ + void editingStopped(ChangeEvent event); + + +} // CellEditorListener diff --git a/libjava/classpath/javax/swing/event/ChangeEvent.java b/libjava/classpath/javax/swing/event/ChangeEvent.java new file mode 100644 index 0000000..f75c15a --- /dev/null +++ b/libjava/classpath/javax/swing/event/ChangeEvent.java @@ -0,0 +1,59 @@ +/* ChangeEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventObject; + +/** + * ChangeEvent + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class ChangeEvent extends EventObject { + + /** + * ChangeEvent constructor + * @param source Source object + */ + public ChangeEvent(Object source) { + super(source); + } // ChangeEvent() + + +} // ChangeEvent diff --git a/libjava/classpath/javax/swing/event/ChangeListener.java b/libjava/classpath/javax/swing/event/ChangeListener.java new file mode 100644 index 0000000..1e58b1d --- /dev/null +++ b/libjava/classpath/javax/swing/event/ChangeListener.java @@ -0,0 +1,57 @@ +/* ChangeListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * ChangeListener interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface ChangeListener extends EventListener { + + /** + * State changed + * @param event Change Event + */ + void stateChanged(ChangeEvent event); + + +} // ChangeListener diff --git a/libjava/classpath/javax/swing/event/DocumentEvent.java b/libjava/classpath/javax/swing/event/DocumentEvent.java new file mode 100644 index 0000000..6a005ea --- /dev/null +++ b/libjava/classpath/javax/swing/event/DocumentEvent.java @@ -0,0 +1,166 @@ +/* DocumentEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import javax.swing.text.Document; +import javax.swing.text.Element; + +/** + * DocumentEvent public interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface DocumentEvent { + + //------------------------------------------------------------- + // Classes ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * ElementChange public interface + */ + public interface ElementChange { + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getIndex + * @returns int + */ + int getIndex(); + + /** + * getElement + * @returns Element + */ + Element getElement(); + + /** + * getChildrenRemoved + * @returns Element[] + */ + Element[] getChildrenRemoved(); + + /** + * getChildrenAdded + * @returns Element[] + */ + Element[] getChildrenAdded(); + + + } // ElementChange + + /** + * EventType + */ + class EventType + { + /** + * INSERT + */ + public static final EventType INSERT = new EventType("INSERT"); // TODO + + /** + * REMOVE + */ + public static final EventType REMOVE = new EventType("REMOVE"); // TODO + + /** + * CHANGE + */ + public static final EventType CHANGE = new EventType("CHANGE"); // TODO + + /** + * typeString + */ + private String type; + + /** + * Constructor EventType + * @param type TODO + */ + private EventType(String type) + { + this.type = type; + } + + /** + * toString + * @returns String + */ + public String toString() + { + return type; + } + } + + /** + * getType + * @returns EventType + */ + EventType getType(); + + /** + * getOffset + * @returns int + */ + int getOffset(); + + /** + * getLength + * @returns int + */ + int getLength(); + + /** + * getDocument + * @returns Document + */ + Document getDocument(); + + /** + * getChange + * @param element TODO + * @returns ElementChange + */ + ElementChange getChange(Element element); + + +} // DocumentEvent diff --git a/libjava/classpath/javax/swing/event/DocumentListener.java b/libjava/classpath/javax/swing/event/DocumentListener.java new file mode 100644 index 0000000..df5e784 --- /dev/null +++ b/libjava/classpath/javax/swing/event/DocumentListener.java @@ -0,0 +1,68 @@ +/* DocumentListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import java.util.EventListener; + +/** + * DocumentListener public interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface DocumentListener extends EventListener { + + /** + * Changed update + * @param event Document Event + */ + void changedUpdate(DocumentEvent event); + + /** + * Insert update + * @param event Document Event + */ + void insertUpdate(DocumentEvent event); + + /** + * Remove update + * @param event Document Event + */ + void removeUpdate(DocumentEvent event); + + +} // DocumentListener diff --git a/libjava/classpath/javax/swing/event/EventListenerList.java b/libjava/classpath/javax/swing/event/EventListenerList.java new file mode 100644 index 0000000..ea14d4d --- /dev/null +++ b/libjava/classpath/javax/swing/event/EventListenerList.java @@ -0,0 +1,302 @@ +/* EventListenerList.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.EventListener; + + +/** + * A utility class for keeping track of {@link EventListener}s. + * + *

Example for using this class: + * + *

 import java.util.EventListener;
+ * import javax.swing.event.EventListenerList;
+ *
+ * class Foo
+ * {
+ *   protected final EventListenerList listeners = new EventListenerList();
+ *   protected BarClosedEvent barClosedEvent = null;
+ *
+ *   public void addBarListener(BarListener l)
+ *   {
+ *     listeners.add(BarListener.class, l);
+ *   }
+ *
+ *   public void removeBarListener(BarListener l)
+ *   {
+ *     listeners.remove(BarListener.class, l);
+ *   }
+ *
+ *   protected void fireBarClosedEvent()
+ *   {
+ *     Object[] l = listeners.getListenerList();
+ *
+ *     for (int i = l.length - 2; i >= 0; i -= 2)
+ *       if (l[i] == BarListener.class)
+ *         {
+ *           // Create the event on demand, when it is needed the first time.
+ *           if (barClosedEvent == null)
+ *             barClosedEvent = new BarClosedEvent(this);
+ *
+ *           ((BarClosedListener) l[i + 1]).barClosed(barClosedEvent);
+ *         }
+ *   }
+ * }
+ * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class EventListenerList + implements Serializable +{ + /** + * An ID for serializing instances of this class; verified with the + * serialver tool of Sun J2SE 1.4.1_01. + */ + static final long serialVersionUID = -5677132037850737084L; + + + /** + * An empty array that is shared by all instances of this class that + * have no listeners. + */ + private static final Object[] NO_LISTENERS = new Object[0]; + + + /** + * An array with all currently registered listeners. The array has + * twice as many elements as there are listeners. For an even + * integer i, listenerList[i] indicates + * the registered class, and listenerList[i+1] is the + * listener. + */ + protected transient Object[] listenerList = NO_LISTENERS; + + + /** + * EventListenerList constructor + */ + public EventListenerList() + { + } + + + /** + * Registers a listener of a specific type. + * + * @param t the type of the listener. + * + * @param listener the listener to add, which must be an instance of + * t, or of a subclass of t. + * + * @throws IllegalArgumentException if listener is not + * an instance of t (or a subclass thereof). + * + * @throws Exception if t is null. + */ + public void add(Class t, EventListener listener) + { + int oldLength; + Object[] newList; + + if (listener == null) + return; + + if (!t.isInstance(listener)) + throw new IllegalArgumentException(); + + oldLength = listenerList.length; + newList = new Object[oldLength + 2]; + if (oldLength > 0) + System.arraycopy(listenerList, 0, newList, 0, oldLength); + + newList[oldLength] = t; + newList[oldLength + 1] = listener; + listenerList = newList; + } + + + /** + * Determines the number of listeners. + */ + public int getListenerCount() + { + return listenerList.length / 2; + } + + + /** + * Determines the number of listeners of a particular class. + * + * @param t the type of listeners to be counted. In order to get + * counted, a subscribed listener must be exactly of class + * t. Thus, subclasses of t will not be + * counted. + */ + public int getListenerCount(Class t) + { + int result = 0; + for (int i = 0; i < listenerList.length; i += 2) + if (t == listenerList[i]) + ++result; + + return result; + } + + + /** + * Get a list of listenerType/listener pairs + * @returns Listener list + */ + public Object[] getListenerList() + { + return listenerList; + } + + + /** + * Retrieves the currently subscribed listeners of a particular + * type. For a listener to be returned, it must have been + * registered with exactly the type c; subclasses are + * not considered equal. + * + *

The returned array can always be cast to c[]. + * Since it is a newly allocated copy, the caller may arbitrarily + * modify the array. + * + * @param c the class which was passed to {@link #add}. + * + * @throws ClassCastException if c does not implement + * the {@link EventListener} interface. + * + * @throws NullPointerException if c is + * null. + * + * @returns an array of c whose elements are the + * currently subscribed listeners of the specified type. If there + * are no such listeners, an empty array is returned. + * + * @since 1.3 + */ + public EventListener[] getListeners(Class c) + { + int count, f; + EventListener[] result; + + count = getListenerCount(c); + result = (EventListener[]) Array.newInstance(c, count); + f = 0; + for (int i = 0; i < listenerList.length; i += 2) + if (listenerList[i] == c) + result[f++] = (EventListener) listenerList[i + 1]; + + return result; + } + + + /** + * Removes a listener of a specific type. + * + * @param t the type of the listener. + * + * @param listener the listener to remove, which must be an instance + * of t, or of a subclass of t. + * + * @throws IllegalArgumentException if listener is not + * an instance of t (or a subclass thereof). + * + * @throws Exception if t is null. + */ + public void remove(Class t, EventListener listener) + { + Object[] oldList, newList; + int oldLength; + + if (listener == null) + return; + + if (!t.isInstance(listener)) + throw new IllegalArgumentException(); + + oldList = listenerList; + oldLength = oldList.length; + for (int i = 0; i < oldLength; i += 2) + if (oldList[i] == t && oldList[i + 1] == listener) + { + if (oldLength == 2) + newList = NO_LISTENERS; + else + { + newList = new Object[oldLength - 2]; + if (i > 0) + System.arraycopy(oldList, 0, newList, 0, i); + if (i < oldLength - 2) + System.arraycopy(oldList, i + 2, newList, i, + oldLength - 2 - i); + } + listenerList = newList; + return; + } + } + + + /** + * Returns a string representation of this object that may be useful + * for debugging purposes. + */ + public String toString() + { + StringBuffer buf = new StringBuffer("EventListenerList: "); + buf.append(listenerList.length / 2); + buf.append(" listeners: "); + for (int i = 0; i < listenerList.length; i += 2) + { + buf.append(" type "); + buf.append(((Class) listenerList[i]).getName()); + buf.append(" listener "); + buf.append(listenerList[i + 1]); + } + return buf.toString(); + } +} diff --git a/libjava/classpath/javax/swing/event/HyperlinkEvent.java b/libjava/classpath/javax/swing/event/HyperlinkEvent.java new file mode 100644 index 0000000..4afa009 --- /dev/null +++ b/libjava/classpath/javax/swing/event/HyperlinkEvent.java @@ -0,0 +1,162 @@ +/* HyperlinkEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.net.URL; +import java.util.EventObject; + +import javax.swing.text.Element; + +/** + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class HyperlinkEvent extends EventObject +{ + public static final class EventType + { + public static final EventType ENTERED = new EventType("ENTERED"); // TODO + public static final EventType EXITED = new EventType("EXITED"); // TODO + public static final EventType ACTIVATED = new EventType("ACTIVATED"); // TODO + + private String type; + + /** + * Creates a new Event type. + * + * @param type String representing the event type. + */ + private EventType(String type) + { + this.type = type; + } + + /** + * Returns a String of this object. + */ + public String toString() + { + return type; + } + } + + private static final long serialVersionUID = -2054640811732867012L; + + private EventType type; + private URL url; + private String description; + private Element element; + + /** + * Creates a new HyperlinkEvent with the given arguments. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + */ + public HyperlinkEvent(Object source, EventType type, URL url) + { + this (source, type, url, null, null); + } + + /** + * Creates a new HyperlinkEvent with the given arguments. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param description The description for this link. + */ + public HyperlinkEvent(Object source, EventType type, URL url, + String description) + { + this (source, type, url, description, null); + } + + /** + * Creates a new HyperlinkEvent with the given arguments. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param description The description for this link. + * @param element The element in the document representing the anchor. + */ + public HyperlinkEvent(Object source, EventType type, URL url, + String description, Element element) + { + super(source); + this.type = type; + this.url = url; + this.description = description; + this.element = element; + } + + /** + * Returns the element of the document repesenting this anchor. + */ + public Element getSourceElement() + { + return element; + } + + /** + * Returns the URL of this event. + */ + public URL getURL() + { + return url; + } + + /** + * Returns the type of this event. + */ + public EventType getEventType() + { + return type; + } + + /** + * Returns the description of this event. + */ + public String getDescription() + { + return description; + } +} diff --git a/libjava/classpath/javax/swing/event/HyperlinkListener.java b/libjava/classpath/javax/swing/event/HyperlinkListener.java new file mode 100644 index 0000000..5dede99 --- /dev/null +++ b/libjava/classpath/javax/swing/event/HyperlinkListener.java @@ -0,0 +1,57 @@ +/* HyperlinkListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * HyperlinkListener + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface HyperlinkListener extends EventListener { + + /** + * Hyperlink updated + * @param event Hyperlink Event + */ + void hyperlinkUpdate(HyperlinkEvent event); + + +} // HyperlinkListener diff --git a/libjava/classpath/javax/swing/event/InternalFrameAdapter.java b/libjava/classpath/javax/swing/event/InternalFrameAdapter.java new file mode 100644 index 0000000..a2878e7 --- /dev/null +++ b/libjava/classpath/javax/swing/event/InternalFrameAdapter.java @@ -0,0 +1,113 @@ +/* InternalFrameAdapter.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +/** + * InternalFrameAdapter + * @author Andrew Selkirk + */ +public abstract class InternalFrameAdapter implements InternalFrameListener +{ + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * InternalFrameAdapter constructor + */ + public InternalFrameAdapter() { + } // InternalFrameAdapter() + + + //------------------------------------------------------------- + // Interface: InternalFrameListener --------------------------- + //------------------------------------------------------------- + + /** + * 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 diff --git a/libjava/classpath/javax/swing/event/InternalFrameEvent.java b/libjava/classpath/javax/swing/event/InternalFrameEvent.java new file mode 100644 index 0000000..badfa80 --- /dev/null +++ b/libjava/classpath/javax/swing/event/InternalFrameEvent.java @@ -0,0 +1,115 @@ +/* InternalFrameEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.awt.AWTEvent; + +import javax.swing.JInternalFrame; + +/** + * @author Andrew Selkirk + */ +public class InternalFrameEvent extends AWTEvent +{ + private static final long serialVersionUID = -5204823611874873183L; + + /** + * Internal frame activated event + */ + public static final int INTERNAL_FRAME_ACTIVATED = 25554; + + /** + * Internal frame closed event + */ + public static final int INTERNAL_FRAME_CLOSED = 25551; + + /** + * Internal frame closing event + */ + public static final int INTERNAL_FRAME_CLOSING = 25550; + + /** + * Internal frame deactivated event + */ + public static final int INTERNAL_FRAME_DEACTIVATED = 25555; + + /** + * Internal frame deiconifed event + */ + public static final int INTERNAL_FRAME_DEICONIFIED = 25553; + + /** + * Internal frame frame first event + */ + public static final int INTERNAL_FRAME_FIRST = 25549; + + /** + * Internal frame iconified event + */ + public static final int INTERNAL_FRAME_ICONIFIED = 25552; + + /** + * Internal frame last event + */ + public static final int INTERNAL_FRAME_LAST = 25555; + + /** + * Internal frame opened event + */ + public static final int INTERNAL_FRAME_OPENED = 25549; + + /** + * Creates a JInternalFrameEvent object. + * + * @param source The source of this event. + * @param id Then event ID of this event. + */ + public InternalFrameEvent(JInternalFrame source, int id) + { + super(source, id); + } + + /** + * Returns the JInternalFrame object stored in this event. + */ + public JInternalFrame getInternalFrame() + { + return (JInternalFrame) source; + } +} diff --git a/libjava/classpath/javax/swing/event/InternalFrameListener.java b/libjava/classpath/javax/swing/event/InternalFrameListener.java new file mode 100644 index 0000000..d1b2812 --- /dev/null +++ b/libjava/classpath/javax/swing/event/InternalFrameListener.java @@ -0,0 +1,92 @@ +/* InternalFrameListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * InternalFrameListener public interface + * @author Andrew Selkirk + */ +public interface InternalFrameListener extends EventListener { + + /** + * Internal frame activated + * @param event Internal Frame Event + */ + void internalFrameActivated(InternalFrameEvent event); + + /** + * Internal frame closed + * @param event Internal Frame Event + */ + void internalFrameClosed(InternalFrameEvent event); + + /** + * Internal frame closing + * @param event Internal Frame Event + */ + void internalFrameClosing(InternalFrameEvent event); + + /** + * Internal frame deactivated + * @param event Internal Frame Event + */ + void internalFrameDeactivated(InternalFrameEvent event); + + /** + * Internal frame deiconified + * @param event Internal Frame Event + */ + void internalFrameDeiconified(InternalFrameEvent event); + + /** + * Internal frame iconified + * @param event Internal Frame Event + */ + void internalFrameIconified(InternalFrameEvent event); + + /** + * Internal frame opened + * @param event Internal Frame Event + */ + void internalFrameOpened(InternalFrameEvent event); + + +} // InternalFrameListener diff --git a/libjava/classpath/javax/swing/event/ListDataEvent.java b/libjava/classpath/javax/swing/event/ListDataEvent.java new file mode 100644 index 0000000..2a6e6db --- /dev/null +++ b/libjava/classpath/javax/swing/event/ListDataEvent.java @@ -0,0 +1,98 @@ +/* ListDataEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +/** + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class ListDataEvent extends EventObject +{ + private static final long serialVersionUID = 2510353260071004774L; + + public static final int CONTENTS_CHANGED = 0; + public static final int INTERVAL_ADDED = 1; + public static final int INTERVAL_REMOVED = 2; + + private int type = 0; + private int index0 = 0; + private int index1 = 0; + + /** + * Creates a ListDataEvent object. + * + * @param source The source of the event. + * @param type The type of the event + * @param index0 Bottom of range + * @param index1 Top of range + */ + public ListDataEvent(Object source, int type, int index0, int index1) + { + super(source); + this.type = type; + this.index0 = index0; + this.index1 = index1; + } + + /** + * Returns the bottom index. + */ + public int getIndex0() + { + return index0; + } + + /** + * Returns the top index. + */ + public int getIndex1() + { + return index1; + } + + /** + * Returns the type of this event. + */ + public int getType() + { + return type; + } +} diff --git a/libjava/classpath/javax/swing/event/ListDataListener.java b/libjava/classpath/javax/swing/event/ListDataListener.java new file mode 100644 index 0000000..7ce17d8 --- /dev/null +++ b/libjava/classpath/javax/swing/event/ListDataListener.java @@ -0,0 +1,69 @@ +/* ListDataListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * ListDataListener public interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface ListDataListener extends EventListener { + + /** + * Contents Changed + * @param event ListDataEvent Event + */ + void contentsChanged(ListDataEvent event); + + /** + * Interval Added + * @param event ListDataEvent Event + */ + void intervalAdded(ListDataEvent event); + + /** + * Interval Removed + * @param event ListDataEvent Event + */ + void intervalRemoved(ListDataEvent event); + + +} // ListDataListener diff --git a/libjava/classpath/javax/swing/event/ListSelectionEvent.java b/libjava/classpath/javax/swing/event/ListSelectionEvent.java new file mode 100644 index 0000000..e5e4c33 --- /dev/null +++ b/libjava/classpath/javax/swing/event/ListSelectionEvent.java @@ -0,0 +1,126 @@ +/* ListSelectionEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventObject; + +/** + * ListSelectionEvent + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class ListSelectionEvent extends EventObject { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * firstIndex + */ + private int firstIndex = 0; + + /** + * lastIndex + */ + private int lastIndex = 0; + + /** + * isAdjusting + */ + private boolean isAdjusting = false; + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor ListSelectionEvent + * @param source Source + * @param firstIndex First index + * @param lastIndex Last index + * @param isAdjusting Is Adjusting? + */ + public ListSelectionEvent(Object source, int firstIndex, + int lastIndex, boolean isAdjusting) { + super(source); + this.firstIndex = firstIndex; + this.lastIndex = lastIndex; + this.isAdjusting = isAdjusting; + } // ListSelectionEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getFirstIndex + * @returns firstIndex + */ + public int getFirstIndex() { + return firstIndex; + } // getFirstIndex() + + /** + * getLastIndex + * @returns lastIndex + */ + public int getLastIndex() { + return lastIndex; + } // getLastIndex() + + /** + * getValueIsAdjusting + * @returns isAdjusting + */ + public boolean getValueIsAdjusting() { + return isAdjusting; + } // getValueIsAdjusting() + + /** + * String representation + * @returns String representation + */ + public String toString() { + return null; // TODO + } // toString() + + +} // ListSelectionEvent diff --git a/libjava/classpath/javax/swing/event/ListSelectionListener.java b/libjava/classpath/javax/swing/event/ListSelectionListener.java new file mode 100644 index 0000000..4ebf583 --- /dev/null +++ b/libjava/classpath/javax/swing/event/ListSelectionListener.java @@ -0,0 +1,57 @@ +/* ListSelectionListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * ListSelectionListener public interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface ListSelectionListener extends EventListener { + + /** + * Value changed + * @param event List Selection Event + */ + void valueChanged(ListSelectionEvent event); + + +} // ListSelectionListener diff --git a/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java b/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java new file mode 100644 index 0000000..9976167 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java @@ -0,0 +1,115 @@ +/* MenuDragMouseEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.awt.Component; +import java.awt.event.MouseEvent; + +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; + +/** + * MenuDragMouseEvent + * @author Andrew Selkirk + */ +public class MenuDragMouseEvent extends MouseEvent { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * path + */ + private MenuElement[] path = null; + + /** + * manager + */ + private MenuSelectionManager manager = null; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor MenuDragMouseEvent + * @param source Source + * @param id MouseEvent type + * @param when Time + * @param modifiers Key modifiers + * @param x Horizontal position + * @param y Vertical position + * @param clickCount Click count + * @param popupTrigger Popup trigger? + * @param path Path + * @param manager MenuSelectionManager + */ + public MenuDragMouseEvent(Component source, int id, long when, int modifiers, + int x, int y, int clickCount, boolean popupTrigger, + MenuElement[] path, MenuSelectionManager manager) { + super(source, id, when, modifiers, x, y, clickCount, popupTrigger); + this.path = path; + this.manager = manager; + } // MenuDragMouseEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * Get path + * @returns path + */ + public MenuElement[] getPath() { + return path; + } // getPath() + + /** + * Get menu selection manager + * @returns manager + */ + public MenuSelectionManager getMenuSelectionManager() { + return manager; + } // getMenuSelectionManager() + + +} // MenuDragMouseEvent diff --git a/libjava/classpath/javax/swing/event/MenuDragMouseListener.java b/libjava/classpath/javax/swing/event/MenuDragMouseListener.java new file mode 100644 index 0000000..bfca315 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuDragMouseListener.java @@ -0,0 +1,74 @@ +/* MenuDragMouseListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * MenuDragMouseListener public interface + * @author Andrew Selkirk + */ +public interface MenuDragMouseListener extends EventListener { + + /** + * Menu drag mouse dragged + * @param event Menu Drag Mouse Event + */ + void menuDragMouseDragged(MenuDragMouseEvent event); + + /** + * Menu drag mouse entered + * @param event Menu Drag Mouse Event + */ + void menuDragMouseEntered(MenuDragMouseEvent event); + + /** + * Menu drag mouse exited + * @param event Menu Drag Mouse Event + */ + void menuDragMouseExited(MenuDragMouseEvent event); + + /** + * Menu drag mouse released + * @param event Menu Drag Mouse Event + */ + void menuDragMouseReleased(MenuDragMouseEvent event); + + +} // MenuDragMouseListener diff --git a/libjava/classpath/javax/swing/event/MenuEvent.java b/libjava/classpath/javax/swing/event/MenuEvent.java new file mode 100644 index 0000000..35bb5b9 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuEvent.java @@ -0,0 +1,59 @@ +/* MenuEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventObject; + +/** + * MenuEvent + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class MenuEvent extends EventObject { + + /** + * Constructor MenuEvent + * @param source Source object + */ + public MenuEvent(Object source) { + super(source); + } // MenuEvent() + + +} // MenuEvent diff --git a/libjava/classpath/javax/swing/event/MenuKeyEvent.java b/libjava/classpath/javax/swing/event/MenuKeyEvent.java new file mode 100644 index 0000000..48fcb45 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuKeyEvent.java @@ -0,0 +1,113 @@ +/* MenuKeyEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.awt.Component; +import java.awt.event.KeyEvent; + +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; + +/** + * MenuKeyEvent + * @author Andrew Selkirk + */ +public class MenuKeyEvent extends KeyEvent { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * path + */ + private MenuElement[] path = null; + + /** + * manager + */ + private MenuSelectionManager manager = null; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor MenuKeyEvent + * @param source Source + * @param id KeyEvent ID + * @param when Time + * @param modifiers Modifier keys + * @param keyCode Key code + * @param keyhar Key char + * @param path Path + * @param manager MenuSelectionManager + */ + public MenuKeyEvent(Component source, int id, long when, int modifiers, + int keyCode, char keyChar, MenuElement[] path, + MenuSelectionManager manager) { + super(source, id, when, modifiers, keyCode, keyChar); + this.path = path; + this.manager = manager; + } // MenuKeyEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getPath + * @returns path + */ + public MenuElement[] getPath() { + return path; + } // getPath() + + /** + * getMenuSelectionManager + * @returns MenuSelectionManager + */ + public MenuSelectionManager getMenuSelectionManager() { + return manager; + } // getMenuSelectionManager() + + +} // MenuKeyEvent diff --git a/libjava/classpath/javax/swing/event/MenuKeyListener.java b/libjava/classpath/javax/swing/event/MenuKeyListener.java new file mode 100644 index 0000000..7a1eb89 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuKeyListener.java @@ -0,0 +1,68 @@ +/* MenuKeyListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * MenuKeyListener public interface + * @author Andrew Selkirk + */ +public interface MenuKeyListener extends EventListener { + + /** + * Menu key pressed + * @param event Menu Key Event + */ + void menuKeyPressed(MenuKeyEvent event); + + /** + * Menu key released + * @param event Menu Key Event + */ + void menuKeyReleased(MenuKeyEvent event); + + /** + * Menu key typed + * @param event Menu Key Event + */ + void menuKeyTyped(MenuKeyEvent event); + + +} // MenuKeyListener diff --git a/libjava/classpath/javax/swing/event/MenuListener.java b/libjava/classpath/javax/swing/event/MenuListener.java new file mode 100644 index 0000000..dba704a --- /dev/null +++ b/libjava/classpath/javax/swing/event/MenuListener.java @@ -0,0 +1,68 @@ +/* MenuListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * MenuListener public interface + * @author Andrew Selkirk + */ +public interface MenuListener extends EventListener { + + /** + * Menu canceled + * @param event Menu Event + */ + void menuCanceled(MenuEvent event); + + /** + * Menu deselected + * @param event Menu Event + */ + void menuDeselected(MenuEvent event); + + /** + * Menu selected + * @param event Menu Event + */ + void menuSelected(MenuEvent event); + + +} // MenuListener diff --git a/libjava/classpath/javax/swing/event/MouseInputAdapter.java b/libjava/classpath/javax/swing/event/MouseInputAdapter.java new file mode 100644 index 0000000..2da5543 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MouseInputAdapter.java @@ -0,0 +1,119 @@ +/* MouseInputAdapter.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.awt.event.MouseEvent; + +/** + * MouseInputAdapter + * @author Andrew Selkirk + */ +public abstract class MouseInputAdapter implements MouseInputListener +{ + /** + * Constructor MouseInputAdapter + */ + public MouseInputAdapter() + { + // Do nothing here. + } + + /** + * Mouse clicked + * @param event Mouse event + */ + public void mouseClicked(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse dragged + * @param event Mouse event + */ + public void mouseDragged(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse entered + * @param event Mouse event + */ + public void mouseEntered(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse exited + * @param event Mouse event + */ + public void mouseExited(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse moved + * @param event Mouse event + */ + public void mouseMoved(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse pressed + * @param event Mouse event + */ + public void mousePressed(MouseEvent event) + { + // Do nothing by default. + } + + /** + * Mouse released + * @param event Mouse event + */ + public void mouseReleased(MouseEvent event) + { + // Do nothing by default. + } +} diff --git a/libjava/classpath/javax/swing/event/MouseInputListener.java b/libjava/classpath/javax/swing/event/MouseInputListener.java new file mode 100644 index 0000000..3c3ca23 --- /dev/null +++ b/libjava/classpath/javax/swing/event/MouseInputListener.java @@ -0,0 +1,52 @@ +/* MouseInputListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +/** + * MouseInputListener public interface + * @author Andrew Selkirk + */ +public interface MouseInputListener extends MouseListener, + MouseMotionListener { + +} // MouseInputListener + diff --git a/libjava/classpath/javax/swing/event/PopupMenuEvent.java b/libjava/classpath/javax/swing/event/PopupMenuEvent.java new file mode 100644 index 0000000..0555550 --- /dev/null +++ b/libjava/classpath/javax/swing/event/PopupMenuEvent.java @@ -0,0 +1,58 @@ +/* PopupMenuEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventObject; + +/** + * PopupMenuEvent + * @author Andrew Selkirk + */ +public class PopupMenuEvent extends EventObject { + + /** + * Constructor PopupMenuEvent + * @param source Source + */ + public PopupMenuEvent(Object source) { + super(source); + } // PopupMenuEvent() + + +} // PopupMenuEvent diff --git a/libjava/classpath/javax/swing/event/PopupMenuListener.java b/libjava/classpath/javax/swing/event/PopupMenuListener.java new file mode 100644 index 0000000..dc917d2 --- /dev/null +++ b/libjava/classpath/javax/swing/event/PopupMenuListener.java @@ -0,0 +1,68 @@ +/* PopupMenuListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * PopupMenuListener public interface + * @author Andrew Selkirk + */ +public interface PopupMenuListener extends EventListener { + + /** + * Popup Menu Canceled + * @param event Popup Menu Event + */ + void popupMenuCanceled(PopupMenuEvent event); + + /** + * Popup Menu will become invisible + * @param event Popup Menu Event + */ + void popupMenuWillBecomeInvisible(PopupMenuEvent event); + + /** + * Popup Menu will become visible + * @param event Popup Menu Event + */ + void popupMenuWillBecomeVisible(PopupMenuEvent event); + + +} // PopupMenuListener diff --git a/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java new file mode 100644 index 0000000..ddbb486 --- /dev/null +++ b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java @@ -0,0 +1,255 @@ +/* SwingPropertyChangeSupport.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EventListener; +import java.util.Hashtable; + +/** + * SwingPropertyChangeSupport + * @author Andrew Selkirk +*/ +public final class SwingPropertyChangeSupport + extends PropertyChangeSupport { + + private static final long serialVersionUID = 7162625831330845068L; + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * listeners + */ + private transient EventListenerList listeners; + + /** + * propertyListeners + */ + private Hashtable propertyListeners; + + /** + * source + */ + private Object source; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor SwingPropertyChangeSupport + * @param source TODO + */ + public SwingPropertyChangeSupport(Object source) { + super(source); + this.source = source; + this.listeners = new EventListenerList(); + this.propertyListeners = new Hashtable(); + } // SwingPropertyChangeSupport() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * writeObject + * @param stream TODO + * @exception IOException TODO + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + // TODO + } // writeObject() + + /** + * readObject + * @param stream TODO + * @exception ClassNotFoundException TODO + * @exception IOException TODO + */ + private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException { + // TODO + } // readObject() + + /** + * addPropertyChangeListener + * @param listener TODO + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(PropertyChangeListener.class, listener); + } // addPropertyChangeListener() + + /** + * addPropertyChangeListener + * @param propertyName TODO + * @param listener TODO + */ + public synchronized void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + + // Variables + EventListenerList list; + + // Get Listener list + list = (EventListenerList) propertyListeners.get(propertyName); + if (list == null) { + list = new EventListenerList(); + propertyListeners.put(propertyName, list); + } // if + + // Add Listeners + list.add(PropertyChangeListener.class, listener); + + } // addPropertyChangeListener() + + /** + * removePropertyChangeListener + * @param listener TODO + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(PropertyChangeListener.class, listener); + } // removePropertyChangeListener() + + /** + * removePropertyChangeListener + * @param propertyName TODO + * @param listener TODO + */ + public synchronized void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + + // Variables + EventListenerList list; + + // Get Listener list + list = (EventListenerList) propertyListeners.get(propertyName); + if (list == null) { + return; + } // if + + // Remove Listeners + list.remove(PropertyChangeListener.class, listener); + + // Clean up propertyListeners + if (list.getListenerCount() == 0) { + propertyListeners.remove(propertyName); + } // if + + } // removePropertyChangeListener() + + /** + * firePropertyChange + * @param propertyName TODO + * @param oldValue TODO + * @param newValue TODO + */ + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + + // Variables + PropertyChangeEvent event; + + // Create Property Change Event + event = new PropertyChangeEvent(source, propertyName, oldValue, newValue); + + // Fire Event + firePropertyChange(event); + + } // firePropertyChange() + + /** + * firePropertyChange + * @param event TODO + */ + public void firePropertyChange(PropertyChangeEvent event) { + + // Variables + EventListenerList list; + EventListener[] listenerList; + 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()))) { + return; + } // if + + // Process Main Listener List + listenerList = listeners.getListeners(PropertyChangeListener.class); + for (index = 0; index < listenerList.length; index++) { + listener = (PropertyChangeListener) listenerList[index]; + listener.propertyChange(event); + } // for + + // Process Property Listener List + list = (EventListenerList) propertyListeners.get(event.getPropertyName()); + if (list != null) { + listenerList = list.getListeners(PropertyChangeListener.class); + for (index = 0; index < listenerList.length; index++) { + listener = (PropertyChangeListener) listenerList[index]; + listener.propertyChange(event); + } // for + } // if + + } // firePropertyChange() + + /** + * hasListeners + * @param propertyName TODO + * @returns boolean + */ + public synchronized boolean hasListeners(String propertyName) { + + // Get Listener list + if (propertyListeners.get(propertyName) == null) { + return false; + } // if + + return true; + + } // hasListeners() + + +} // SwingPropertyChangeSupport diff --git a/libjava/classpath/javax/swing/event/TableColumnModelEvent.java b/libjava/classpath/javax/swing/event/TableColumnModelEvent.java new file mode 100644 index 0000000..2ca4148 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TableColumnModelEvent.java @@ -0,0 +1,105 @@ +/* TableColumnModelEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.table.TableColumnModel; + +/** + * TableColumnModelEvent + * @author Andrew Selkirk + */ +public class TableColumnModelEvent extends EventObject { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * fromIndex + */ + protected int fromIndex = 0; + + /** + * toIndex + */ + protected int toIndex = 0; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor TableColumnModelEvent + * @param source Source TableColumnModel + * @param from From index + * @param to To index + */ + public TableColumnModelEvent(TableColumnModel source, + int from, int to) { + super(source); + fromIndex = from; + toIndex = to; + } // TableColumnModelEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getFromIndex. + * @returns From index + */ + public int getFromIndex() { + return fromIndex; + } // getFromIndex() + + /** + * getToIndex. + * @returns To index + */ + public int getToIndex() { + return toIndex; + } // getToIndex() + + +} // TableColumnModelEvent diff --git a/libjava/classpath/javax/swing/event/TableColumnModelListener.java b/libjava/classpath/javax/swing/event/TableColumnModelListener.java new file mode 100644 index 0000000..90e1b29 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TableColumnModelListener.java @@ -0,0 +1,80 @@ +/* TableColumnModelListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * TableColumnModelListener public interface + * @author Andrew Selkirk + */ +public interface TableColumnModelListener extends EventListener { + + /** + * Column added + * @param event Table Column Model Event + */ + void columnAdded(TableColumnModelEvent event); + + /** + * Column margin changed + * @param event Change Event + */ + void columnMarginChanged(ChangeEvent event); + + /** + * Column moved + * @param event Table Column Model Event + */ + void columnMoved(TableColumnModelEvent event); + + /** + * Column removed + * @param event Table Column Model Event + */ + void columnRemoved(TableColumnModelEvent event); + + /** + * Column selection changed + * @param event List Selection Event + */ + void columnSelectionChanged(ListSelectionEvent event); + + +} // TableColumnModelListener diff --git a/libjava/classpath/javax/swing/event/TableModelEvent.java b/libjava/classpath/javax/swing/event/TableModelEvent.java new file mode 100644 index 0000000..e15174c --- /dev/null +++ b/libjava/classpath/javax/swing/event/TableModelEvent.java @@ -0,0 +1,220 @@ +/* TableModelEvent.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.table.TableModel; + +/** + * An event that describes changes to a {@link TableModel}. + * + * @see javax.swing.event.TableModelListener + * + * @author Andrew Selkirk + */ +public class TableModelEvent extends EventObject +{ + private static final long serialVersionUID = -7849342674552212824L; + + /** A column index representing all columns. */ + public static final int ALL_COLUMNS = -1; + + /** + * An event type indicating that one or more rows have been deleted from the + * model. + */ + public static final int DELETE = -1; + + /** A row index representing the header row. */ + public static final int HEADER_ROW = -1; + + /** + * An event type indicating that one or more rows have been inserted into the + * model. + */ + public static final int INSERT = 1; + + /** An event type indicating that data has been updated in the model. */ + public static final int UPDATE = 0; + + /** The column in the table model that the event relates to. */ + protected int column = 0; + + /** The first row in the table model that the event relates to. */ + protected int firstRow = 0; + + /** The last row in the table model that the event relates to. */ + protected int lastRow = 0; + + /** + * The event type (one of {@link #UPDATE}, {@link #INSERT}, {@link #DELETE}). + */ + protected int type = 0; + + /** + * Creates a new TableModelEvent indicating an {@link #UPDATE} + * to the data in all columns and rows. + * + * @param source the source object (null not permitted). + * + * @throws IllegalArgumentException if source is + * null. + */ + public TableModelEvent(TableModel source) + { + this(source, 0, Integer.MAX_VALUE, ALL_COLUMNS, UPDATE); + } + + /** + * Creates a new TableModelEvent indicating an {@link #UPDATE} + * to the data in a single row across all columns. + * + * @param source the source object (null not permitted). + * @param row the updated row. + * + * @throws IllegalArgumentException if source is + * null. + */ + public TableModelEvent(TableModel source, int row) + { + this(source, row, row, ALL_COLUMNS, UPDATE); + } + + /** + * Creates a new TableModelEvent indicating an {@link #UPDATE} + * to the data in the specified rows across all columns. + * + * @param source the source object (null not permitted). + * @param firstRow the first row of update. + * @param lastRow the last row of update. + * + * @throws IllegalArgumentException if source is + * null. + */ + public TableModelEvent(TableModel source, int firstRow, int lastRow) + { + this(source, firstRow, lastRow, ALL_COLUMNS, UPDATE); + } + + /** + * Creates a new TableModelEvent indicating an {@link #UPDATE} + * to the data in the specified rows and column. Use {@link #ALL_COLUMNS} + * for the column argument to indicate all columns. + * + * @param source the source object (null not permitted). + * @param firstRow the first row of update. + * @param lastRow the last row of update. + * @param column the affected column. + * + * @throws IllegalArgumentException if source is + * null. + */ + public TableModelEvent(TableModel source, int firstRow, int lastRow, + int column) + { + this(source, firstRow, lastRow, column, UPDATE); + } + + /** + * Creates a new TableModelEvent indicating an operation of + * the specified type on the data in the specified rows and + * column. The event type is usually one of {@link #UPDATE}, {@link #INSERT}, + * and {@link #DELETE}. + * + * @param source the source object (null not permitted). + * @param firstRow the first row of update. + * @param lastRow the last row of update. + * @param column the affected column. + * @param type the type of change. + * + * @throws IllegalArgumentException if source is + * null. + */ + public TableModelEvent(TableModel source, int firstRow, int lastRow, + int column, int type) + { + super(source); + this.firstRow = firstRow; + this.lastRow = lastRow; + this.column = column; + this.type = type; + } + + /** + * Returns the affected column of this event. + * + * @return The column index. + */ + public int getColumn() + { + return column; + } + + /** + * Returns the first affected row of this event. + * + * @return The row index. + */ + public int getFirstRow() + { + return firstRow; + } + + /** + * Returns the last affected row of this event. + * + * @return The row index. + */ + public int getLastRow() + { + return lastRow; + } + + /** + * Returns the type of change indicated by this event (usually one of + * {@link #UPDATE}, {@link #INSERT}, {@link #DELETE}). + * + * @return The type. + */ + public int getType() + { + return type; + } +} diff --git a/libjava/classpath/javax/swing/event/TableModelListener.java b/libjava/classpath/javax/swing/event/TableModelListener.java new file mode 100644 index 0000000..c8d6e8f8 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TableModelListener.java @@ -0,0 +1,55 @@ +/* TableModelListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import java.util.EventListener; + +/** + * TableModelListener public interface + * @author Andrew Selkirk + */ +public interface TableModelListener extends EventListener { + + /** + * Table changed + * @param event Table Model Event + */ + void tableChanged(TableModelEvent event); + + +} // TableModelListener diff --git a/libjava/classpath/javax/swing/event/TreeExpansionEvent.java b/libjava/classpath/javax/swing/event/TreeExpansionEvent.java new file mode 100644 index 0000000..c4b3313 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeExpansionEvent.java @@ -0,0 +1,89 @@ +/* TreeExpansionEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.tree.TreePath; + +/** + * TreeExpansionEvent + * @author Andrew Selkirk + */ +public class TreeExpansionEvent extends EventObject { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * path + */ + protected TreePath path = null; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor TreeExpansionEvent + * @param source Source object + * @param path Path + */ + public TreeExpansionEvent(Object source, TreePath path) { + super(source); + this.path = path; + } // TreeExpansionEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getPath + * @returns Tree path + */ + public TreePath getPath() { + return path; + } // getPath() + + +} // TreeExpansionEvent diff --git a/libjava/classpath/javax/swing/event/TreeExpansionListener.java b/libjava/classpath/javax/swing/event/TreeExpansionListener.java new file mode 100644 index 0000000..08507a0 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeExpansionListener.java @@ -0,0 +1,62 @@ +/* TreeExpansionListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * TreeExpansionListener public interface + * @author Andrew Selkirk + */ +public interface TreeExpansionListener extends EventListener { + + /** + * Tree collapsed + * @param event Tree Expansion Event + */ + void treeCollapsed(TreeExpansionEvent event); + + /** + * Tree expanded + * @param event Tree Expansion Event + */ + void treeExpanded(TreeExpansionEvent event); + + +} // TreeExpansionListener diff --git a/libjava/classpath/javax/swing/event/TreeModelEvent.java b/libjava/classpath/javax/swing/event/TreeModelEvent.java new file mode 100644 index 0000000..a217e3b --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeModelEvent.java @@ -0,0 +1,171 @@ +/* TreeModelEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.tree.TreePath; + +/** + * TreeModelEvent + * @author Andrew Selkirk + */ +public class TreeModelEvent extends EventObject { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * childIndices + */ + protected int[] childIndices = new int[0]; + + /** + * children + */ + protected Object[] children = new Object[0]; + + /** + * path + */ + protected TreePath path = null; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path + */ + public TreeModelEvent(Object source, Object[] path) { + super(source); + this.path = new TreePath(path); + } // TreeModelEvent() + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path path + * @param childIndices Child indices + * @param children Children + */ + public TreeModelEvent(Object source, Object[] path, + int[] childIndices, Object[] children) { + super(source); + this.path = new TreePath(path); + this.childIndices = childIndices; + this.children = children; + } // TreeModelEvent() + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path Path + */ + public TreeModelEvent(Object source, TreePath path) { + super(source); + this.path = path; + } // TreeModelEvent() + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path Path + * @param childIndices Child indices + * @param children Children + */ + public TreeModelEvent(Object source, TreePath path, + int[] childIndices, Object[] children) { + super(source); + this.path = path; + this.childIndices = childIndices; + this.children = children; + } // TreeModelEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getChildIndices + * @returns child indices + */ + public int[] getChildIndices() { + return childIndices; + } // getChildIndices() + + /** + * getChildren + * @returns children + */ + public Object[] getChildren() { + return children; + } // getChildren() + + /** + * getPath + * @returns path + */ + public Object[] getPath() { + return path.getPath(); + } // getPath() + + /** + * getTreePath + * @returns TreePath + */ + public TreePath getTreePath() { + return path; + } // getTreePath() + + /** + * String representation + * @returns String representation + */ + public String toString() { + return null; // TODO + } // toString() + + +} // TreeModelEvent diff --git a/libjava/classpath/javax/swing/event/TreeModelListener.java b/libjava/classpath/javax/swing/event/TreeModelListener.java new file mode 100644 index 0000000..57b5c51 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeModelListener.java @@ -0,0 +1,74 @@ +/* TreeModelListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * TreeModelListener public interface + * @author Andrew Selkirk + */ +public interface TreeModelListener extends EventListener { + + /** + * Tree nodes changed + * @param event Tree Model Event + */ + void treeNodesChanged(TreeModelEvent event); + + /** + * Tree nodes inserted + * @param event Tree Model Event + */ + void treeNodesInserted(TreeModelEvent event); + + /** + * Tree nodes removed + * @param event Tree Model Event + */ + void treeNodesRemoved(TreeModelEvent event); + + /** + * Tree structured changed + * @param event Tree Model Event + */ + void treeStructureChanged(TreeModelEvent event); + + +} // TreeModelListener diff --git a/libjava/classpath/javax/swing/event/TreeSelectionEvent.java b/libjava/classpath/javax/swing/event/TreeSelectionEvent.java new file mode 100644 index 0000000..df4e0ff --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeSelectionEvent.java @@ -0,0 +1,199 @@ +/* TreeSelectionEvent.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.tree.TreePath; + +/** + * TreeSelectionEvent + * @author Andrew Selkirk + * @version 1.0 + */ +public class TreeSelectionEvent extends EventObject { + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * paths + */ + protected TreePath[] paths; + + /** + * areNew + */ + protected boolean[] areNew; + + /** + * oldLeadSelectionPath + */ + protected TreePath oldLeadSelectionPath; + + /** + * newLeadSelectionPath + */ + protected TreePath newLeadSelectionPath; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor TreeSelectionEvent + * @param source TODO + * @param paths TODO + * @param areNew TODO + * @param oldLeadSelectionPath TODO + * @param newLeadSelectionPath TODO + */ + public TreeSelectionEvent(Object source, TreePath[] paths, + boolean[] areNew, TreePath oldLeadSelectionPath, + TreePath newLeadSelectionPath) + { + super(source); + this.paths = paths; + this.areNew = areNew; + this.oldLeadSelectionPath = oldLeadSelectionPath; + this.newLeadSelectionPath = newLeadSelectionPath; + } // TreeSelectionEvent() + + /** + * Constructor TreeSelectionEvent + * @param source TODO + * @param paths TODO + * @param areNew TODO + * @param oldLeadSelectionPath TODO + * @param newLeadSelectionPath TODO + */ + public TreeSelectionEvent(Object source, TreePath path, + boolean isNew, TreePath oldLeadSelectionPath, + TreePath newLeadSelectionPath) + { + super(source); + this.paths = new TreePath[]{path}; + this.areNew = new boolean[]{isNew}; + this.oldLeadSelectionPath = oldLeadSelectionPath; + this.newLeadSelectionPath = newLeadSelectionPath; + } // TreeSelectionEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * @returns the first path element + */ + public TreePath getPath() + { + return paths[0]; + } // getPath() + + /** + * + * @returns the paths with selection changed + */ + public TreePath[] getPaths() + { + return (TreePath[]) paths.clone(); + } // getPaths() + + /** + * @return true if the first path is added to the selection, false otherwise + */ + public boolean isAddedPath() + { + return areNew[0]; + } // isAddedPath() + + /** + * @param path the path to check + * @return true if the path is added to the selection, false otherwise + */ + public boolean isAddedPath(TreePath path) + { + for (int i = paths.length - 1; i >= 0; i--) + if (paths[i].equals(path)) + return areNew[i]; + + return false; + } // isAddedPath() + + /** + * @param index the index'th path + * @return true if the path is added to the selection, false otherwise + */ + public boolean isAddedPath(int index) + { + return areNew[index]; + } // isAddedPath() + + /** + * @return the previous lead selection path + */ + public TreePath getOldLeadSelectionPath() + { + return oldLeadSelectionPath; + } // getOldLeadSelectionPath() + + /** + * @returns the current lead selection path + */ + public TreePath getNewLeadSelectionPath() + { + return newLeadSelectionPath; + } // getNewLeadSelectionPath() + + /** + * @param source the new event source + * @return a cloned event with another event source + */ + public Object cloneWithSource(Object source) + { + return new TreeSelectionEvent (source, paths, areNew, + oldLeadSelectionPath, + newLeadSelectionPath); + } // cloneWithSource() + + +} // TreeSelectionEvent diff --git a/libjava/classpath/javax/swing/event/TreeSelectionListener.java b/libjava/classpath/javax/swing/event/TreeSelectionListener.java new file mode 100644 index 0000000..b844a6e --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeSelectionListener.java @@ -0,0 +1,56 @@ +/* TreeSelectionListener.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +// Imports +import java.util.EventListener; + +/** + * TreeSelectionListener public interface + * @author Andrew Selkirk + */ +public interface TreeSelectionListener extends EventListener { + + /** + * Value changed + * @param event Tree Selection Event + */ + void valueChanged(TreeSelectionEvent event); + + +} // TreeSelectionListener diff --git a/libjava/classpath/javax/swing/event/TreeWillExpandListener.java b/libjava/classpath/javax/swing/event/TreeWillExpandListener.java new file mode 100644 index 0000000..89d3764 --- /dev/null +++ b/libjava/classpath/javax/swing/event/TreeWillExpandListener.java @@ -0,0 +1,65 @@ +/* TreeWillExpandListener.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventListener; + +import javax.swing.tree.ExpandVetoException; + +/** + * @author Andrew Selkirk + */ +public interface TreeWillExpandListener extends EventListener +{ + /** + * Invoked whenever a node in the tree is about to be collapsed. + * + * @param event The tree expansion Event + */ + void treeWillCollapse(TreeExpansionEvent event) + throws ExpandVetoException; + + /** + * Invoked whenever a node in the tree is about to be expanded. + * + * @param event The tree expansion Event + */ + void treeWillExpand(TreeExpansionEvent event) + throws ExpandVetoException; +} diff --git a/libjava/classpath/javax/swing/event/UndoableEditEvent.java b/libjava/classpath/javax/swing/event/UndoableEditEvent.java new file mode 100644 index 0000000..147c2e5 --- /dev/null +++ b/libjava/classpath/javax/swing/event/UndoableEditEvent.java @@ -0,0 +1,92 @@ +/* UndoableEditEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.event; + +import java.util.EventObject; + +import javax.swing.undo.UndoableEdit; + +/** + * UndoableEditEvent + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public class UndoableEditEvent extends EventObject { + + private static final long serialVersionUID = 4418044561759134484L; + + //------------------------------------------------------------- + // Variables -------------------------------------------------- + //------------------------------------------------------------- + + /** + * edit + */ + private UndoableEdit edit; + + + //------------------------------------------------------------- + // Initialization --------------------------------------------- + //------------------------------------------------------------- + + /** + * Constructor UndoableEditEvent + * @param source TODO + * @param edit TODO + */ + public UndoableEditEvent(Object source, UndoableEdit edit) { + super(source); + this.edit = edit; + } // UndoableEditEvent() + + + //------------------------------------------------------------- + // Methods ---------------------------------------------------- + //------------------------------------------------------------- + + /** + * getEdit + * @returns UndoableEdit + */ + public UndoableEdit getEdit() { + return edit; + } // getEdit() + + +} // UndoableEditEvent diff --git a/libjava/classpath/javax/swing/event/UndoableEditListener.java b/libjava/classpath/javax/swing/event/UndoableEditListener.java new file mode 100644 index 0000000..13eecf5 --- /dev/null +++ b/libjava/classpath/javax/swing/event/UndoableEditListener.java @@ -0,0 +1,56 @@ +/* UndoableEditListener.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.event; + +import java.util.EventListener; + + +/** + * UndoableEditListener public interface + * @author Andrew Selkirk + * @author Ronald Veldema + */ +public interface UndoableEditListener extends EventListener +{ + /** + * Undoable edit has happened + * + * @param event Undoable Edit Event + */ + void undoableEditHappened(UndoableEditEvent event); +} diff --git a/libjava/classpath/javax/swing/event/package.html b/libjava/classpath/javax/swing/event/package.html new file mode 100644 index 0000000..faef7e1 --- /dev/null +++ b/libjava/classpath/javax/swing/event/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.event + + +

Provides events and listeners used by components in the +javax.swing package.

+ + + diff --git a/libjava/classpath/javax/swing/filechooser/FileFilter.java b/libjava/classpath/javax/swing/filechooser/FileFilter.java new file mode 100644 index 0000000..42770d9 --- /dev/null +++ b/libjava/classpath/javax/swing/filechooser/FileFilter.java @@ -0,0 +1,80 @@ +/* FileFilter.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.filechooser; + +import java.io.File; + +/** + * 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 diff --git a/libjava/classpath/javax/swing/filechooser/FileSystemView.java b/libjava/classpath/javax/swing/filechooser/FileSystemView.java new file mode 100644 index 0000000..ffa41ca --- /dev/null +++ b/libjava/classpath/javax/swing/filechooser/FileSystemView.java @@ -0,0 +1,361 @@ +/* FileSystemView.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.filechooser; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import javax.swing.Icon; + + +/** + * DOCUMENT ME! + */ +public abstract class FileSystemView +{ + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * @param filename DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File createFileObject(File dir, String filename) + { + return new File(dir, filename); + } + + /** + * DOCUMENT ME! + * + * @param path DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File createFileObject(String path) + { + return new File(path); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected File createFileSystemRoot(File f) + { + File[] roots = File.listRoots(); + if (roots == null) + return null; + return roots[0]; + } + + /** + * DOCUMENT ME! + * + * @param containingDir DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ + public abstract File createNewFolder(File containingDir) + throws IOException; + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * @param fileName DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getChild(File parent, String fileName) + { + // FIXME: Handle the case when parent and child are special folders. + return new File(parent, fileName); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getDefaultDirectory() + { + return getHomeDirectory(); + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * @param useFileHiding DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File[] getFiles(File dir, boolean useFileHiding) + { + if (dir == null || dir.listFiles() == null) + return null; + File[] files = dir.listFiles(); + if (! useFileHiding) + return files; + ArrayList trim = new ArrayList(); + for (int i = 0; i < files.length; i++) + if (! files[i].isHidden()) + trim.add(files[i]); + File[] value = (File[]) trim.toArray(new File[0]); + return value; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + 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; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getHomeDirectory() + { + return createFileObject(System.getProperty("user.home")); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File getParentDirectory(File f) + { + if (f == null) + return null; + return f.getParentFile(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File[] getRoots() + { + // subclass + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getSystemDisplayName(File f) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getSystemIcon(File f) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getSystemTypeDescription(File f) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isComputerNode(File dir) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isDrive(File dir) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isFileSystem(File f) + { + return (f.isFile() || f.isDirectory()); + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isFileSystemRoot(File dir) + { + File[] roots = File.listRoots(); + if (roots == null || dir == null) + return false; + String filename = dir.getAbsolutePath(); + for (int i = 0; i < roots.length; i++) + if (roots[i].getAbsolutePath().equals(filename)) + return true; + return false; + } + + /** + * DOCUMENT ME! + * + * @param dir DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isFloppyDrive(File dir) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isHiddenFile(File f) + { + return f.isHidden(); + } + + /** + * DOCUMENT ME! + * + * @param folder DOCUMENT ME! + * @param file DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isParent(File folder, File file) + { + File parent = file.getParentFile(); + if (parent == null) + return false; + return folder.equals(parent); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isRoot(File f) + { + // These are not file system roots. + return false; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Boolean isTraversable(File f) + { + // Tested. A directory where the user has no permission to rwx is still + // 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()); + } +} diff --git a/libjava/classpath/javax/swing/filechooser/FileView.java b/libjava/classpath/javax/swing/filechooser/FileView.java new file mode 100644 index 0000000..c431fd4 --- /dev/null +++ b/libjava/classpath/javax/swing/filechooser/FileView.java @@ -0,0 +1,114 @@ +/* FileView.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.filechooser; + +import java.io.File; + +import javax.swing.Icon; + +/** + * FileView + * @author Andrew Selkirk + * @version 1.0 + */ +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 diff --git a/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java b/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java new file mode 100644 index 0000000..f2360ec --- /dev/null +++ b/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java @@ -0,0 +1,144 @@ +/* UnixFileSystemView.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.filechooser; + +import java.io.File; +import java.io.IOException; +import javax.swing.Icon; + + +/** + * DOCUMENT ME! + */ +class UnixFileSystemView extends FileSystemView +{ + /** DOCUMENT ME! */ + private static final String NEW_FOLDER_NAME = "NewFolder"; + + /** + * DOCUMENT ME! + * + * @param containingDir DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ + public File createNewFolder(File containingDir) throws IOException + { + int count = 0; + File f = null; + String filename = containingDir.getAbsolutePath() + File.separator + + NEW_FOLDER_NAME; + while (f == null) + { + String full = filename; + if (count > 0) + full += "." + (count++); + f = new File(full); + if (f.isDirectory() || f.isFile()) + { + count++; + f = null; + } + } + f.mkdir(); + return f; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public File[] getRoots() + { + return File.listRoots(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getSystemDisplayName(File f) + { + // FIXME: Implement; + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getSystemIcon(File f) + { + // FIXME: Implement; + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getSystemTypeDescription(File f) + { + // FIXME: Implement. + return null; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isRoot(File f) + { + return isFileSystemRoot(f); + } +} diff --git a/libjava/classpath/javax/swing/filechooser/package.html b/libjava/classpath/javax/swing/filechooser/package.html new file mode 100644 index 0000000..bf897ab --- /dev/null +++ b/libjava/classpath/javax/swing/filechooser/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.filechooser + + +

Provides support classes for the {@link javax.swing.JFileChooser} +component.

+ + + diff --git a/libjava/classpath/javax/swing/package.html b/libjava/classpath/javax/swing/package.html new file mode 100644 index 0000000..30ceb88 --- /dev/null +++ b/libjava/classpath/javax/swing/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing + + +

Provides a collection of cross-platform user interface +components.

+ + + diff --git a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java new file mode 100644 index 0000000..f6af088 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java @@ -0,0 +1,64 @@ +/* ActionMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.ActionMap; + + +/** + * An ActionMap that implements the {@link UIResource} + * interface to indicate that it belongs to a pluggable + * LookAndFeel. + * + * @see javax.swing.ActionMap + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ActionMapUIResource + extends ActionMap + implements UIResource +{ + /** + * Constructs a new ActionMapUIResource. + */ + public ActionMapUIResource() + { + /* The constructor does nothing. */ + } +} diff --git a/libjava/classpath/javax/swing/plaf/BorderUIResource.java b/libjava/classpath/javax/swing/plaf/BorderUIResource.java new file mode 100644 index 0000000..1bf8540 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/BorderUIResource.java @@ -0,0 +1,933 @@ +/* BorderUIResource.java + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.io.Serializable; + +import javax.swing.Icon; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.MatteBorder; +import javax.swing.border.TitledBorder; + +/** + * A wrapper for {@link javax.swing.border.Border} that also + * implements the {@link UIResource} marker interface. This is useful + * for implementing pluggable look-and-feels: When switching the + * current LookAndFeel, only those borders are replaced that are + * marked as {@link UIResource}. For this reason, a look-and-feel + * should always install borders that implement + * UIResource, such as the borders provided by this + * class. + * + * @serial + * @serialField delegate Border the Border wrapped + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BorderUIResource + extends Object + implements Border, UIResource, Serializable +{ + /** + * Verified using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3440553684010079691L; + + + /** + * A shared instance of an {@link EtchedBorderUIResource}, or + * null if the {@link #getEtchedBorderUIResource()} + * method has not yet been called. + */ + private static Border etchedBorderUIResource; + + + /** + * A shared instance of a {@link BevelBorderUIResource} whose + * bevelType is {@link + * javax.swing.border.BevelBorder#LOWERED}, or null if + * the {@link #getLoweredBevelBorderUIResource()} has not yet been + * called. + */ + private static Border loweredBevelBorderUIResource; + + + /** + * A shared instance of a {@link BevelBorderUIResource} whose + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}, or null if + * the {@link #getRaisedBevelBorderUIResource()} has not yet been + * called. + */ + private static Border raisedBevelBorderUIResource; + + + /** + * A shared instance of a {@link LineBorderUIResource} for + * a one-pixel thick black line, or null if + * the {@link #getBlackLineBorderUIResource()} has not yet been + * called. + */ + private static Border blackLineBorderUIResource; + + + /** + * Returns a shared instance of an etched border which also + * is marked as an {@link UIResource}. + * + * @see javax.swing.border.EtchedBorder + */ + public static Border getEtchedBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (etchedBorderUIResource == null) + etchedBorderUIResource = new EtchedBorderUIResource(); + return etchedBorderUIResource; + } + + + /** + * Returns a shared instance of {@link BevelBorderUIResource} whose + * bevelType is {@link + * javax.swing.border.BevelBorder#LOWERED}. + * + * @see javax.swing.border.BevelBorder + */ + public static Border getLoweredBevelBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (loweredBevelBorderUIResource == null) + loweredBevelBorderUIResource = new BevelBorderUIResource( + BevelBorder.LOWERED); + return loweredBevelBorderUIResource; + } + + + /** + * Returns a shared instance of {@link BevelBorderUIResource} whose + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}. + * + * @see javax.swing.border.BevelBorder + */ + public static Border getRaisedBevelBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (raisedBevelBorderUIResource == null) + raisedBevelBorderUIResource = new BevelBorderUIResource( + BevelBorder.RAISED); + return raisedBevelBorderUIResource; + } + + + /** + * Returns a shared instance of {@link LineBorderUIResource} for + * a black, one-pixel width border. + * + * @see javax.swing.border.LineBorder + */ + public static Border getBlackLineBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (blackLineBorderUIResource == null) + blackLineBorderUIResource = new LineBorderUIResource(Color.black); + return blackLineBorderUIResource; + } + + + /** + * The wrapped border. + */ + private Border delegate; + + + /** + * Constructs a BorderUIResource for wrapping + * a Border object. + * + * @param delegate the border to be wrapped. + */ + public BorderUIResource(Border delegate) + { + if (delegate == null) + throw new IllegalArgumentException(); + + this.delegate = delegate; + } + + + /** + * Paints the border around an enclosed component by calling + * the paintBorder method of the wrapped delegate. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + delegate.paintBorder(c, g, x, y, width, height); + } + + + /** + * Measures the width of this border by calling the + * getBorderInsets method of the wrapped + * delegate. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return delegate.getBorderInsets(c); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting by calling the isBorderOpaque + * method of the wrapped delegate. + * + * @return true if the border is fully opaque, or + * false if some pixels of the background + * can shine through the border. + */ + public boolean isBorderOpaque() + { + return delegate.isBorderOpaque(); + } + + + /** + * A {@link javax.swing.border.BevelBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class BevelBorderUIResource + extends BevelBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -1275542891108351642L; + + /** + * Constructs a BevelBorderUIResource whose colors will be derived + * from the background of the enclosed component. The background + * color is retrieved each time the border is painted, so a border + * constructed by this method will automatically reflect a change + * to the component’s background color. + * + *

[An illustration showing raised and lowered BevelBorders]

+ * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + */ + public BevelBorderUIResource(int bevelType) + { + super(bevelType); + } + + + /** + * Constructs a BevelBorderUIResource given its appearance type + * and two colors for its highlight and shadow. + * + *

[An illustration showing BevelBorders that were
+     * constructed with this method]

+ * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @param highlight the color that will be used for the inner side + * of the highlighted edges (top and left if if + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}; bottom and right + * otherwise). The color for the outer side is a brightened + * version of this color. + * + * @param shadow the color that will be used for the outer side of + * the shadowed edges (bottom and right if + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}; top and left + * otherwise). The color for the inner side is a brightened + * version of this color. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + * + * @throws NullPointerException if highlight or + * shadow is null. + */ + public BevelBorderUIResource(int bevelType, + Color highlight, + Color shadow) + { + super(bevelType, highlight, shadow); + } + + + /** + * Constructs a BevelBorderUIResource given its appearance type + * and all its colors. + * + *

[An illustration showing BevelBorders that
+     * were constructed with this method]

+ * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @param highlightOuter the color that will be used for the outer + * side of the highlighted edges (top and left if + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}; bottom and right + * otherwise). + * + * @param highlightInner the color that will be used for the inner + * side of the highlighted edges. + * + * @param shadowOuter the color that will be used for the outer + * side of the shadowed edges (bottom and right if + * bevelType is {@link + * javax.swing.border.BevelBorder#RAISED}; top and left + * otherwise). + * + * @param shadowInner the color that will be used for the inner + * side of the shadowed edges. + * + * @throws IllegalArgumentException if bevelType has + * an unsupported value. + * + * @throws NullPointerException if one of the passed colors + * is null. + */ + public BevelBorderUIResource(int bevelType, + Color highlightOuter, + Color highlightInner, + Color shadowOuter, + Color shadowInner) + { + super(bevelType, + highlightOuter, highlightInner, + shadowOuter, shadowInner); + } + } + + + /** + * A {@link javax.swing.border.CompoundBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class CompoundBorderUIResource + extends CompoundBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = 7550017084975167341L; + + /** + * Constructs a CompoundBorderUIResource with the specified inside + * and outside borders. + * + * @param outsideBorder the outside border, which is painted to the + * outside of both insideBorder and the enclosed + * component. It is acceptable to pass null, in + * which case no outside border is painted. + * + * @param insideBorder the inside border, which is painted to + * between outsideBorder and the enclosed + * component. It is acceptable to pass null, in + * which case no inside border is painted. + */ + public CompoundBorderUIResource(Border outsideBorder, + Border insideBorder) + { + super(outsideBorder, insideBorder); + } + } + + + /** + * An {@link javax.swing.border.EmptyBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + *

[An illustration of EmptyBorder]

+ * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class EmptyBorderUIResource + extends EmptyBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -4914187529340071708L; + + /** + * Constructs an empty border given the number of pixels required + * on each side. + * + * @param top the number of pixels that the border will need + * for its top edge. + * + * @param left the number of pixels that the border will need + * for its left edge. + * + * @param bottom the number of pixels that the border will need + * for its bottom edge. + * + * @param right the number of pixels that the border will need + * for its right edge. + */ + public EmptyBorderUIResource(int top, int left, int bottom, int right) + { + super(top, left, bottom, right); + } + + + /** + * Constructs an empty border given the number of pixels required + * on each side, passed in an Insets object. + * + * @param insets the Insets for the new border. + */ + public EmptyBorderUIResource(Insets insets) + { + super(insets); + } + } + + + /** + * An {@link javax.swing.border.EtchedBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + *

[An illustration of the two EtchedBorder
+   * variants]

+ * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class EtchedBorderUIResource + extends EtchedBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -8186391754165296656L; + + /** + * Constructs an EtchedBorderUIResource that appears lowered into + * the surface. The colors will be derived from the background + * color of the enclosed Component when the border gets painted. + */ + public EtchedBorderUIResource() + { + super(); + } + + + /** + * Constructs an EtchedBorderUIResource with the specified + * appearance. The colors will be derived from the background + * color of the enclosed Component when the border gets painted. + * + *

[An illustration of the two
+     * EtchedBorder variants]

+ * + * @param etchType the desired appearance of the border. The value + * must be either {@link javax.swing.border.EtchedBorder#RAISED} + * or {@link javax.swing.border.EtchedBorder#LOWERED}. + * + * @throws IllegalArgumentException if etchType has + * an unsupported value. + */ + public EtchedBorderUIResource(int etchType) + { + super(etchType); + } + + + /** + * Constructs a lowered EtchedBorderUIResource, explicitly + * selecting the colors that will be used for highlight and + * shadow. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @see #EtchedBorderUIResource(int, Color, Color) + */ + public EtchedBorderUIResource(Color highlight, Color shadow) + { + super(highlight, shadow); + } + + + /** + * Constructs an EtchedBorderUIResource with the specified + * appearance, explicitly selecting the colors that will be used + * for highlight and shadow. + * + *

[An illustration that shows which pixels get
+     * painted in what color]

+ * + * @param etchType the desired appearance of the border. The value + * must be either {@link javax.swing.border.EtchedBorder#RAISED} + * or {@link javax.swing.border.EtchedBorder#LOWERED}. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @throws IllegalArgumentException if etchType has + * an unsupported value. + */ + public EtchedBorderUIResource(int etchType, + Color highlight, Color shadow) + { + super(etchType, highlight, shadow); + } + } + + + /** + * A {@link javax.swing.border.LineBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + *

[An illustration of two LineBorders]

+ * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class LineBorderUIResource + extends LineBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -6171232338180172310L; + + /** + * Constructs a LineBorderUIResource given its color. The border + * will be one pixel thick and have plain corners. + * + * @param color the color for drawing the border. + */ + public LineBorderUIResource(Color color) + { + super(color); + } + + + /** + * Constructs a LineBorder given its color and thickness. The + * border will have plain corners. + * + * @param color the color for drawing the border. + * @param thickness the width of the line in pixels. + */ + public LineBorderUIResource(Color color, int thickness) + { + super(color, thickness); + } + + + /* Note: Since JDK1.3, javax.swing.border.LineBorder also has a + * constructor which accepts a value for the roundedCorners + * property. However, as of JDK1.4.1, the LineBorderUIResource + * subclass does not have a corresponding constructor. + * + * A request for enhancing the Swing API has been filed with Sun: + * http://developer.java.sun.com/developer/bugParade/bugs/4879999.html + */ + } + + + /** + * A {@link javax.swing.border.MatteBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + *

[An illustration of two MatteBorders]

+ * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MatteBorderUIResource + extends MatteBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -8107923147541851122L; + + /** + * Constructs a MatteBorderUIResource given the width on each side + * and a fill color. + * + *

[A picture of a MatteBorder made by this
+     * constructor]

+ * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param matteColor the color for filling the border. + */ + public MatteBorderUIResource(int top, int left, + int bottom, int right, + Color color) + { + super(top, left, bottom, right, color); + } + + + /** + * Constructs a MatteBorderUIResource given the width on each side + * and an icon for tiling the border area. + * + *

[A picture of a MatteBorder made by this
+     * constructor]

+ * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorderUIResource(int top, int left, + int bottom, int right, + Icon tileIcon) + { + super(top, left, bottom, right, tileIcon); + } + + + /** + * Constructs a MatteBorderUIResource given an icon for tiling the + * border area. The icon width is used for the border insets at + * the left and right edge, the icon height for the top and bottom + * edge. + * + *

[A picture of a MatteBorder made by this
+     * constructor]

+ * + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorderUIResource(Icon tileIcon) + { + super(tileIcon); + } + } + + + /** + * A {@link javax.swing.border.TitledBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement UIResource, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class TitledBorderUIResource + extends TitledBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = 7667113547406407427L; + + /** + * Constructs a TitledBorderUIResource given the text of its title. + * + * @param title the title text, or null to use no + * title text. + */ + public TitledBorderUIResource(String title) + { + super(title); + } + + + /** + * Constructs an initially untitled TitledBorderUIResource + * given another border. + * + * @param border the border underneath the title, or + * null to use a default from + * the current look and feel. + */ + public TitledBorderUIResource(Border border) + { + super(border); + } + + + /** + * Constructs a TitledBorder given its border and title text. + * + * @param border the border underneath the title, or + * null to use a default from + * the current look and feel. + * + * @param title the title text, or null + * to use no title text. + */ + public TitledBorderUIResource(Border border, String title) + { + super(border, title); + } + + + /** + * Constructs a TitledBorderUIResource given its border, title + * text, horizontal alignment, and vertical position. + * + * @param border the border underneath the title, or + * null to use a default + * from the current look and feel. + * + * @param title the title text, or null + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, + int titlePosition) + { + super(border, title, titleJustification, titlePosition); + } + + + /** + * Constructs a TitledBorder given its border, title text, + * horizontal alignment, vertical position, and font. + * + * @param border the border underneath the title, or + * null to use a default + * from the current look and feel. + * + * @param title the title text, or null + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or null + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, + int titlePosition, + Font titleFont) + { + super(border, title, titleJustification, titlePosition, + titleFont); + } + + + /** + * Constructs a TitledBorder given its border, title text, + * horizontal alignment, vertical position, font, and color. + * + * @param border the border underneath the title, or + * null to use a default + * from the current look and feel. + * + * @param title the title text, or null + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or null + * to use a default from the current look and feel. + * + * @param titleColor the color for the title text, or null + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if titleJustification + * or titlePosition have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, int titlePosition, + Font titleFont, Color titleColor) + { + super(border, title, titleJustification, titlePosition, + titleFont, titleColor); + } + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ButtonUI.java b/libjava/classpath/javax/swing/plaf/ButtonUI.java new file mode 100644 index 0000000..197299e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ButtonUI.java @@ -0,0 +1,52 @@ +/* ButtonUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JButton. + * + * @see javax.swing.JButton + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ButtonUI + extends ComponentUI +{ +} diff --git a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java new file mode 100644 index 0000000..68ffd91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java @@ -0,0 +1,60 @@ +/* ColorChooserUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JColorChooser. + * + * @see javax.swing.JColorChooser + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ColorChooserUI + extends ComponentUI +{ + /** + * Constructs a ColorChooserUI. + */ + public ColorChooserUI() + { + /* The constructor does not do anything. */ + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ColorUIResource.java b/libjava/classpath/javax/swing/plaf/ColorUIResource.java new file mode 100644 index 0000000..33b1676 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ColorUIResource.java @@ -0,0 +1,123 @@ +/* ColorUIResource.java + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Color; + + +/** + * A Color that is marked as UIResource, which indicates that + * the color has been installed by a pluggable LookAndFeel. Such colors + * are replaced when the LookAndFeel changes. + * + * @see java.awt.Color + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ColorUIResource + extends Color + implements UIResource +{ + /** + * Constructs a ColorUIResource using the specified + * red, green, and blue values, which must be given as integers in + * the range of 0-255. The alpha channel value will default to 255, + * meaning that the color is fully opaque. + * + * @param r the red intensity, which must be in the range [0 .. 255]. + * @param g the green intensity, which must be in the range [0 .. 255]. + * @param b the blue intensity, which must be in the range [0 .. 255]. + * + * @throws IllegalArgumentException if any of the values is outside the + * specified range. + */ + public ColorUIResource(int r, int g, int b) + { + super(r, g, b); + } + + + /** + * Constructs a ColorUIResource using the specified + * RGB value. The blue value is in bits 0-7, green in bits 8-15, and + * red in bits 16-23. The other bits are ignored. The alpha value is set + * to 255, meaning that the color is fully opaque. + * + * @param rgb the rgb value, as discussed above. + */ + public ColorUIResource(int rgb) + { + super(rgb); + } + + + /** + * Constructs a ColorUIResource using the specified + * red, green, and blue intensities, which must be given as floats in + * the range of 0-1. The alpha channel value will default to 1.0f, + * meaning that the color is fully opaque. + * + * @param r the red intensity, which must be in the range [0.0 .. 1.0]. + * @param g the green intensity, which must be in the range [0.0 .. 1.0]. + * @param b the blue intensity, which must be in the range [0.0 .. 1.0]. + * + * @throws IllegalArgumentException if any of the values is outside the + * specified range. + */ + public ColorUIResource(float r, float g, float b) + { + super(r, g, b); + } + + + /** + * Constructs a ColorUIResource, using the intensities + * of another color. + * + * @param c the color whose intensities will be considered when + * constructing this ColorUIResource (null + * not permitted). + * + * @throws NullPointerException if c is null. + */ + public ColorUIResource(Color c) + { + super(c.getRGB()); + } +} diff --git a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java new file mode 100644 index 0000000..9498a48 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java @@ -0,0 +1,96 @@ +/* ComboBoxUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.JComboBox; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JButton. + * + * @see javax.swing.JComboBox + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ComboBoxUI + extends ComponentUI +{ + /** + * Constructs a new ComboBoxUI. + */ + public ComboBoxUI() + { + } + + + /** + * Sets the visibility of the popup button. + * + * @param c the JComboBox whose popup + * is shown or hidden. + * + * @param visible true to show the popup, false + * to hide it. + */ + public abstract void setPopupVisible(JComboBox c, boolean visible); + + + /** + * Determines whether the popup button is currently visible. + * + * @param c the JComboBox whose popup visibility + * is retrieved. + * + * @return true if the popup button is currently + * visible, false otherwise. + */ + public abstract boolean isPopupVisible(JComboBox c); + + + /** + * Determines whether the combo box can receive input focus. + * + * @param c JComboBox whose focus traversability + * is to be retrieved. + * + * @returns true if c can receive + * input focus, false otherwise. + */ + public abstract boolean isFocusTraversable(JComboBox c); +} diff --git a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java new file mode 100644 index 0000000..e141871 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java @@ -0,0 +1,70 @@ +/* ComponentInputMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.ComponentInputMap; +import javax.swing.JComponent; + + +/** + * A ComponentInputMap that implements the {@link UIResource} + * interface to indicate that it belongs to a pluggable + * LookAndFeel. + * + * @see javax.swing.ComponentInputMap + * @see javax.swing.InputMap + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ComponentInputMapUIResource + extends ComponentInputMap + implements UIResource +{ + /** + * Constructs a new ComponentInputMapUIResource. + * + * @param component the JComponent associated with + * this InputMap. + */ + public ComponentInputMapUIResource(JComponent component) + { + super(component); + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ComponentUI.java b/libjava/classpath/javax/swing/plaf/ComponentUI.java new file mode 100644 index 0000000..0e76805 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComponentUI.java @@ -0,0 +1,326 @@ +/* ComponentUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.accessibility.Accessible; +import javax.swing.JComponent; + +/** + * The abstract base class for all delegates that provide the + * pluggable look and feel for Swing components. User applications + * should not need to access this class; it is internal to Swing + * and the look-and-feel implementations. + * + *

[UML diagram illustrating the architecture for pluggable
+ * look and feels]

+ * + *

Components such as {@link javax.swing.JSlider} do not directly + * implement operations related to the look and feel of the user + * interface, such as painting or layout. Instead, they use a delegate + * object for all such tasks. In the case of JSlider, the + * user interface would be provided by some concrete subclass of + * {@link javax.swing.plaf.SliderUI}. + * + *

Soon after its creation, a ComponentUI will be sent + * an {@link #installUI} message. The ComponentUI will + * react by setting properties such as the border or the background + * color of the JComponent for which it provides its + * services. Soon before the end of its lifecycle, the + * ComponentUI will receive an {@link #uninstallUI} + * message, at which time the ComponentUI is expected to + * undo any changes.

+ * + *

Note that the ui of a JComponent + * changes whenever the user switches between look and feels. For + * example, the ui property of a JSlider + * could change from an instance of MetalSliderUI to an + * instance of FooSliderUI. This switch can happen at any + * time, but it will always be performed from inside the Swing thread.

+ * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ComponentUI +{ + /** + * Constructs a new UI delegate. + */ + public ComponentUI() + { + } + + + /** + * Sets up the specified component so it conforms the the design + * guidelines of the implemented look and feel. When the look and + * feel changes, a ComponentUI delegate is created. + * The delegate object then receives an installUI + * message. + * + *

This method should perform the following tasks:

+ * + * + * + * @param c the component for which this delegate will provide + * services. + * + * @see #uninstallUI + * @see javax.swing.JComponent#setUI + * @see javax.swing.JComponent#updateUI + */ + public void installUI(JComponent c) + { + // The default implementation does not change any properties. + } + + + /** + * Puts the specified component into the state it had before + * {@link #installUI} was called. + * + * @param c the component for which this delegate has provided + * services. + * + * @see #installUI + * @see javax.swing.JComponent#setUI + * @see javax.swing.JComponent#updateUI + */ + public void uninstallUI(JComponent c) + { + // The default implementation does not change any properties. + } + + + /** + * Paints the component according to the design guidelines + * of the look and feel. Most subclasses will want to override + * this method. + * + * @param g the graphics for painting. + * + * @param c the component for which this delegate performs + * services. + */ + public void paint(Graphics g, JComponent c) + { + } + + + /** + * Fills the specified component with its background color + * (unless the opaque property is false) + * before calling {@link #paint}. + * + *

It is unlikely that a subclass needs to override this method. + * The actual rendering should be performed by the {@link #paint} + * method. + * + * @param g the graphics for painting. + * + * @param c the component for which this delegate performs + * services. + * + * @see #paint + * @see javax.swing.JComponent#paintComponent + */ + public void update(Graphics g, JComponent c) + { + if (c.isOpaque()) + { + g.setColor(c.getBackground()); + g.fillRect(0, 0, c.getWidth(), c.getHeight()); + } + paint(g, c); + } + + + /** + * Determines the preferred size of a component. The default + * implementation returns null, which means that + * c’s layout manager should be asked to + * calculate the preferred size. + * + * @param c the component for which this delegate performs services. + * + * @return the preferred size, or null to indicate that + * c’s layout manager should be asked + * for the preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return null; + } + + + /** + * Determines the minimum size of a component. The default + * implementation calls {@link #getPreferredSize}, but subclasses + * might want to override this. + * + * @param c the component for which this delegate performs services. + * + * @return the minimum size, or null to indicate that + * c’s layout manager should be asked + * to calculate the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + + /** + * Determines the maximum size of a component. The default + * implementation calls {@link #getPreferredSize}, but subclasses + * might want to override this. + * + * @param c the component for which this delegate performs services. + * + * @return the maximum size, or null to indicate that + * c’s layout manager should be asked + * to calculate the maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + + /** + * Determines whether a click into the component at a specified + * location is considered as having hit the component. The default + * implementation checks whether the point falls into the + * component’s bounding rectangle. Some subclasses might want + * to override this, for example in the case of a rounded button. + * + * @param c the component for which this delegate performs services. + * + * @param x the x coordinate of the point, relative to the local + * coordinate system of the component. Zero would be be + * component’s left edge, irrespective of the location + * inside its parent. + * + * @param y the y coordinate of the point, relative to the local + * coordinate system of the component. Zero would be be + * component’s top edge, irrespective of the location + * inside its parent. + */ + public boolean contains(JComponent c, int x, int y) + { + /* JComponent.contains calls the ui delegate for hit + * testing. Therefore, endless mutual recursion would result if we + * called c.contains(x, y) here. + * + * The previous Classpath implementation called the deprecated + * method java.awt.Component.inside. In the Sun implementation, it + * can be observed that inside, other than contains, does not call + * the ui delegate. But that inside() behaves different to + * contains() clearly is in violation of the method contract, and + * it is not something that a good implementation should rely upon + * -- even if Classpath ends up being forced to replicate this + * apparent bug of the Sun implementation. + */ + return (x >= 0) && (x < c.getWidth()) + && (y >= 0) && (y < c.getHeight()); + } + + + /** + * Creates a delegate object for the specified component. Users + * should use the createUI method of a suitable + * subclass. The implementation of ComponentUI + * always throws an error. + * + * @param c the component for which a UI delegate is requested. + */ + public static ComponentUI createUI(JComponent c) + { + throw new Error( + "javax.swing.plaf.ComponentUI does not implement createUI; call " + + "createUI on a subclass."); + } + + + /** + * Counts the number of accessible children in the component. The + * default implementation delegates the inquiry to the {@link + * javax.accessibility.AccessibleContext} of c. + * + * @param c the component whose accessible children + * are to be counted. + */ + public int getAccessibleChildrenCount(JComponent c) + { + return c.getAccessibleContext().getAccessibleChildrenCount(); + } + + + /** + * Returns the specified accessible child of the component. The + * default implementation delegates the inquiry to the {@link + * javax.accessibility.AccessibleContext} of c. + * + * @param i the index of the accessible child, starting at zero. + * + * @param c the component whose i-th accessible child + * is requested. + */ + public Accessible getAccessibleChild(JComponent c, int i) + { + return c.getAccessibleContext().getAccessibleChild(i); + } +} diff --git a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java new file mode 100644 index 0000000..2e44088 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java @@ -0,0 +1,56 @@ +/* DesktopIconUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a desktop icon. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class DesktopIconUI + extends ComponentUI +{ + /** + * Constructs a new DesktopIconUI. + */ + public DesktopIconUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java new file mode 100644 index 0000000..de553ea --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java @@ -0,0 +1,59 @@ +/* DesktopPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JDesktopPane. + * + * @see javax.swing.JDesktopPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class DesktopPaneUI + extends ComponentUI +{ + /** + * Constructs a new DesktopPaneUI. + */ + public DesktopPaneUI() + { + } +} + diff --git a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java new file mode 100644 index 0000000..63c6838 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java @@ -0,0 +1,68 @@ +/* DimensionUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Dimension; + +/** + * A Dimension that is marked as UIResource, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @see java.awt.Dimension + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class DimensionUIResource + extends Dimension + implements UIResource +{ + /** + * Constructs a new DimensionUIResource, given its width and height. + * + * @param width the width in pixels. + * @param height the height in pixels. + */ + public DimensionUIResource(int width, int height) + { + super(width, height); + } +} diff --git a/libjava/classpath/javax/swing/plaf/FileChooserUI.java b/libjava/classpath/javax/swing/plaf/FileChooserUI.java new file mode 100644 index 0000000..87847c4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/FileChooserUI.java @@ -0,0 +1,138 @@ +/* FileChooserUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileView; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JFileChooser. + * + * @see javax.swing.JFileChooser + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class FileChooserUI + extends ComponentUI +{ + /** + * Constructs a new FileChooserUI. + */ + public FileChooserUI() + { + } + + + /** + * Returns a FileFilter that accepts every file. While + * the filtering itself is not specific to any look and feel, the + * text returned by FileFilter.getDescription() need + * not be the same across all look and feels. + * + * @param chooser the JFileChooser for which + * a FileFilter is requested. + * + * @see javax.swing.JFileChooser#getAcceptAllFileFilter + * @see javax.swing.filechooser.FileFilter#getDescription + */ + public abstract FileFilter getAcceptAllFileFilter(JFileChooser chooser); + + + /** + * Returns a view to a file, which is able to retrieve its name, + * icon, and other properties that are relevant for presenting + * the file to the user. + * + * @param chooser the JFileChooser for which + * a FileFilter is requested. + */ + public abstract FileView getFileView(JFileChooser chooser); + + + /** + * Determines which text is appropriate for the approve button + * according to the design guidelines of the implemented + * look and feel. + * + * @param chooser the JFileChooser whose + * button text is requested. + * + * @see javax.swing.JFileChoose#getApproveButtonText + */ + public abstract String getApproveButtonText(JFileChooser chooser); + + + /** + * Determines which text is appropriate for the title bar of a + * JFileChooser according to the design guidelines of + * the implemented look and feel. + * + * @param chooser the JFileChooser whose + * dialog title is requested. + * + * @see javax.swing.JFileChoose#getDialogtitle + */ + public abstract String getDialogTitle(JFileChooser chooser); + + + /** + * Refreshes the currently displayed directory. + * + * @param chooser the JFileChooser whose + * dialog title needs re-scanning. + */ + public abstract void rescanCurrentDirectory(JFileChooser chooser); + + + /** + * Ensures that a specified file is visible in the + * JFileChooser + * + * @param chooser the JFileChooser that + * should display the file file. + * + * @param file the file that needs to be made visible. + */ + public abstract void ensureFileIsVisible(JFileChooser chooser, File file); +} diff --git a/libjava/classpath/javax/swing/plaf/FontUIResource.java b/libjava/classpath/javax/swing/plaf/FontUIResource.java new file mode 100644 index 0000000..1c17310 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/FontUIResource.java @@ -0,0 +1,101 @@ +/* FontUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Font; + + +/** + * A font that is marked as UIResource, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class FontUIResource + extends Font + implements UIResource +{ + /** + * Constructs a new FontUIResource given + * the name, style and size of the font. + * + * @param name the name of the font. A number of + * “logical” names are supported by any Java + * implementation. These are + * “Dialog”, + * “DialogInput”, + * “Monospaced”, + * “Serif”, and + * “SansSerif”. + * + * @param style the style of the font, for instance {@link + * java.awt.Font#BOLD} or {@link java.awt.Font#PLAIN}. + * + * @param size the size of the font in typographic points, for + * instance 10, 12 or 13. Designers of LookAndFeels should be + * aware that some languages (like Japanese and Chinese) have + * glyphs that are too complex to be legible at small point + * sizes. + */ + public FontUIResource(String name, int style, int size) + { + super(name, style, size); + } + + + /** + * Constructs a new FontUIResource given + * an existing font. + * + * @param f the font that serves as a template. + */ + public FontUIResource(Font f) + { + /* This implementation will get rid of many font properties, + * such as skewing, values of multiple master design axes, + * etc., unless they get encoded into the name. It probably + * is not a problem for LookAndFeels because user interfaces + * are usually not very advanced with respect to typography. + */ + super(f.getName(), f.getStyle(), f.getSize()); + } +} diff --git a/libjava/classpath/javax/swing/plaf/IconUIResource.java b/libjava/classpath/javax/swing/plaf/IconUIResource.java new file mode 100644 index 0000000..1b09ed3 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/IconUIResource.java @@ -0,0 +1,122 @@ +/* IconUIResource.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; + +import javax.swing.Icon; + +/** + * An icon that is marked as UIResource, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such icons are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class IconUIResource + implements Icon, UIResource, Serializable +{ + /** + * Verified using the serialver tool of Sun JDK 1.4.1_01 + * on GNU/Linux 2.4.18. + */ + static final long serialVersionUID = 3327049506004830542L; + + + /** + * The icon that is wrapped by this IconUIResource. + */ + private Icon delegate; + + + /** + * Constructs a IconUIResource that wraps another + * icon. All messages are forwarded to the delegate icon. + * + * @param delegate the icon that is wrapped by this + * IconUIResource. + */ + public IconUIResource(Icon delegate) + { + this.delegate = delegate; + } + + + /** + * Paints the icon by asking the delegate icon to paint itself. + * + * @param c the Component whose icon is being painted. Some icons + * use this argument to retrieve properties like the + * background color. + * + * @param g the graphics into which the icon will be painted. + * + * @param x the horizontal position of the icon. + * + * @param y the vertical position of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + delegate.paintIcon(c, g, x, y); + } + + + /** + * Returns the width of the icon in pixels. The implementation + * determines and returns the width of the delegate icon. + */ + public int getIconWidth() + { + return delegate.getIconWidth(); + } + + + /** + * Returns the height of the icon in pixels. The implementation + * determines and returns the height of the delegate icon. + */ + public int getIconHeight() + { + return delegate.getIconHeight(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java new file mode 100644 index 0000000..ae032e5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java @@ -0,0 +1,63 @@ +/* InputMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.InputMap; + + +/** + * An InputMap that is marked as UIResource, + * which indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class InputMapUIResource + extends InputMap + implements UIResource +{ + /** + * Constructs a new InputMapUIResource. + */ + public InputMapUIResource() + { + } +} + diff --git a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java new file mode 100644 index 0000000..755d8ad --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java @@ -0,0 +1,77 @@ +/* InsetsUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Insets; +import java.io.Serializable; + + +/** + * An Insets that is marked as UIResource, + * which indicates that it has been installed by a pluggable + * LookAndFeel. Such insets are replaced when the LookAndFeel changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class InsetsUIResource + extends Insets + implements Cloneable, UIResource, Serializable +{ + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 5622110143266315421L; + + + /** + * Constructs a new InsetsUIResource given the + * inset at each edge. + * + * @param top the inset at the top, in pixels. + * @param left the inset at the left, in pixels. + * @param bottom the inset at the bottom, in pixels. + * @param right the inset at the right, in pixels. + */ + public InsetsUIResource(int top, int left, int bottom, int right) + { + super(top, left, bottom, right); + } +} diff --git a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java new file mode 100644 index 0000000..fd1e337 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java @@ -0,0 +1,59 @@ +/* InternalFrameUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JInternalFrame. + * + * @see javax.swing.JInternalFrame + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class InternalFrameUI + extends ComponentUI +{ + /** + * Constructs a new InternalFrameUI. + */ + public InternalFrameUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/LabelUI.java b/libjava/classpath/javax/swing/plaf/LabelUI.java new file mode 100644 index 0000000..8fc1d71 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/LabelUI.java @@ -0,0 +1,59 @@ +/* LabelUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JLabel. + * + * @see javax.swing.JLabel + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class LabelUI + extends ComponentUI +{ + /** + * Constructs a new LabelUI. + */ + public LabelUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ListUI.java b/libjava/classpath/javax/swing/plaf/ListUI.java new file mode 100644 index 0000000..66d5cf5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ListUI.java @@ -0,0 +1,114 @@ +/* ListUI.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Point; +import java.awt.Rectangle; + +import javax.swing.JList; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JList. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ListUI + extends ComponentUI +{ + /** + * Constructs a new ListUI. + */ + public ListUI() + { + } + + + /** + * Determines the cell index which is the closest to the specified + * location. The find out whether the returned cell actually + * contains the location, the caller should also use {@link + * #getCellBounds}. + * + * @param list the JList for which this delegate object + * provides the pluggable user interface. + * + * @param location a point in the JList coordinate + * system. + * + * @return the index of the closest cell, or -1 if the list model + * is empty. + */ + public abstract int locationToIndex(JList list, Point location); + + + /** + * Determines the location of the specified cell. + * + * @param list the JList for which this delegate object + * provides the pluggable user interface. + * + * @param index the zero-based index of the cell whose location shall be + * determined. + * + * @return the position of the top left corner of the cell in the + * JList coordinate system, or null + * if cell does not designate a valid cell. + */ + public abstract Point indexToLocation(JList list, int index); + + + /** + * Determines the bounding box of the rectangle spanned by + * two list indices. + * + * @param list the JList for which this delegate object + * provides the pluggable user interface. + * + * @param index1 the zero-based index of the first cell. + * + * @param index2 the zero-based index of the second cell. + * + * @return the spanned rectangle, or null if either + * index1 or index2 does not + * designate a valid cell. + */ + public abstract Rectangle getCellBounds(JList list, + int index1, int index2); +} diff --git a/libjava/classpath/javax/swing/plaf/MenuBarUI.java b/libjava/classpath/javax/swing/plaf/MenuBarUI.java new file mode 100644 index 0000000..8835571 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/MenuBarUI.java @@ -0,0 +1,59 @@ +/* MenuBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JMenuBar. + * + * @see javax.swing.JMenuBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class MenuBarUI + extends ComponentUI +{ + /** + * Constructs a new MenuBarUI. + */ + public MenuBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/MenuItemUI.java b/libjava/classpath/javax/swing/plaf/MenuItemUI.java new file mode 100644 index 0000000..31d7319 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/MenuItemUI.java @@ -0,0 +1,59 @@ +/* MenuItemUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JMenuItem. + * + * @see javax.swing.JMenuItem + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class MenuItemUI + extends ButtonUI +{ + /** + * Constructs a new MenuItemUI. + */ + public MenuItemUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/OptionPaneUI.java b/libjava/classpath/javax/swing/plaf/OptionPaneUI.java new file mode 100644 index 0000000..13d1caa --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/OptionPaneUI.java @@ -0,0 +1,75 @@ +/* OptionPaneUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.JOptionPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JOptionPane. + * + * @see javax.swing.JOptionPane + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class OptionPaneUI + extends ComponentUI +{ + /** + * Gives keyboard input focus to the component that represents + * the default value. + * + * @param pane the JOptionPane for which this delegate + * object provides the pluggable user interface. + */ + public abstract void selectInitialValue(JOptionPane pane); + + + /** + * Determines whether the user has provided custom components + * for the options or the message. + * + * @param pane the JOptionPane for which this delegate + * object provides the pluggable user interface. + * + * @return true if the user has supplied any custom + * components; false if all components are + * provided by Swing or a LookAndFeel. + */ + public abstract boolean containsCustomComponents(JOptionPane pane); +} diff --git a/libjava/classpath/javax/swing/plaf/PanelUI.java b/libjava/classpath/javax/swing/plaf/PanelUI.java new file mode 100644 index 0000000..b1171b8 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/PanelUI.java @@ -0,0 +1,58 @@ +/* PanelUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JPanel. + * + * @see javax.swing.JPanel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class PanelUI + extends ComponentUI +{ + /** + * Constructs a new PanelUI. + */ + public PanelUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java new file mode 100644 index 0000000..c70ad2a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java @@ -0,0 +1,117 @@ +/* PopupMenuUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.event.MouseEvent; + +import javax.swing.JPopupMenu; +import javax.swing.Popup; +import javax.swing.PopupFactory; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JPopupMenu. + * + * @see javax.swing.JPopupMenu + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class PopupMenuUI + extends ComponentUI +{ + /** + * Constructs a new PopupMenuUI. + */ + public PopupMenuUI() + { + } + + + /** + * Tests whether or not a mouse event triggers a popup menu. + * + *

The default implementation calls + * event.isPopupTrigger(), which checks for the gesture + * that is common for the platform on which the application runs. If + * a look and feel wants to employ non-standard conventions for + * triggering a popup menu, it can override this method. + * + * @param event the event to check. + * + * @return true if the event triggers a popup menu; + * false otherwise. + * + * @since 1.3 + */ + public boolean isPopupTrigger(MouseEvent event) + { + return event.isPopupTrigger(); + } + + + /** + * Creates a Popup for displaying the popup menu. The + * default implementation uses the {@link javax.swing.PopupFactory} + * for retrieving a suitable Popup, but subclasses + * might want to override this method if a LookAndFeel needs special + * Popups. + * + * @param popup the JPopupMenu for whose display + * a Popup is needed. + * + * @param x the horizontal position where the popup will be + * displayed. + * + * @param y the vertical position where the popup will be + * displayed. + * + * @return a Popup for showing and hiding + * the menu. + * + * @since 1.4 + */ + public Popup getPopup(JPopupMenu popup, int x, int y) + { + return PopupFactory.getSharedInstance().getPopup( + /* origin/owner of the popup */ popup.getInvoker(), + /* contents */ popup, + x, y); + } +} diff --git a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java new file mode 100644 index 0000000..79c1b95 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java @@ -0,0 +1,59 @@ +/* ProgressBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JProgressBar. + * + * @see javax.swing.JProgressBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ProgressBarUI + extends ComponentUI +{ + /** + * Constructs a new ProgressBarUI. + */ + public ProgressBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/RootPaneUI.java b/libjava/classpath/javax/swing/plaf/RootPaneUI.java new file mode 100644 index 0000000..ff7d0a6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/RootPaneUI.java @@ -0,0 +1,58 @@ +/* RootPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JRootPane. + * + * @see javax.swing.JRootPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class RootPaneUI + extends ComponentUI +{ + /** + * Constructs a new RootPaneUI. + */ + public RootPaneUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java new file mode 100644 index 0000000..3cad393 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java @@ -0,0 +1,58 @@ +/* ScrollBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JScrollBar. + * + * @see javax.swing.JScrollBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ScrollBarUI + extends ComponentUI +{ + /** + * Constructs a new ScrollBarUI. + */ + public ScrollBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java new file mode 100644 index 0000000..14d2ac6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java @@ -0,0 +1,59 @@ +/* ScrollPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JScrollPane. + * + * @see javax.swing.JScrollPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ScrollPaneUI + extends ComponentUI +{ + /** + * Constructs a new ScrollPaneUI. + */ + public ScrollPaneUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SeparatorUI.java b/libjava/classpath/javax/swing/plaf/SeparatorUI.java new file mode 100644 index 0000000..6855bd0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SeparatorUI.java @@ -0,0 +1,58 @@ +/* SeparatorUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JSeparator. + * + * @see javax.swing.JSeparator + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SeparatorUI + extends ComponentUI +{ + /** + * Constructs a new SeparatorUI. + */ + public SeparatorUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SliderUI.java b/libjava/classpath/javax/swing/plaf/SliderUI.java new file mode 100644 index 0000000..775f196 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SliderUI.java @@ -0,0 +1,59 @@ +/* SliderUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JSlider. + * + * @see javax.swing.JSlider + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SliderUI + extends ComponentUI +{ + /** + * Constructs a new SliderUI. + */ + public SliderUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SpinnerUI.java b/libjava/classpath/javax/swing/plaf/SpinnerUI.java new file mode 100644 index 0000000..fb4a3b1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SpinnerUI.java @@ -0,0 +1,59 @@ +/* SpinnerUI.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JSpinner. + * + * @since 1.4 + * @see javax.swing.JSpinner + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SpinnerUI + extends ComponentUI +{ + /** + * Constructs a new SpinnerUI. + */ + public SpinnerUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java new file mode 100644 index 0000000..ea9af2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java @@ -0,0 +1,133 @@ +/* SplitPaneUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Graphics; + +import javax.swing.JSplitPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JSplitPane. + * + * @see javax.swing.JSplitPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SplitPaneUI + extends ComponentUI +{ + /** + * Constructs a new SplitPaneUI. + */ + public SplitPaneUI() + { + } + + + /** + * Moves the divider to the location which best respects + * the preferred sizes of the children. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + */ + public abstract void resetToPreferredSizes(JSplitPane pane); + + + /** + * Moves the divider to the specified location. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + * + * @param location the new location of the divider. + */ + public abstract void setDividerLocation(JSplitPane pane, + int location); + + + /** + * Determines the current location of the divider. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + * + * @return the current location of the divider. + */ + public abstract int getDividerLocation(JSplitPane pane); + + + /** + * Determines the minimum location of the divider. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + * + * @return the leftmost (or topmost) possible location + * of the divider. + */ + public abstract int getMinimumDividerLocation(JSplitPane pane); + + + /** + * Determines the maximum location of the divider. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + * + * @return the bottommost (or rightmost) possible location + * of the divider. + */ + public abstract int getMaximumDividerLocation(JSplitPane pane); + + + /** + * Called by the JSplitPane after it has finished + * painting its children. + * + * @param pane the JSplitPane for thich this + * delegate provides the look and feel. + * + * @param g the Graphics used for painting. + */ + public abstract void finishedPaintingChildren(JSplitPane pane, + Graphics g); +} diff --git a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java new file mode 100644 index 0000000..6ab823b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java @@ -0,0 +1,111 @@ +/* TabbedPaneUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Rectangle; + +import javax.swing.JTabbedPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JTabbedPane. + * + * @see javax.swing.JTabbedPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TabbedPaneUI + extends ComponentUI +{ + /** + * Constructs a new TabbedPaneUI. + */ + public TabbedPaneUI() + { + } + + + /** + * Determines which tab lies at a given position. + * + * @param pane the JTabbedPane for which this + * delegate object provides the user interface. + * + * @param x the horizontal position, where zero is the left + * edge of pane. + * + * @param y the vertical position, where zero is the top + * edge of pane. + * + * @return the zero-based index of the tab, or -1 if no + * tab is at the specified position. + */ + public abstract int tabForCoordinate(JTabbedPane pane, + int x, int y); + + + /** + * Calculates the bounding box of a tab. + * + * @param pane the JTabbedPane for which this + * delegate object provides the user interface. + * + * @param index the index of the tab, which must be an integer + * in the range [0 .. pane.getTabCount() - 1]. + * + * @return the bounding box of the index-th tab, + * in the coordinate system of pane. + */ + public abstract Rectangle getTabBounds(JTabbedPane pane, int index); + + + /** + * Determines how many runs are used to display tabs. + * + * @param pane the JTabbedPane for which this + * delegate object provides the user interface. + * + * @return the number of tab runs. + * + * @see javax.swing.JTabbedPane#getTabRunCount() + */ + public abstract int getTabRunCount(JTabbedPane pane); +} + diff --git a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java new file mode 100644 index 0000000..f23ca74 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java @@ -0,0 +1,59 @@ +/* TableHeaderUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JTableHeader. + * + * @see javax.swing.table.JTableHeader + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TableHeaderUI + extends ComponentUI +{ + /** + * Constructs a new TableHeaderUI. + */ + public TableHeaderUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TableUI.java b/libjava/classpath/javax/swing/plaf/TableUI.java new file mode 100644 index 0000000..e56bcd1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TableUI.java @@ -0,0 +1,59 @@ +/* TableUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JTable. + * + * @see javax.swing.JTable + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TableUI + extends ComponentUI +{ + /** + * Constructs a new TableUI. + */ + public TableUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TextUI.java b/libjava/classpath/javax/swing/plaf/TextUI.java new file mode 100644 index 0000000..86d1f1f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TextUI.java @@ -0,0 +1,284 @@ +/* TextUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Point; +import java.awt.Rectangle; + +import javax.swing.text.BadLocationException; +import javax.swing.text.EditorKit; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.View; + +/** + * An abstract base class for delegates that provide the user + * interface for text editors. + * + * @see javax.swing.text.JTextComponent + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TextUI + extends ComponentUI +{ + /** + * Constructs a new TextUI. + */ + public TextUI() + { + } + + + /** + * Calculates the geometric extent of the character at the + * given offset. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param pos the zero-based index of the character into the + * document model. + * + * @return the bounding box of the character at index + * pos, in view coordinates. + * + * @throws BadLocationException if pos does not + * designate a valid position in the document model. + * + * @see javax.swing.text.View#modelToView(int, + * javax.swing.text.Position.Bias, int, + * javax.swing.text.position.Bias, java.awt.Shape) + */ + public abstract Rectangle modelToView(JTextComponent tc, int pos) + throws BadLocationException; + + + /** + * Calculates the geometric extent of the character at the + * given offset. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param pos the zero-based index of the character into the + * document model. + * + * @param bias whether to take the character before or after the + * caret position indicated by pos. The value + * must be either {@link + * javax.swing.text.Position.Bias#Backward} or {@link + * javax.swing.text.Position.Bias#Forward}. + * + * @return the bounding box of the character at index + * pos, in view coordinates. + * + * @throws BadLocationException if pos does not + * designate a valid position in the document model. + * + * @see javax.swing.text.View#modelToView(int, + * javax.swing.text.Position.Bias, int, + * javax.swing.text.position.Bias, java.awt.Shape) + */ + public abstract Rectangle modelToView(JTextComponent tc, int pos, + Position.Bias bias) + throws BadLocationException; + + + /** + * Finds the caret position which is closest to the specified visual + * location. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param loc the position in view coordinates. + * + * @return the caret position which is closest to loc. + * + * @see #viewToModel(JTextComponent, Point, Position.Bias[]) + */ + public abstract int viewToModel(JTextComponent t, Point pt); + + + /** + * Finds the caret position which is closest to the specified visual + * location. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param loc the position in view coordinates. + * + * @param outBias an array whose size must be at least one. + * After the call, outBias[0] will indicate + * whether loc is in the glyph before + * (Position.Bias.Backward) or after + * (Position.Bias.Forward) the returned + * caret position. + * + * @return the caret position which is closest to loc. + */ + public abstract int viewToModel(JTextComponent tc, Point loc, + Position.Bias[] outBias); + + + + /** + * Calculates the caret position that is visually next to the given + * position. This is useful to determine where to move the caret + * after the user has pressed an arrow key. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param pos the current caret position, a zero-based index + * into the document model. + * + * @param bias whether to take the character before or after the + * caret position indicated by pos. The value + * must be either {@link + * javax.swing.text.Position.Bias#Backward} or {@link + * javax.swing.text.Position.Bias#Forward}. + * + * @param direction the visual direction. Pass + * {@link javax.swing.SwingConstants#WEST} for the left + * arrow key, {@link javax.swing.SwingConstants#EAST} + * for the right arrow key, {@link + * javax.swing.SwingConstants#NORTH} for the up arrow + * key, or {@link javax.swing.SwingConstants#SOUTH} + * for the down arrow key. + * + * @throws BadLocationException if pos does not + * designate a valid position in the document model. + * + * @throws IllegalArgumentException if direction + * is not one of Position.Bias.Forward + * or Position.Biad.Backward. + */ + public abstract int getNextVisualPositionFrom(JTextComponent tc, + int pos, + Position.Bias bias, + int direction, + Position.Bias[] outBias) + throws BadLocationException; + + + /** + * Repaints a range of characters. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param start the first character in the range that needs + * painting, indicated as an index into the document model. + * + * @param end the last character in the range that needs + * painting, indicated as an index into the document model. + * end must be greater than or equal to + * start. + */ + public abstract void damageRange(JTextComponent tc, int start, int end); + + + /** + * Repaints a range of characters, also specifying the bias for the + * start and end of the range. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param start the first character in the range that needs + * painting, indicated as an index into the document model. + * + * @param end the last character in the range that needs + * painting, indicated as an index into the document model. + * end must be greater than or equal to + * start. + */ + public abstract void damageRange(JTextComponent tc, + int start, int end, + Position.Bias startBias, + Position.Bias endBias); + + + /** + * Retrieves the EditorKit managing policies and + * persistent state. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @return the EditorKit used by tc. + */ + public abstract EditorKit getEditorKit(JTextComponent tc); + + + /** + * Retrieves the root of the view tree that visually presents + * the text. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @return the root View used by tc. + */ + public abstract View getRootView(JTextComponent tc); + + + /** + * Returns a String for presenting a tool tip at the specified + * location. + * + * @param tc the JTextComponent for which this + * delegate object provides the user interface. + * + * @param loc the location for which the tool tip is requested. + * + * @return the text for the tool tip, or null to + * display no tool tip. + * + * @since 1.4 + */ + public String getToolTipText(JTextComponent tc, Point loc) + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/ToolBarUI.java b/libjava/classpath/javax/swing/plaf/ToolBarUI.java new file mode 100644 index 0000000..730cf48 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ToolBarUI.java @@ -0,0 +1,59 @@ +/* ToolBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JToolBar. + * + * @see javax.swing.JToolBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ToolBarUI + extends ComponentUI +{ + /** + * Constructs a new ToolBarUI. + */ + public ToolBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ToolTipUI.java b/libjava/classpath/javax/swing/plaf/ToolTipUI.java new file mode 100644 index 0000000..4383d0e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ToolTipUI.java @@ -0,0 +1,59 @@ +/* ToolTipUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JToolTip. + * + * @see javax.swing.JToolTip + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ToolTipUI + extends ComponentUI +{ + /** + * Constructs a new ToolTipUI. + */ + public ToolTipUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TreeUI.java b/libjava/classpath/javax/swing/plaf/TreeUI.java new file mode 100644 index 0000000..e32952d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TreeUI.java @@ -0,0 +1,211 @@ +/* TreeUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Rectangle; + +import javax.swing.JTree; +import javax.swing.tree.TreePath; + +/** + * An abstract base class for delegates that provide the user + * interface for JTree. + * + * @see javax.swing.JTree + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TreeUI + extends ComponentUI +{ + /** + * Constructs a new TreeUI. + */ + public TreeUI() + { + } + + + /** + * Determines the geometric extent of the label that is + * drawn for a path. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @param path the path whose label extent is requested. + * + * @return a rectangle enclosing the label, or null + * if path contains invalid nodes. + */ + public abstract Rectangle getPathBounds(JTree tree, TreePath path); + + + /** + * Creates a TreePath for the specified row. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @param row the index of the row, which should be a number + * in the range [0, getRowCount(tree) - 1]. + * + * @return a TreePath for the specified row, or + * null if row is outside + * the valid range. + */ + public abstract TreePath getPathForRow(JTree tree, int row); + + + /** + * Determines in which row a TreePath is currently + * being displayed. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @param path the path for which the caller wants to know + * in which row it is being displayed. + * + * @return a number in the range [0, getRowCount(tree) + * - 1] if the path is currently on display; + * -1 if the path is not shown to the + * user. + */ + public abstract int getRowForPath(JTree tree, TreePath path); + + + /** + * Counts how many rows are currently displayed. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @return the number of visible rows. + */ + public abstract int getRowCount(JTree tree); + + + /** + * Finds the path that is closest to the specified position. + * + *

[A screen shot of a JTree] + * + *

As shown by the above illustration, the bounds of the + * closest path do not necessarily need to contain the passed + * location. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @param x the horizontal location, relative to the origin + * of tree. + * + * @param y the vertical location, relative to the origin + * of tree. + * + * @return the closest path, or null if the + * tree is currenlty not displaying any paths at all. + */ + public abstract TreePath getClosestPathForLocation(JTree tree, + int x, int y); + + + /** + * Determines whether the user is currently editing a tree cell. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @see #getEditingPath + */ + public abstract boolean isEditing(JTree tree); + + + /** + * Stops editing a tree cell, committing the entered value into the + * tree’s model. If no editing session is active, or if the + * active editor does not agree to stopping, nothing happens. In + * some look and feels, this action happens when the user has + * pressed the enter key. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @return false if the editing still goes on because + * the cell editor has objected to stopping the session; + * true if editing has been stopped. + */ + public abstract boolean stopEditing(JTree tree); + + + /** + * Cancels editing a tree cell, discarding any entered value. + * If no editing session is active, nothing happens. The cell + * editor is not given an opportunity to veto the canceling. + * In some look and feels, this action happens when the user has + * pressed the escape key. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + */ + public abstract void cancelEditing(JTree tree); + + + /** + * Starts a session to edit a tree cell. If the cell editor + * rejects editing the cell, it will just be selected. + * + * @param tree the JTree for which this delegate + * object provides the user interface. + * + * @param path the cell to edit. + */ + public abstract void startEditingAtPath(JTree tree, TreePath path); + + + /** + * Retrieves the tree cell that is currently being edited. + * + * @return the currently edited path, or null + * if no editing session is currently active. + */ + public abstract TreePath getEditingPath(JTree tree); +} diff --git a/libjava/classpath/javax/swing/plaf/UIResource.java b/libjava/classpath/javax/swing/plaf/UIResource.java new file mode 100644 index 0000000..1e28280 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/UIResource.java @@ -0,0 +1,55 @@ +/* UIResource.java + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * This public interface is used to designate which objects were created by + * ComponentUI delegates. When uninstalling the user public interface + * renderer with ComponentUI.uninstallUI() the renderer + * property is set to null. + *
+ * A comparison against null can be used with all properties except for + * the java.awt.Component properties font, foreground, and + * background. The container can provide the value of the properties if + * they are initialized or set to null. + * + * @author Brian Jones + * @see java.lang.ComponentUI + */ +public interface UIResource { } diff --git a/libjava/classpath/javax/swing/plaf/ViewportUI.java b/libjava/classpath/javax/swing/plaf/ViewportUI.java new file mode 100644 index 0000000..087938f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ViewportUI.java @@ -0,0 +1,60 @@ +/* ViewportUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a JViewport. + * + * @see javax.swing.JViewport + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ViewportUI + extends ComponentUI +{ + /** + * Constructs a new ViewportUI. + */ + public ViewportUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java new file mode 100644 index 0000000..4da4691 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java @@ -0,0 +1,350 @@ +/* BasicArrowButton.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.JButton; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +/** + * This class draws simple arrow buttons for the Basic Look and Feel. + */ +public class BasicArrowButton extends JButton implements SwingConstants +{ + /** The default size of the Arrow buttons. */ + private static int defaultSize = 10; + + /** 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. */ + protected int direction; + + /** + * The color the arrow is painted in if disabled and the bottom and right + * edges of the button. + * This is package-private to avoid an accessor method. + */ + transient Color shadow = Color.GRAY; + + /** + * The color the arrow is painted in if enabled and the bottom and right + * edges of the button. + * This is package-private to avoid an accessor method. + */ + transient Color darkShadow = Color.DARK_GRAY; + + /** + * The top and left edges of the button. + * This is package-private to avoid an accessor method. + */ + 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. + * + * @param direction The direction the arrow points in. + */ + public BasicArrowButton(int direction) + { + super(); + setBorder(buttonBorder); + setDirection(direction); + } + + /** + * Creates a new BasicArrowButton object with the given colors and + * direction. + * + * @param direction The direction to point in. + * @param background The background color. + * @param shadow The shadow color. + * @param darkShadow The dark shadow color. + * @param highlight The highlight color. + */ + public BasicArrowButton(int direction, Color background, Color shadow, + Color darkShadow, Color highlight) + { + this(direction); + setBackground(background); + this.shadow = shadow; + this.darkShadow = darkShadow; + this.highlight = highlight; + } + + /** + * This method returns whether the focus can traverse to this component. + * + * @return Whether the focus can traverse to this component. + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * This method returns the direction of the arrow. + * + * @return The direction of the arrow. + */ + public int getDirection() + { + return direction; + } + + /** + * This method changes the direction of the arrow. + * + * @param dir The new direction of the arrow. + */ + public void setDirection(int dir) + { + this.direction = dir; + } + + /** + * This method paints the arrow button. The painting is delegated to the + * paintTriangle method. + * + * @param g The Graphics object to paint with. + */ + 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()); + } + + /** + * This method returns the preferred size of the arrow button. + * + * @return The preferred size. + */ + 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); + } + + /** + * This method returns the minimum size of the arrow button. + * + * @return The minimum size. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * This method returns the maximum size of the arrow button. + * + * @return The maximum size. + */ + public Dimension getMaximumSize() + { + return getPreferredSize(); + } + + /** + * The method paints a triangle with the given size and direction at the + * given x and y coordinates. + * + * @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. + */ + 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); + + switch (direction) + { + case NORTH: + x1 = xPoints[0] + 2; + y1 = yPoints[0]; + y2 = y1; + x2 = xPoints[2] - 1; + break; + case SOUTH: + x1 = xPoints[1]; + y1 = yPoints[1] + 1; + x2 = xPoints[2] - 1; + y2 = yPoints[2]; + break; + case LEFT: + case WEST: + x1 = xPoints[0] + 1; + y1 = yPoints[0] + 1; + x2 = x1; + y2 = yPoints[2] + 1; + break; + case RIGHT: + case EAST: + x1 = xPoints[2]; + y1 = yPoints[2] + 1; + x2 = xPoints[1] - 1; + y2 = yPoints[1] + 1; + break; + } + Color saved = g.getColor(); + + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + + if (arrow != null) + g.fillPolygon(xPoints, yPoints, 3); + } + 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); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java new file mode 100644 index 0000000..e7d6e43 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java @@ -0,0 +1,1814 @@ +/* BasicBorders.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JButton; +import javax.swing.JPopupMenu; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +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.plaf.BorderUIResource; +import javax.swing.plaf.UIResource; +import javax.swing.text.JTextComponent; + +/** + * Provides various borders for the Basic look and feel. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BasicBorders +{ + /** + * A MarginBorder that gets shared by multiple components. + * Created on demand by the private helper function {@link + * #getMarginBorder()}. + */ + private static MarginBorder sharedMarginBorder; + + + /** + * Returns a border for drawing push buttons. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “Button.shadow”, + * “Button.darkShadow”, + * “Button.light”, and + * “Button.highlight”. + * + *

[A screen shot of the returned border] + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link ButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new ButtonBorder(defaults.getColor("Button.shadow"), + defaults.getColor("Button.darkShadow"), + defaults.getColor("Button.light"), + defaults.getColor("Button.highlight")); + + /* While the inner border is shared between multiple buttons, + * we do not share the outer border because ButtonBorders store + * their border colors. We cannot guarantee that the colors + * (which come from UIDefaults) are unchanged between invocations + * of getButtonBorder. We could store the last colors, and share + * the button border if the colors are the same as in the last + * invocation, but it probably is not worth the effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing radio buttons. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “RadioButton.shadow”, + * “RadioButton.darkShadow”, + * “RadioButton.light”, and + * “RadioButton.highlight”. + * + *

[A screen shot of the returned border] + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link RadioButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getRadioButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new RadioButtonBorder( + defaults.getColor("RadioButton.shadow"), + defaults.getColor("RadioButton.darkShadow"), + defaults.getColor("RadioButton.light"), + defaults.getColor("RadioButton.highlight")); + + /* While the inner border is shared between multiple buttons, we + * do not share the outer border because RadioButtonBorders, being + * ButtonBorders, store their border colors. We cannot guarantee + * that the colors (which come from UIDefaults) are unchanged + * between invocations of getButtonBorder. We could store the last + * colors, and share the button border if the colors are the same + * as in the last invocation, but it probably is not worth the + * effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing toggle buttons. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “ToggleButton.shadow”, + * “ToggleButton.darkShadow”, + * “ToggleButton.light”, and + * “ToggleButton.highlight”. + * + *

[A screen shot of the returned border] + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link ToggleButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getToggleButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new ToggleButtonBorder( + defaults.getColor("ToggleButton.shadow"), + defaults.getColor("ToggleButton.darkShadow"), + defaults.getColor("ToggleButton.light"), + defaults.getColor("ToggleButton.highlight")); + + /* While the inner border is shared between multiple buttons, we + * do not share the outer border because ToggleButtonBorders, being + * ButtonBorders, store their border colors. We cannot guarantee + * that the colors (which come from UIDefaults) are unchanged + * between invocations of getButtonBorder. We could store the last + * colors, and share the button border if the colors are the same + * as in the last invocation, but it probably is not worth the + * effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing a two-pixel thick separator line + * below menu bars. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “MenuBar.shadow” and + * “MenuBar.highlight”. + * + *

[A screen shot of a JMenuBar with this border] + * + * @return a {@link MenuBarBorder}. + * + * @see javax.swing.JMenuBar + */ + public static Border getMenuBarBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new MenuBarBorder(defaults.getColor("MenuBar.shadow"), + defaults.getColor("MenuBar.highlight")); + } + + + /** + * Returns a border for drawing a one-pixel thick border around + * split panes that are interrupted where the divider joins the + * border. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “SplitPane.darkShadow” and + * “SplitPane.highlight”. + * + *

[A screen shot for JSplitPane.HORIZONTAL_SPLIT] + * + *

[A screen shot for JSplitPane.VERTICAL_SPLIT] + * + * @return a {@link SplitPaneBorder}. + * + * @see javax.swing.JSplitPane + * @see #getSplitPaneDividerBorder() + */ + public static Border getSplitPaneBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new SplitPaneBorder(defaults.getColor("SplitPane.highlight"), + defaults.getColor("SplitPane.darkShadow")); + } + + + /** + * Returns a border for drawing a one-pixel thick border around + * the divider of split panes. + * + *

The colors of the edges that are adjacent to the child components + * of the JSplitPane are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “SplitPane.darkShadow” and + * “SplitPane.highlight”. The color of the + * other two edges is the background color of the divider. + * + *

+ + * + * @return an instance of SplitPaneDividerBorder, which is + * not a public API class of this package. + * + * @see javax.swing.JSplitPane + * @see javax.swing.plaf.basic.BasicSplitPaneDivider + * @see #getSplitPaneBorder() + * + * @since 1.3 + */ + public static Border getSplitPaneDividerBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new SplitPaneDividerBorder( + defaults.getColor("SplitPane.highlight"), + defaults.getColor("SplitPane.darkShadow")); + } + + + /** + * Returns a border for drawing a border around a text field + * that makes the field appear as etched into the surface. + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “TextField.shadow”, + * “TextField.darkShadow”, + * “TextField.light”, and + * “TextField.highlight”. + * + *

[A screen shot of a border returned by
+   * this method] + * + * @return an instance of {@link FieldBorder}. + * + * @see javax.swing.JTextField + * @see javax.swing.text.JTextComponent + */ + public static Border getTextFieldBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new FieldBorder( + defaults.getColor("TextField.shadow"), + defaults.getColor("TextField.darkShadow"), + defaults.getColor("TextField.light"), + defaults.getColor("TextField.highlight")); + } + + + /** + * Returns a two-pixel thick, green + * LineBorderUIResource. This is so ugly that look and + * feels better use different borders for their progress bars, or + * they will look really terrible. + * + *

[A screen shot of a border returned by this method] + */ + public static Border getProgressBarBorder() + { + /* There does not seem to exist a way to parametrize the color + * or thickness of the border through UIDefaults. + */ + return new BorderUIResource.LineBorderUIResource(Color.green, 2); + } + + + /** + * Returns a border that is composed of a raised bevel border and a + * one-pixel thick line border. + * + *

[A screen shot of a border returned by this method] + * + *

The colors of the border are retrieved from the + * UIDefaults of the currently active look and feel + * using the keys “InternalFrame.borderShadow”, + * “InternalFrame.borderDarkShadow”, + * “InternalFrame.borderLight”, + * “InternalFrame.borderHighlight”, and + * (for the inner one-pixel thick line) + * “InternalFrame.borderColor”. + */ + public static Border getInternalFrameBorder() + { + UIDefaults defaults; + Color shadow, darkShadow, highlight, lightHighlight, line; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + + shadow = defaults.getColor("InternalFrame.borderShadow"); + darkShadow = defaults.getColor("InternalFrame.borderDarkShadow"); + highlight = defaults.getColor("InternalFrame.borderLight"); + lightHighlight = defaults.getColor("InternalFrame.borderHighlight"); + line = defaults.getColor("InternalFrame.borderColor"); + + return new BorderUIResource.CompoundBorderUIResource( + /* outer border */ + new BorderUIResource.BevelBorderUIResource( + BevelBorder.RAISED, + (highlight != null) ? highlight : Color.lightGray, + (lightHighlight != null) ? lightHighlight : Color.white, + (darkShadow != null) ? darkShadow : Color.black, + (shadow != null) ? shadow : Color.gray), + + /* inner border */ + new BorderUIResource.LineBorderUIResource( + (line != null) ? line : Color.lightGray)); + } + + + /** + * Returns a shared MarginBorder. + */ + static Border getMarginBorder() // intentionally not public + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (sharedMarginBorder == null) + sharedMarginBorder = new MarginBorder(); + + return sharedMarginBorder; + } + + + /** + * A border whose appearance depends on the state of + * the enclosed button. + * + *

[A screen shot of this border] + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class ButtonBorder + extends AbstractBorder + implements Serializable, UIResource + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -157053874580739687L; + + + /** + * The color for drawing the shaded parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color shadow; + + + /** + * The color for drawing the dark shaded parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color darkShadow; + + + /** + * The color for drawing the highlighted parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color highlight; + + + /** + * The color for drawing the bright highlighted parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color lightHighlight; + + + /** + * Constructs a new border for drawing a button in the Basic + * look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public ButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.darkShadow = (darkShadow != null) ? darkShadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.lightGray; + this.lightHighlight = (lightHighlight != null) + ? lightHighlight + : Color.white; + } + + + /** + * Paints the ButtonBorder around a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + ButtonModel bmodel = null; + + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + BasicGraphicsUtils.drawBezel( + g, x, y, width, height, + /* pressed */ (bmodel != null) + && /* mouse button pressed */ bmodel.isPressed() + && /* mouse inside */ bmodel.isArmed(), + /* default */ (c instanceof JButton) + && ((JButton) c).isDefaultButton(), + shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + *

Although the thickness of the actually painted border + * depends on the state of the enclosed component, this + * measurement always returns the same amount of pixels. Indeed, + * it would be rather confusing if a button was appearing to + * change its size depending on whether it is pressed or not. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + *

Although the thickness of the actually painted border + * depends on the state of the enclosed component, this + * measurement always returns the same amount of pixels. Indeed, + * it would be rather confusing if a button was appearing to + * change its size depending on whether it is pressed or not. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Sun reference implementation. With + * Apple/Sun JDK 1.3.1 on MacOS X 10.1.5, the result is + * [3, 3, 3, 3]. With Sun JDK 1.4.1_01 on Linux/x86, the + * result is [2, 3, 3, 3]. We use the values from the 1.4.1_01 + * release. + */ + if (insets == null) + return new Insets(2, 3, 3, 3); + + insets.top = 2; + insets.bottom = insets.left = insets.right = 3; + return insets; + } + } + + + /** + * A border that makes its enclosed component appear as lowered + * into the surface. Typically used for text fields. + * + *

[A screen shot of this border] + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class FieldBorder + extends AbstractBorder + implements UIResource + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 949220756998454908L; + + + /** + * The color for drawing the outer half of the top and left + * edges. + */ + protected Color shadow; + + + /** + * The color for drawing the inner half of the top and left + * edges. + */ + protected Color darkShadow; + + + /** + * The color for drawing the inner half of the bottom and right + * edges. + */ + protected Color highlight; + + + /** + * The color for drawing the outer half of the bottom and right + * edges. + */ + protected Color lightHighlight; + + + /** + * Constructs a new border for drawing a text field in the Basic + * look and feel. + * + * @param shadow the color for drawing the outer half + * of the top and left edges. + * + * @param darkShadow the color for drawing the inner half + * of the top and left edges. + * + * @param highlight the color for drawing the inner half + * of the bottom and right edges. + * + * @param lightHighlight the color for drawing the outer half + * of the bottom and right edges. + */ + public FieldBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.darkShadow = (darkShadow != null) ? darkShadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.lightGray; + this.lightHighlight = (lightHighlight != null) + ? lightHighlight : Color.white; + } + + + /** + * Paints the FieldBorder around a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * If c is an instance of {@link + * javax.swing.text.JTextComponent}, its margin is + * added to the border size. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param c the component whose border is to be measured. + * If c is an instance of {@link + * javax.swing.text.JTextComponent}, its margin is + * added to the border size. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + if (insets == null) + insets = new Insets(2, 2, 2, 2); + else + insets.top = insets.left = insets.bottom = insets.right = 2; + + if (c instanceof JTextComponent) + { + Insets margin = ((JTextComponent) c).getMargin(); + insets.top += margin.top; + insets.left += margin.left; + insets.bottom += margin.bottom; + insets.right += margin.right; + } + + return insets; + } + } + + + /** + * An invisible, but spacing border whose margin is determined + * by calling the getMargin() method of the enclosed + * component. If the enclosed component has no such method, + * this border will not occupy any space. + * + *

[An illustration that shows how MarginBorder
+   * determines its borders] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MarginBorder + extends AbstractBorder + implements Serializable, UIResource + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3035848353448896090L; + + + /** + * Constructs a new MarginBorder. + */ + public MarginBorder() + { + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, right, + * top and bottom fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + + /** + * Determines the insets of this border by calling the + * getMargin() method of the enclosed component. The + * resulting margin will be stored into the the left, + * right, top and bottom + * fields of the passed insets parameter. + * + *

Unfortunately, getMargin() is not a method of + * {@link javax.swing.JComponent} or some other common superclass + * of things with margins. While reflection could be used to + * determine the existence of this method, this would be slow on + * many virtual machines. Therefore, the current implementation + * knows about {@link javax.swing.AbstractButton#getMargin()}, + * {@link javax.swing.JPopupMenu#getMargin()}, {@link + * javax.swing.JToolBar#getMargin()}, and {@link + * javax.swing.text.JTextComponent}. If c is an + * instance of a known class, the respective + * getMargin() method is called to determine the + * correct margin. Otherwise, a zero-width margin is returned. + * + * @param c the component whose border is to be measured. + * + * @return the same object that was passed for insets, + * but with changed fields. + */ + public Insets getBorderInsets(Component c, Insets insets) + { + Insets margin = null; + + /* This is terrible object-oriented design. See the above Javadoc + * for an excuse. + */ + if (c instanceof AbstractButton) + margin = ((AbstractButton) c).getMargin(); + else if (c instanceof JPopupMenu) + margin = ((JPopupMenu) c).getMargin(); + else if (c instanceof JToolBar) + margin = ((JToolBar) c).getMargin(); + else if (c instanceof JTextComponent) + margin = ((JTextComponent) c).getMargin(); + + if (margin == null) + insets.top = insets.left = insets.bottom = insets.right = 0; + else + { + insets.top = margin.top; + insets.left = margin.left; + insets.bottom = margin.bottom; + insets.right = margin.right; + } + + return insets; + } + } + + + /** + * A border for drawing a separator line below JMenuBar. + * + *

[A screen shot of a JMenuBar with this border] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MenuBarBorder + extends AbstractBorder + implements UIResource + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -6909056571935227506L; + + + /** + * The shadow color, which is used for the upper line of the + * two-pixel thick bottom edge. + */ + private Color shadow; + + + /** + * The highlight color, which is used for the lower line of the + * two-pixel thick bottom edge. + */ + private Color highlight; + + + /** + * Constructs a new MenuBarBorder for drawing a JMenuBar in + * the Basic look and feel. + * + *

[A screen shot of a JMenuBar with this
+     * border] + * + * @param shadow the shadow color, which is used for the upper + * line of the two-pixel thick bottom edge. + * + * @param highlight the shadow color, which is used for the lower + * line of the two-pixel thick bottom edge. + */ + public MenuBarBorder(Color shadow, Color highlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.highlight = (highlight != null) ? highlight : Color.white; + } + + + /** + * Paints the MenuBarBorder around a given component. + * + * @param c the component whose border is to be painted, usually + * an instance of {@link javax.swing.JMenuBar}. + * + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Color oldColor; + + /* To understand this code, it might be helpful to look at the + * image "BasicBorders.MenuBarBorder-1.png" that is included + * with the JavaDoc. It is located in the "doc-files" + * subdirectory. + */ + oldColor = g.getColor(); + y = y + height - 2; + try + { + g.setColor(shadow); + g.drawLine(x, y, x + width - 2, y); + g.drawLine(x, y + 1, x, y + 1); + g.drawLine(x + width - 2, y + 1, x + width - 2, y + 1); + + g.setColor(highlight); + g.drawLine(x + 1, y + 1, x + width - 3, y + 1); + g.drawLine(x + width - 1, y, x + width - 1, y + 1); + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [0,0,2,0], + * which was expected from looking at the screen shot. + */ + if (insets == null) + return new Insets(0, 0, 2, 0); + + insets.left = insets.right = insets.top = 0; + insets.bottom = 2; + return insets; + } + } + + + /** + * A border for drawing radio buttons in the Basic look and feel. + * + *

[A screen shot of this border] + * + *

Note about the screen shot: Normally, the + * borderPainted property is false for + * JRadioButtons. For this screen shot, it has been set to + * true so the borders get drawn. Also, a + * concretization of the Basic look and would typically provide + * icons for the various states of radio buttons. + * + *

Note that the focus rectangle is invisible If the radio button + * is currently selected. While it might be debatable whether this + * makes a lot of sense, this behavior can be observed in the Sun + * reference implementation (in JDK 1.3.1 and 1.4.1). The Classpath + * implementation tries to exactly replicate the JDK appearance. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class RadioButtonBorder + extends ButtonBorder + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 1596945751743747369L; + + + /** + * Constructs a new border for drawing a JRadioButton in + * the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public RadioButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* The superclass ButtonBorder substitutes null arguments + * with fallback colors. + */ + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the RadioButtonBorder around a given component. + * + *

The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + AbstractButton button = null; + ButtonModel bmodel = null; + boolean lowered = false; + boolean focused = false; + + if (c instanceof AbstractButton) + { + button = (AbstractButton) c; + bmodel = button.getModel(); + } + + if (bmodel != null) + { + lowered = button.isSelected() + || (/* mouse inside */ bmodel.isArmed() && bmodel.isPressed()); + focused = button.hasFocus() && button.isFocusPainted(); + } + + if (lowered) + BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height, + shadow, darkShadow, + highlight, lightHighlight); + else + BasicGraphicsUtils.drawBezel(g, x, y, width, height, + /* isPressed */ false, + /* isPefault */ focused, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2]. + */ + if (insets == null) + return new Insets(2, 2, 2, 2); + + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + } + + + /** + * A one-pixel thick border for rollover buttons, for example in + * tool bars. + * + * @since 1.4 + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class RolloverButtonBorder + extends ButtonBorder + { + /** + * Determined using the serialver tool + * of Sun JDK 1.4.1_01 on GNU/Linux 2.4.20 for x86. + */ + static final long serialVersionUID = 1976364864896996846L; + + + /** + * Constructs a new border for drawing a roll-over button + * in the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public RolloverButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the border around a rollover button. If c + * is not an {@link javax.swing.AbstractButton} whose model + * returns true for {@link + * javax.swing.ButtonModel#isRollover}, nothing gets painted at + * all. + * + * @param c the button whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + ButtonModel bmodel = null; + boolean drawPressed; + Color oldColor = g.getColor(); + int x2, y2; + + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + /* Draw nothing if c is not a rollover button. */ + if ((bmodel == null) || !bmodel.isRollover()) + return; + + /* Draw nothing if the mouse is pressed, but outside the button. */ + if (bmodel.isPressed() && !bmodel.isArmed()) + return; + + drawPressed = bmodel.isSelected() || bmodel.isPressed(); + x2 = x + width - 1; + y2 = y + height - 1; + + try + { + g.setColor(drawPressed ? shadow : lightHighlight); + g.drawLine(x, y, x2 - 1, y); // top edge + g.drawLine(x, y + 1, x, y2 - 1); // left edge + + g.setColor(drawPressed ? lightHighlight : shadow); + g.drawLine(x, y2, x2, y2); // bottom edge + g.drawLine(x2, y, x2, y2 - 1); // right edge + } + finally + { + g.setColor(oldColor); + } + } + } + + + /** + * A border for JSplitPanes in the Basic look and feel. The divider + * in the middle of the JSplitPane has its own border class, of which + * an instance can be obtained with {@link #getSplitPaneDividerBorder()}. + * + *

[A screen shot for JSplitPane.HORIZONTAL_SPLIT] + * + *

[A screen shot for JSplitPane.VERTICAL_SPLIT] + * + *

In contrast to the other borders of the Basic look and feel, + * this class is not serializable. While this might be unintended, + * GNU Classpath follows the specification in order to be fully + * compatible with the Sun reference implementation. + * + *

In the Sun JDK, the bottom edge of the divider also gets + * painted if the orientation of the enclosed JSplitPane is + * JSplitPane.VERTICAL_SPLIT (at least in versions + * 1.3.1 and 1.4.1). GNU Classpath does not replicate this bug. A + * report has been filed with Sun (bug ID 4885629). + * + *

Note that the bottom left pixel of the border has a different + * color depending on the orientation of the enclosed JSplitPane. + * Although this is visually inconsistent, Classpath replicates the + * appearance of the Sun reference implementation. A bug report has + * been filed with Sun (review ID 188774). + * + * @see #getSplitPaneBorder() + * @see #getSplitPaneDividerBorder() + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + 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)}. + */ + 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)}. + */ + 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)}. + */ + 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)}. + */ + private static final int SUPPRESS_RIGHT = 8; + + + /** + * The color for drawing the bottom and right edges of the border. + */ + protected Color highlight; + + + /** + * The color for drawing the top and left edges of the border. + */ + protected Color shadow; + + + /** + * Constructs a new border for drawing a JSplitPane in the Basic + * look and feel. The divider in the middle of the JSplitPane has + * its own border class, SplitPaneDividerBorder. + * + * @param shadow the shadow color. + * @param highlight the highlight color. + */ + public SplitPaneBorder(Color highlight, Color shadow) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.white; + } + + + /** + * Paints the border around a JSplitPane. + * + *

[A screen shot for JSplitPane.HORIZONTAL_SPLIT] + * + *

[A screen shot for JSplitPane.VERTICAL_SPLIT] + * + * @param c the JSplitPane whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + JSplitPane splitPane; + Component content; + + if (!(c instanceof JSplitPane)) + return; + + splitPane = (JSplitPane) c; + switch (splitPane.getOrientation()) + { + case JSplitPane.HORIZONTAL_SPLIT: + if ((content = splitPane.getLeftComponent()) != null) + paintRect(g, SUPPRESS_RIGHT, true, x, y, content.getBounds()); + if ((content = splitPane.getRightComponent()) != null) + paintRect(g, SUPPRESS_LEFT, true, x, y, content.getBounds()); + break; + + case JSplitPane.VERTICAL_SPLIT: + if ((content = splitPane.getTopComponent()) != null) + paintRect(g, SUPPRESS_BOTTOM, false, x, y, content.getBounds()); + if ((content = splitPane.getBottomComponent()) != null) + paintRect(g, SUPPRESS_TOP, false, x, y, content.getBounds()); + break; + } + } + + + /** + * Paints a border around a child of a JSplitPane, + * omitting some of the edges. + * + * @param g the graphics for painting. + * + * @param suppress a bit mask indicating the set of suppressed + * edges, for example SUPPRESS_TOP | SUPPRESS_RIGHT. + * + * @param x the x coordinate of the SplitPaneBorder. + * + * @param y the y coordinate of the SplitPaneBorder. + * + * @param shadeBottomLeftPixel true to paint the + * bottom left pixel in the shadow color, + * false for the highlight color. The Basic + * look and feel uses the highlight color for the bottom + * left pixel of the border of a JSplitPane whose + * orientation is VERTICAL_SPLIT, and the shadow color + * otherwise. While this might be a strange distinction, + * Classpath tries to look identical to the reference + * implementation. A bug report has been filed with Sun; + * its review ID is 188774. We currently replicate the + * Sun behavior. + * + * @param rect the bounds of the child of JSplitPane whose + * border is to be painted. + */ + private void paintRect(Graphics g, int suppress, + boolean shadeBottomLeftPixel, + int x, int y, + Rectangle rect) + { + if (rect == null) + return; + + /* On each edge, the border exceeds the enclosed child by one + * pixel. See the image "BasicBorders.SplitPaneBorder-1.png" in + * the directory "doc-files". + */ + x += rect.x - 1; + y += rect.y - 1; + int right = x + rect.width + 1; + int bottom = y + rect.height + 1; + + Color oldColor = g.getColor(); + try + { + g.setColor(shadow); + if ((suppress & SUPPRESS_TOP) == 0) + g.drawLine(x, y, right, y); + if ((suppress & SUPPRESS_LEFT) == 0) + g.drawLine(x, y, x, bottom); + else + g.drawLine(x, bottom, x, bottom); // one pixel + + g.setColor(highlight); + if ((suppress & SUPPRESS_BOTTOM) == 0) + g.drawLine(x + (shadeBottomLeftPixel ? 1 : 0), bottom, right, bottom); + else if (!shadeBottomLeftPixel) + g.drawLine(x, bottom, x, bottom); // one pixel + + if ((suppress & SUPPRESS_RIGHT) == 0) + g.drawLine(right, y, right, bottom); + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured, usually + * an instance of {@link javax.swing.JSplitPane}. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(1, 1, 1, 1); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return false because this border does not + * paint over the pixels where the divider joins + * the border. + */ + public boolean isBorderOpaque() + { + /* Strangely, the Sun implementation (tested with JDK 1.3.1 and + * 1.4.1_01) seems to always return true. It could be a bug, + * but without knowing the details of their implementation, it is + * hard to decide. + */ + return false; + } + } + + + /** + * A border for the divider inside a JSplitPane. + * + *

[A screen shot of this border] + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + private static class SplitPaneDividerBorder + implements Border, UIResource, Serializable + { + /** + * The highlight color, which is drawn on the left or top edge + * depending on the orientation of the JSplitPanel. + */ + protected Color highlight; + + + /** + * The highlight color, which is drawn on the right or bottom edge + * depending on the orientation of the JSplitPanel. + */ + protected Color shadow; + + + /** + * Constructs a new border for drawing the divider of a JSplitPane + * in the Basic look and feel. The outer parts of the JSplitPane have + * their own border class, SplitPaneBorder. + * + * @param shadow the shadow color. + * @param highlight the highlight color. + */ + public SplitPaneDividerBorder(Color highlight, Color shadow) + { + this.highlight = (highlight != null) ? highlight : Color.white; + this.shadow = (shadow != null) ? shadow : Color.black; + } + + + /** + * Paints the border around the divider of a JSplitPane. + * + *

[A picture that shows which pixels
+     * get painted in what color] + * + * @param c the JSplitPane whose divider’s border + * is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Color oldColor, dcol; + int x2, y2; + JSplitPane sp; + + sp = getSplitPane(c); + if (sp == null) + return; + + x2 = x + width - 1; + y2 = y + height - 1; + oldColor = g.getColor(); + dcol = c.getBackground(); + try + { + switch (sp.getOrientation()) + { + case JSplitPane.HORIZONTAL_SPLIT: + g.setColor(dcol); + g.drawLine(x + 1, y, x2 - 1, y); + g.drawLine(x + 1, y2, x2 - 1, y2); + g.setColor(sp.getLeftComponent() != null ? highlight : dcol); + g.drawLine(x, y, x, y2); + g.setColor(sp.getRightComponent() != null ? shadow : dcol); + g.drawLine(x2, y, x2, y2); + break; + + case JSplitPane.VERTICAL_SPLIT: + g.setColor(dcol); + g.drawLine(x, y + 1, x, y2 - 1); + g.drawLine(x2, y + 1, x2, y2 - 1); + g.setColor(sp.getTopComponent() != null ? highlight : dcol); + g.drawLine(x, y, x2, y); + g.setColor(sp.getBottomComponent() != null ? shadow : dcol); + g.drawLine(x, y2, x2, y2); + break; + } + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured, usually + * an instance of {@link javax.swing.JSplitPane}. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(1, 1, 1, 1); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return true if both highlight and shadow + * color are fully opaque. + */ + public boolean isBorderOpaque() + { + return (highlight.getAlpha() == 255) && (shadow.getAlpha() == 255); + } + + + /** + * Determines the JSplitPane whose divider is being painted. + * + * @param c an instance of BasicSplitPaneDivider. + * + * @return a JSplitPane, or null if + * c is not an instance of {@link + * javax.swing.plaf.basic.BasicSplitPaneDivider}. + */ + private JSplitPane getSplitPane(Component c) + { + if (c instanceof BasicSplitPaneDivider) + return (((BasicSplitPaneDivider) c).getBasicSplitPaneUI()) + .getSplitPane(); + else + return null; + } + } + + + /** + * A border for toggle buttons in the Basic look and feel. + * + *

[A screen shot of this border] + * + *

The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class ToggleButtonBorder + extends ButtonBorder + { + /** + * Determined using the serialver tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3528666548001058394L; + + + /** + * Constructs a new border for drawing a JToggleButton in + * the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public ToggleButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* The superclass ButtonBorder substitutes null arguments + * with fallback colors. + */ + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the ToggleButtonBorder around a given component. + * + *

The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the 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. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + /* The author of this code tried various variants for setting + * the state of the enclosed JToggleButton, but it seems that + * the drawn border is always identical. Weird, because this + * means that the user does not see whether the JToggleButton + * is selected or not. + */ + BasicGraphicsUtils.drawBezel(g, x, y, width, height, + /* pressed */ false, + /* default */ false, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the left, + * right, top and + * bottom fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for insets. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2]. + */ + if (insets == null) + return new Insets(2, 2, 2, 2); + + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java new file mode 100644 index 0000000..5349f52 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java @@ -0,0 +1,231 @@ +/* BasicButtonListener.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JComponent; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +public class BasicButtonListener + implements MouseListener, MouseMotionListener, FocusListener, + ChangeListener, PropertyChangeListener +{ + public BasicButtonListener(AbstractButton b) + { + // Do nothing here. + } + + public void propertyChange(PropertyChangeEvent e) + { + } + + protected void checkOpacity(AbstractButton b) + { + } + + public void focusGained(FocusEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + if (button.isFocusPainted()) + button.repaint(); + } + } + + public void focusLost(FocusEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + if (button.isFocusPainted()) + button.repaint(); + } + } + + public void installKeyboardActions(JComponent c) + { + c.getActionMap().put("pressed", + new AbstractAction() + { + public void actionPerformed(ActionEvent e) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + // It is important that these transitions happen in this order. + model.setArmed(true); + model.setPressed(true); + } + }); + + c.getActionMap().put("released", + new AbstractAction() + { + public void actionPerformed(ActionEvent e) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + // It is important that these transitions happen in this order. + model.setPressed(false); + model.setArmed(false); + } + }); + } + + public void uninstallKeyboardActions(JComponent c) + { + c.getActionMap().put("pressed", null); + c.getActionMap().put("released", null); + } + + public void stateChanged(ChangeEvent e) + { + } + + public void mouseMoved(MouseEvent e) + { + } + + public void mouseDragged(MouseEvent e) + { + } + + public void mouseClicked(MouseEvent e) + { + } + + /** + * Accept a mouse press event and arm the button. + * + * @param e The mouse press event to accept + */ + public void mousePressed(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (e.getButton() == MouseEvent.BUTTON1) + { + // It is important that these transitions happen in this order. + model.setArmed(true); + model.setPressed(true); + } + } + } + + /** + * Accept a mouse release event and set the button's + * "pressed" property to true, if the model + * is armed. If the model is not armed, ignore the event. + * + * @param e The mouse release event to accept + */ + public void mouseReleased(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (e.getButton() == MouseEvent.BUTTON1) + { + // It is important that these transitions happen in this order. + model.setPressed(false); + model.setArmed(false); + } + } + } + + /** + * Accept a mouse enter event and set the button's "rollover" property to + * true, if the button's "rolloverEnabled" property is + * true. If the button is currently armed and the mouse + * button is not held down, this enter event will also disarm the model. + * + * @param e The mouse enter event to accept + */ + public void mouseEntered(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (button.isRolloverEnabled()) + model.setRollover(true); + + if (model.isPressed() + && (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0) + model.setArmed(true); + else + model.setArmed(false); + } + } + + /** + * Accept a mouse exit event and set the button's model's "rollover" + * property to false, if it's "rolloverEnabled" property is + * true. Also disarm the button. + * + * @param e The mouse exit event to accept + */ + public void mouseExited(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (button.isRolloverEnabled()) + model.setRollover(false); + model.setArmed(false); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java new file mode 100644 index 0000000..d893c5d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java @@ -0,0 +1,421 @@ +/* BasicButtonUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ButtonUI; +import javax.swing.plaf.ComponentUI; + +public class BasicButtonUI extends ButtonUI +{ + /** + * A constant used to pad out elements in the button's layout and + * preferred size calculations. + */ + protected int defaultTextIconGap = 4; + + /** + * A constant added to the defaultTextIconGap to adjust the text + * within this particular button. + */ + protected int defaultTextShiftOffset = 0; + + 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 + * + * @return A new UI capable of drawing the component + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicButtonUI(); + } + + public int getDefaultTextIconGap(AbstractButton b) + { + return defaultTextIconGap; + } + + protected void clearTextShiftOffset() + { + textShiftOffset = 0; + } + + protected int getTextShiftOffset() + { + return textShiftOffset; + } + + protected void setTextShiftOffset() + { + textShiftOffset = defaultTextShiftOffset; + } + + /** + * Returns the prefix for the UI defaults property for this UI class. + * This is 'Button' for this class. + * + * @return the prefix for the UI defaults property + */ + protected String getPropertyPrefix() + { + return "Button"; + } + + 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")); + b.setInputMap(JComponent.WHEN_FOCUSED, + (InputMap) defaults.get(prefix + ".focusInputMap")); + b.setOpaque(true); + } + + protected void uninstallDefaults(AbstractButton b) + { + b.setForeground(null); + b.setBackground(null); + b.setBorder(null); + b.setIconTextGap(defaultTextIconGap); + b.setMargin(null); + } + + protected BasicButtonListener listener; + + protected BasicButtonListener createButtonListener(AbstractButton b) + { + return new BasicButtonListener(b); + } + + protected void installListeners(AbstractButton b) + { + listener = createButtonListener(b); + b.addChangeListener(listener); + b.addPropertyChangeListener(listener); + b.addFocusListener(listener); + b.addMouseListener(listener); + b.addMouseMotionListener(listener); + } + + protected void uninstallListeners(AbstractButton b) + { + b.removeChangeListener(listener); + b.removePropertyChangeListener(listener); + b.removeFocusListener(listener); + b.removeMouseListener(listener); + b.removeMouseMotionListener(listener); + } + + protected void installKeyboardActions(AbstractButton b) + { + listener.installKeyboardActions(b); + } + + protected void uninstallKeyboardActions(AbstractButton b) + { + listener.uninstallKeyboardActions(b); + } + + /** + * Install the BasicButtonUI as the UI for a particular component. + * This means registering all the UI's listeners with the component, + * and setting any properties of the button which are particular to + * this look and feel. + * + * @param c The component to install the UI into + */ + public void installUI(final JComponent c) + { + super.installUI(c); + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + installDefaults(b); + installListeners(b); + installKeyboardActions(b); + } + } + + /** + * Calculate the preferred size of this component, by delegating to + * {@link BasicGraphicsUtils#getPreferredButtonSize}. + * + * @param c The component to measure + * + * @return The preferred dimensions of the component + */ + public Dimension getPreferredSize(JComponent c) + { + AbstractButton b = (AbstractButton)c; + Dimension d = + BasicGraphicsUtils.getPreferredButtonSize + (b, defaultTextIconGap + defaultTextShiftOffset); + return d; + } + + private static Icon currentIcon(AbstractButton b) + { + Icon i = b.getIcon(); + ButtonModel model = b.getModel(); + + if (model.isPressed() && b.getPressedIcon() != null) + i = b.getPressedIcon(); + + else if (model.isRollover()) + { + if (b.isSelected() && b.getRolloverSelectedIcon() != null) + i = b.getRolloverSelectedIcon(); + else if (b.getRolloverIcon() != null) + i = b.getRolloverIcon(); + } + + else if (b.isSelected()) + { + if (b.isEnabled() && b.getSelectedIcon() != null) + i = b.getSelectedIcon(); + else if (b.getDisabledSelectedIcon() != null) + i = b.getDisabledSelectedIcon(); + } + + else if (! b.isEnabled() && b.getDisabledIcon() != null) + i = b.getDisabledIcon(); + + return i; + } + + /** + * 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); + + SwingUtilities.calculateInnerArea(b, vr); + 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); + else + paintButtonNormal(g, vr, c); + + paintIcon(g, c, ir); + if (text != null) + paintText(g, b, tr, text); + paintFocus(g, b, vr, tr, ir); + } + + /** + * Paint any focus decoration this {@link JComponent} might have. The + * component, which in this case will be an {@link AbstractButton}, + * should only have focus decoration painted if it has the focus, and its + * "focusPainted" property is true. + * + * @param g Graphics context to paint with + * @param b Button to paint the focus of + * @param vr Visible rectangle, the area in which to paint + * @param tr Text rectangle, contained in visible rectangle + * @param ir Icon rectangle, contained in visible rectangle + * + * @see AbstractButton#isFocusPainted() + * @see JComponent#hasFocus() + */ + protected void paintFocus(Graphics g, AbstractButton b, Rectangle vr, + Rectangle tr, Rectangle ir) + { + if (b.hasFocus() && b.isFocusPainted()) + { + Color saved_color = g.getColor(); + g.setColor(focusColor); + Rectangle focusRect = ir.union(tr); + g.drawRect(focusRect.x, focusRect.y, + focusRect.width, focusRect.height); + g.setColor(saved_color); + } + } + + /** + * Paint the icon for this component. Depending on the state of the + * component and the availability of the button's various icon + * properties, this might mean painting one of several different icons. + * + * @param g Graphics context to paint with + * @param c Component to paint the icon of + * @param iconRect Rectangle in which the icon should be painted + */ + protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) + { + AbstractButton b = (AbstractButton) c; + Icon i = currentIcon(b); + + if (i != null) + i.paintIcon(c, g, iconRect.x, iconRect.y); + } + + /** + * Paints the background area of an {@link AbstractButton} in the pressed + * state. This means filling the supplied area with the {@link + * pressedBackgroundColor}. + * + * @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()) + { + g.setColor(b.getBackground()); + g.fillRect(area.x, area.y, area.width, area.height); + } + } + + /** + * Paints the "text" property of an {@link AbstractButton}, using the + * {@link textColor} color. + * + * @param g The graphics context to paint with + * @param c The component to paint the state of + * @param textRect The area in which to paint the text + * @param text The text to paint + */ + protected void paintText(Graphics g, JComponent c, Rectangle textRect, + String text) + { + paintText(g, (AbstractButton) c, textRect, text); + } + + /** + * Paints the "text" property of an {@link AbstractButton}, using the + * {@link textColor} color. + * + * @param g The graphics context to paint with + * @param b The button to paint the state of + * @param textRect The area in which to paint the text + * @param text The text to paint + * + * @since 1.4 + */ + protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, + String text) + { + 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(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); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java new file mode 100644 index 0000000..da11898 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -0,0 +1,104 @@ +/* BasicCheckBoxMenuItemUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +/** + * DOCUMENT ME! + */ +public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI +{ + /** + * Factory method to create a BasicCheckBoxMenuItemUI for the given {@link + * JComponent}, which should be a JCheckBoxMenuItem + * + * @param c The {@link JComponent} a UI is being created for. + * + * @return A BasicCheckBoxMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicCheckBoxMenuItemUI(); + } + + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ + protected String getPropertyPrefix() + { + return null; + } + + /** + * 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! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(JMenuItem item, MouseEvent e, + MenuElement[] path, + MenuSelectionManager manager) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java new file mode 100644 index 0000000..e316732 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java @@ -0,0 +1,73 @@ +/* BasicCheckBoxUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +public class BasicCheckBoxUI extends BasicRadioButtonUI +{ + + public static ComponentUI createUI(final JComponent c) { + return new BasicCheckBoxUI(); + } + + public Icon getDefaultIcon() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + return defaults.getIcon("CheckBox.icon"); + } + + public void installUI(final JComponent c) { + super.installUI(c); + } + + // Overridden to change method access. + public String getPropertyPrefix() + { + return super.getPropertyPrefix(); + } +} + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java new file mode 100644 index 0000000..4e6d381 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -0,0 +1,339 @@ +/* BasicColorChooserUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +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.colorchooser.AbstractColorChooserPanel; +import javax.swing.colorchooser.ColorChooserComponentFactory; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ColorChooserUI; +import javax.swing.plaf.ComponentUI; + +/** + * This is the UI Class for the JColorChooser in the Basic Look and Feel. + */ +public class BasicColorChooserUI extends ColorChooserUI +{ + /** + * This helper class handles property changes from the JColorChooser. + */ + public class PropertyHandler implements PropertyChangeListener + { + /** + * This method is called when any of the properties of the JColorChooser + * change. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName() == JColorChooser.CHOOSER_PANELS_PROPERTY) + makeTabs(chooser.getChooserPanels()); + else if (e.getPropertyName() == JColorChooser.PREVIEW_PANEL_PROPERTY) + updatePreviewPanel(chooser.getPreviewPanel()); + else if (e.getPropertyName() == JColorChooser.SELECTION_MODEL_PROPERTY) + ((AbstractColorChooserPanel) pane.getSelectedComponent()) + .updateChooser(); + + chooser.repaint(); + } + } + + /** + * This is a helper class that listens to the Model of the JColorChooser for + * color change events so it can update the preview panel. + */ + private class PreviewListener implements ChangeListener + { + /** + * This method is called whenever the JColorChooser's color changes. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (pane != null) + { + AbstractColorChooserPanel panel = (AbstractColorChooserPanel) pane + .getSelectedComponent(); + if (panel != null) + panel.updateChooser(); + } + chooser.repaint(); + } + } + + /** + * This helper class listens to the JTabbedPane that is used for tab + * changes. + */ + private class TabPaneListener implements ChangeListener + { + /** + * This method is called whenever a different tab is selected in the + * JTabbedPane. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + // Need to do this because we don't update all the tabs when they're not + // visible, so they are not informed of new colors when they're hidden. + AbstractColorChooserPanel comp = (AbstractColorChooserPanel) pane + .getSelectedComponent(); + comp.updateChooser(); + } + } + + /** An array of default choosers to use in the JColorChooser. */ + protected AbstractColorChooserPanel[] defaultChoosers; + + /** The listener for the preview panel. */ + protected ChangeListener previewListener; + + /** The PropertyChangeListener for the JColorChooser. */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The JColorChooser. + * This is package-private to avoid an accessor method. + */ + JColorChooser chooser; + + /** The JTabbedPane that is used. */ + JTabbedPane pane; + + /** The Container that holds the preview panel. */ + private Container prevContainer; + + /** + * Creates a new BasicColorChooserUI object. + */ + public BasicColorChooserUI() + { + super(); + } + + /** + * This method creates a new UI Component for the given JComponent. + * + * @param c The JComponent to create an UI for. + * + * @return A new BasicColorChooserUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicColorChooserUI(); + } + + /** + * This method creates the default chooser panels for the JColorChooser. + * + * @return The default chooser panels. + */ + protected AbstractColorChooserPanel[] createDefaultChoosers() + { + return ColorChooserComponentFactory.getDefaultChooserPanels(); + } + + /** + * This method installs the UI Component for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JColorChooser) + { + chooser = (JColorChooser) c; + chooser.setLayout(new BorderLayout()); + + // Do this first, so we avoid doing work for property change events. + defaultChoosers = createDefaultChoosers(); + chooser.setChooserPanels(defaultChoosers); + pane = new JTabbedPane(); + + pane.addChangeListener(new ChangeListener() + { + public void stateChanged(ChangeEvent e) + { + pane.repaint(); + } + }); + + makeTabs(defaultChoosers); + + chooser.add(pane, BorderLayout.NORTH); + + installPreviewPanel(); + + installDefaults(); + installListeners(); + } + } + + /** + * This method adds tabs to the JTabbedPane for the chooserPanels defined in + * the JColorChooser. + * This is package-private to avoid an accessor method. + * + * @param panels The Panels that need tabs to be made for them. + */ + void makeTabs(AbstractColorChooserPanel[] panels) + { + pane.removeAll(); + for (int i = 0; i < panels.length; i++) + pane.addTab(panels[i].getDisplayName(), panels[i].getSmallDisplayIcon(), + panels[i]); + } + + /** + * This method uninstalls this UI for the given JComponent. + * + * @param c The JComponent that will have this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + + pane = null; + chooser = null; + } + + /** + * This method installs the preview panel for the JColorChooser. + */ + protected void installPreviewPanel() + { + updatePreviewPanel(ColorChooserComponentFactory.getPreviewPanel()); + } + + /** + * This is a helper method that swaps the existing preview panel with the + * given panel. + * This is package-private to avoid an accessor method. + * + * @param preview The new preview panel. + */ + void updatePreviewPanel(JComponent preview) + { + if (prevContainer == null) + { + prevContainer = new JPanel(); + prevContainer.setLayout(new BorderLayout()); + chooser.add(prevContainer, BorderLayout.CENTER); + } + prevContainer.removeAll(); + prevContainer.add(preview, BorderLayout.CENTER); + } + + /** + * This method installs the default properties given by the Basic Look and + * Feel. + */ + 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")); + } + + /** + * This method uninstalls the default properties given by the Basic Look and + * Feel. + */ + protected void uninstallDefaults() + { + chooser.setBackground(null); + chooser.setForeground(null); + chooser.setFont(null); + } + + /** + * This method installs any listeners required for this UI to function. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + previewListener = new PreviewListener(); + + chooser.addPropertyChangeListener(propertyChangeListener); + chooser.getSelectionModel().addChangeListener(previewListener); + + pane.addChangeListener(new TabPaneListener()); + } + + /** + * This method creates the PropertyChangeListener used for listening to the + * JColorChooser. + * + * @return A PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyHandler(); + } + + /** + * This method uninstalls any listeners that were previously installed by + * the UI. + */ + protected void uninstallListeners() + { + chooser.removePropertyChangeListener(propertyChangeListener); + chooser.getSelectionModel().removeChangeListener(previewListener); + + previewListener = null; + propertyChangeListener = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java new file mode 100644 index 0000000..04296df --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java @@ -0,0 +1,170 @@ +/* BasicComboBoxEditor.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +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. + * + * @author Olga Rodimina + */ +public class BasicComboBoxEditor extends Object implements ComboBoxEditor, + FocusListener +{ + protected JTextField editor; + + /** + * Creates a new BasicComboBoxEditor object. + */ + public BasicComboBoxEditor() + { + editor = new JTextField(); + editor.setBorder(new EmptyBorder(1, 1, 1, 1)); + } + + /** + * This method returns textfield that will be used by the combo box to + * display/edit currently selected item in the combo box. + * + * @return textfield that will be used by the combo box to display/edit + * currently selected item + */ + public Component getEditorComponent() + { + return editor; + } + + /** + * Sets item that should be edited when any editing operation is performed + * by the user. The value is always equal to the currently selected value + * in the combo box. Thus whenever a different value is selected from the + * combo box list then this method should be called to change editing + * item to the new selected item. + * + * @param item item that is currently selected in the combo box + */ + public void setItem(Object item) + { + editor.setText(item.toString()); + } + + /** + * This method returns item that is currently editable. + * + * @return item in the combo box that is currently editable + */ + public Object getItem() + { + return editor.getText(); + } + + public void selectAll() + { + editor.selectAll(); + } + + /** + * This method is called when textfield gains focus. This will enable + * editing of the selected item. + * + * @param e the FocusEvent describing change in focus. + */ + public void focusGained(FocusEvent e) + { + // FIXME: Need to implement + } + + /** + * This method is called when textfield loses focus. If during this time any + * editting operation was performed by the user, then it will be cancelled + * and selected item will not be changed. + * + * @param e the FocusEvent describing change in focus + */ + public void focusLost(FocusEvent e) + { + // FIXME: Need to implement + } + + /** + * This method adds actionListener to the editor. 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. + * + * @param l the ActionListener responsible for changing selected item of the + * combo box when it is editted by the user. + */ + public void addActionListener(ActionListener l) + { + // FIXME: Need to implement + } + + /** + * This method removes actionListener from the textfield. + * + * @param l the ActionListener to remove from the textfield. + */ + public void removeActionListener(ActionListener l) + { + // FIXME: Need to implement + } + + public static class UIResource extends BasicComboBoxEditor + implements javax.swing.plaf.UIResource + { + /** + * Creates a new UIResource object. + */ + public UIResource() + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java new file mode 100644 index 0000000..e4fbb83 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java @@ -0,0 +1,142 @@ +/* BasicComboBoxRenderer.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.io.Serializable; + +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.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * This class is renderer for the combo box. + * + * @author Olga Rodimina + */ +public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, + Serializable +{ + /** + * This border is used whenever renderer doesn't have a focus. + */ + protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0); + + /** + * Creates a new BasicComboBoxRenderer object. + */ + public BasicComboBoxRenderer() + { + setHorizontalAlignment(SwingConstants.LEFT); + } + + /** + * Returns preferredSize of the renderer + * + * @return preferredSize of the renderer + */ + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + /** + * getListCellRendererComponent + * + * @param list List of items for which to the background and foreground + * colors + * @param value object that should be rendered in the cell + * @param index index of the cell in the list of items. + * @param isSelected draw cell highlighted if isSelected is true + * @param cellHasFocus draw focus rectangle around cell if the cell has + * focus + * + * @return Component that will be used to draw the desired cell. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, + boolean cellHasFocus) + { + String s = value.toString(); + setText(s); + setOpaque(true); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + if (isSelected) + { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else + { + 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; + } + + public static class UIResource extends BasicComboBoxRenderer + implements javax.swing.plaf.UIResource + { + /** + * Creates a new UIResource object. + */ + public UIResource() + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java new file mode 100644 index 0000000..68e18a6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -0,0 +1,1243 @@ +/* BasicComboBoxUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.accessibility.Accessible; +import javax.swing.CellRendererPane; +import javax.swing.ComboBoxEditor; +import javax.swing.ComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegate for JComboBox + * + * @author Olga Rodimina + * @author Robert Schuster + */ +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 + */ + protected JButton arrowButton; + + /** + * The combo box for which this UI delegate is for + */ + 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 + */ + protected Component editor; + + /** + * Listener listening to focus events occuring in the JComboBox + */ + protected FocusListener focusListener; + + /** + * tells whether JComboBox currently has focus + */ + protected boolean hasFocus; + + /** + * Listener listening to item events fired by the JComboBox + */ + protected ItemListener itemListener; + + /** + * KeyListener listening to key events that occur while JComboBox has focus + */ + protected KeyListener keyListener; + + /** + * MouseListener listening to mouse events occuring in the combo box + */ + 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 + */ + protected JList listBox; + + /** + * ListDataListener listening to JComboBox model + */ + protected ListDataListener listDataListener; + + /** + * Popup list containing combo box's menu items + */ + protected ComboPopup popup; + protected KeyListener popupKeyListener; + protected MouseListener popupMouseListener; + protected MouseMotionListener popupMouseMotionListener; + + /** + * Listener listening to changes in the bound properties of JComboBox + */ + protected PropertyChangeListener propertyChangeListener; + + /** + * Colors that are used to render selected item in the combo box. + */ + private Color shadow; + private Color darkShadow; + private Color highlight; + private Color lightHighlight; + + /* 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; + + // FIXME: This fields aren't used anywhere at this moment. + protected Dimension cachedMinimumSize; + protected CellRendererPane currentValuePane; + protected boolean isMinimumSizeDirty; + + /** + * Creates a new BasicComboBoxUI object. + */ + public BasicComboBoxUI() + { + } + + /** + * Factory method to create a BasicComboBoxUI 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}. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicComboBoxUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install a UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JComboBox) + { + comboBox = (JComboBox) c; + comboBox.setOpaque(true); + comboBox.setLayout(createLayoutManager()); + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * This method uninstalls the UI. + * + * @param c The JComponent that is having this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + comboBox = null; + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this {@link JComboBox}. + */ + 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"); + } + + /** + * This method creates and installs the listeners for this UI. + */ + protected void installListeners() + { + // install combo box's listeners + propertyChangeListener = createPropertyChangeListener(); + comboBox.addPropertyChangeListener(propertyChangeListener); + + focusListener = createFocusListener(); + comboBox.addFocusListener(focusListener); + + itemListener = createItemListener(); + comboBox.addItemListener(itemListener); + + keyListener = createKeyListener(); + comboBox.addKeyListener(keyListener); + + mouseListener = createMouseListener(); + comboBox.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 + */ + protected void uninstallDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + comboBox.setBackground(null); + comboBox.setFont(null); + comboBox.setForeground(null); + + shadow = null; + darkShadow = null; + lightHighlight = null; + highlight = null; + } + + /** + * Detaches all the listeners we attached in {@link #installListeners}. + */ + protected void uninstallListeners() + { + comboBox.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + + comboBox.removeFocusListener(focusListener); + focusListener = null; + + comboBox.removeItemListener(itemListener); + itemListener = null; + + comboBox.removeKeyListener(keyListener); + keyListener = null; + + comboBox.removeMouseListener(mouseListener); + mouseListener = null; + + comboBox.getModel().removeListDataListener(listDataListener); + listDataListener = null; + + unconfigureArrowButton(); + } + + /** + * This method creates popup that will contain list of combo box's items + * + * @return popup containing list of combo box's items + */ + protected ComboPopup createPopup() + { + return new BasicComboPopup(comboBox); + } + + /** + * Creates KeyListener to listen to key events. + * + * @return KeyListener that listens to key events. + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + + /** + * This method create MouseListener that will listen to mouse event occuring + * in combo box. + * + * @return the MouseListener + */ + private MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * This method create FocusListener that will listen to changes in this + * JComboBox's focus. + * + * @return theFocusListener + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method create ListDataListener to listen to ComboBox's data model + * + * @return ListDataListener + */ + protected ListDataListener createListDataListener() + { + return new ListDataHandler(); + } + + /** + * This method creates ItemListener that will listen to to the changes in + * the JComboBox's selection. + * + * @return the ItemListener + */ + protected ItemListener createItemListener() + { + return new ItemHandler(); + } + + /** + * This method creates PropertyChangeListener to listen to the changes in + * the JComboBox's bound properties. + * + * @return the PropertyChangeListener + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method returns layout manager for the combo box. + * + * @return layout manager for the combo box + */ + protected LayoutManager createLayoutManager() + { + return new ComboBoxLayoutManager(); + } + + /** + * This method creates component that will be responsible for rendering the + * selected component in the combo box. + * + * @return render for the combo box + */ + protected ListCellRenderer createRenderer() + { + return new BasicComboBoxRenderer(); + } + + /** + * 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. + * + * @return component that will be responsible for displaying/editting + * selected item in the combo box. + */ + protected ComboBoxEditor createEditor() + { + return new BasicComboBoxEditor(); + } + + /** + * This method installs 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); + + // 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 drop down list of items + popup = createPopup(); + + comboBox.revalidate(); + } + + /** + * This method uninstalls components from this JComboBox + */ + protected void uninstallComponents() + { + // uninstall arrow button + unconfigureArrowButton(); + comboBox.remove(arrowButton); + arrowButton = null; + + listBox = null; + popup = null; + + comboBox.setRenderer(null); + + comboBox.setEditor(null); + editor = null; + } + + /** + * This method adds editor to the combo box + */ + public void addEditor() + { + comboBox.add(editor); + } + + /** + * This method removes editor from the combo box + */ + public void removeEditor() + { + comboBox.remove(editor); + } + + /** + * This method configures editor for this combo box. + */ + protected void configureEditor() + { + // FIXME: Need to implement. Set font and add listeners. + } + + /** + * This method removes all the listeners for the editor. + */ + protected void unconfigureEditor() + { + // FIXME: Need to implement + } + + /** + * This method adds listeners to the arrow button part of the combo box. + */ + public void configureArrowButton() + { + arrowButton.addMouseListener(mouseListener); + } + + /** + * This method removes listeners from the arrow button part of the combo + * box. + */ + public void unconfigureArrowButton() + { + arrowButton.removeMouseListener(mouseListener); + } + + /** + * This method create arrow button for this JComboBox. Arrow button is + * responsible for displaying / hiding drop down list of items when it is + * clicked. + * + * @return JButton arrow button for this JComboBox. + */ + protected JButton createArrowButton() + { + return new BasicArrowButton(BasicArrowButton.SOUTH); + } + + /** + * This method checks if popup part of the combo box is visible on the + * screen + * + * @param c The JComboBox to check + * + * @return true if popup part of the JComboBox is visible and false + * otherwise. + */ + public boolean isPopupVisible(JComboBox c) + { + return popup.isVisible(); + } + + /** + * Displays/Hides JComboBox's list of items on the screen. + * + * @param c The combo box, for which list of items should be + * displayed/hidden + * @param v true if show popup part of the jcomboBox and false to hide. + */ + public void setPopupVisible(JComboBox c, boolean v) + { + if (v) + popup.show(); + else + popup.hide(); + } + + /** + * JComboBox is focus traversable if it is editable and not otherwise. + * + * @param c combo box for which to check whether it is focus traversable + * + * @return true if focus tranversable and false otherwise + */ + public boolean isFocusTraversable(JComboBox c) + { + if (comboBox.isEditable()) + return true; + + return false; + } + + /** + * Paints given menu item using specified graphics context + * + * @param g The graphics context used to paint this combo box + * @param c comboBox which needs to be painted. + */ + 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); + } + + /** + * Returns preferred size for the given menu item. + * + * @param c comboBox for which to get preferred size + * + * @return $Dimension$ 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; + } + + /** + * This method returns the minimum size for this {@link JComboBox} for this + * look and feel. + * + * @param c The {@link JComponent} to find the minimum size for. + * + * @return The dimensions of the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * This method 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. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + public int getAccessibleChildrenCount(JComponent c) + { + // FIXME: Need to implement + return 0; + } + + public Accessible getAccessibleChild(JComponent c, int i) + { + // FIXME: Need to implement + return null; + } + + /** + * Returns true if the specified key is a navigation key and false otherwise + * + * @param keyCode a key for which to check whether it is navigation key or + * not. + * + * @return true if the specified key is a navigation key and false otherwis + */ + protected boolean isNavigationKey(int keyCode) + { + return false; + } + + /** + * This method selects next possible item relative to the current selection + * to be next selected item in the combo box. + */ + protected void selectNextPossibleValue() + { + int index = comboBox.getSelectedIndex(); + if (index != comboBox.getItemCount() - 1) + comboBox.setSelectedIndex(index + 1); + } + + /** + * This method selects previous item relative to current selection to be + * next selected item. + */ + protected void selectPreviousPossibleValue() + { + int index = comboBox.getSelectedIndex(); + if (index != 0) + comboBox.setSelectedIndex(index - 1); + } + + /** + * This method 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() + { + setPopupVisible(comboBox, ! isPopupVisible(comboBox)); + } + + /** + * This method returns 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); + + return rectForCurrentValue; + } + + /** + * This method returns insets of the current border. + * + * @return Insets representing space between combo box and its border + */ + protected Insets getInsets() + { + return new Insets(0, 0, 0, 0); + } + + /** + * This method paints currently selected value in the main part of the combo + * box (part without popup). + * + * @param g graphics context + * @param bounds Rectangle representing the size of the area in which + * selected item should be drawn + * @param hasFocus true if combo box has focus and false otherwise + */ + public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) + { + if (! comboBox.isEditable()) + { + Object currentValue = comboBox.getSelectedItem(); + boolean isPressed = arrowButton.getModel().isPressed(); + + /* Gets the component to be drawn for the current value. + * 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(); + } + else + comboBox.getEditor().setItem(comboBox.getSelectedItem()); + } + + /** + * This method paints 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. + * + * @param g graphics context + * @param bounds Rectangle representing the size of the largest item in the + * comboBox + * @param hasFocus true if combo box has fox and false otherwise + */ + public void paintCurrentValueBackground(Graphics g, Rectangle bounds, + boolean hasFocus) + { + // background is painted by renderer, so it seems that nothing + // should be done here. + } + + /** + * Returns default size for the combo box that doesn't contain any elements + * in it + * + * @return Default size of the combo box with no elements in it. + */ + protected Dimension getDefaultSize() + { + return new Dimension(6, 17); + } + + /** + * Returns size of the largest item in 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. + */ + protected Dimension getLargestItemSize() + { + 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) + { + largestItemSize = getDefaultSize(); + return largestItemSize; + } + + 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); + String s = item.toString(); + Component comp = renderer.getListCellRendererComponent(listBox, item, + -1, false, false); + + if (comp.getPreferredSize().getWidth() > size.getWidth()) + size = comp.getPreferredSize(); + } + + largestItemSize = size; + return largestItemSize; + } + + /** + * This method installs the keyboard actions for the JComboBox as specified + * by the look and feel. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement. + } + + /** + * This method uninstalls the keyboard actions for the JComboBox there were + * installed by in {@link #installListeners}. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement. + } + + /** + * This class is Layout Manager for this combo box. + */ + public class ComboBoxLayoutManager extends Object implements LayoutManager + { + /** + * Creates a new ComboBoxLayoutManager object. + */ + public ComboBoxLayoutManager() + { + } + + public void addLayoutComponent(String name, Component comp) + { + // Do nothing + } + + public void removeLayoutComponent(Component comp) + { + // Do nothing + } + + /** + * Returns preferred layout size of the JComboBox. + * + * @param parent Container for which preferred size should be calculated + * + * @return 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; + } + + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + /** + * This method layouts out 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. + * + * @param parent Container that should be layed out. + */ + public void layoutContainer(Container parent) + { + // Position editor component to the left of arrow button if combo box is + // editable + int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2; + + 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); + comboBox.revalidate(); + } + } + + /** + * This class 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. + */ + public class FocusHandler extends Object implements FocusListener + { + /** + * Creates a new FocusHandler object. + */ + public FocusHandler() + { + } + + /** + * This mehtod is invoked when combo box gains focus. It repaints main + * part of combo box accordingally. + * + * @param e the FocusEvent + */ + public void focusGained(FocusEvent e) + { + hasFocus = true; + comboBox.repaint(); + } + + /** + * This method is invoked when combo box loses focus It repaint main part + * of combo box accordingally and hides popup list of items. + * + * @param e the FocusEvent + */ + public void focusLost(FocusEvent e) + { + hasFocus = false; + comboBox.repaint(); + popup.hide(); + } + } + + /** + * This class handles ItemEvent fired by the JComboBox when its selected + * item changes. + */ + public class ItemHandler extends Object implements ItemListener + { + /** + * Creates a new ItemHandler object. + */ + public ItemHandler() + { + } + + /** + * This method is 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) + { + comboBox.repaint(); + } + } + + /** + * KeyHandler handles key events occuring while JComboBox has focus. + */ + public class KeyHandler extends KeyAdapter + { + public KeyHandler() + { + } + + /* + * This method is invoked whenever key is pressed while JComboBox is in + * focus. + */ + public void keyPressed(KeyEvent e) + { + // FIXME: This method calls JComboBox.selectWithKeyChar if the key that was + // pressed is not a navigation key. + } + } + + /** + * This class handles to the changes occuring in the JComboBox's data model + */ + public class ListDataHandler extends Object implements ListDataListener + { + /** + * Creates a new ListDataHandler object. + */ + public ListDataHandler() + { + } + + /** + * This method is invoked content's of JComboBox's data model are changed + * + * @param e ListDataEvent describing the change. + */ + public void contentsChanged(ListDataEvent e) + { + // if the item is selected or deselected + } + + /** + * This method is invoked when items were 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); + + 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(); + } + } + + /** + * This method is invoked when items were removed from the JComboBox's + * data model. + * + * @param e ListDataEvent describing the change. + */ + public void intervalRemoved(ListDataEvent e) + { + // recalculate display size of the JComboBox. + largestItemSize = getLargestItemSize(); + comboBox.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired by JComboBox. + */ + public class PropertyChangeHandler extends Object + implements PropertyChangeListener + { + public PropertyChangeHandler() + { + } + + /** + * This method is invoked whenever bound property of JComboBox changes. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("enabled")) + { + arrowButton.setEnabled(comboBox.isEnabled()); + + if (comboBox.isEditable()) + comboBox.getEditor().getEditorComponent().setEnabled(comboBox + .isEnabled()); + } + else if (e.getPropertyName().equals("editable")) + { + if (comboBox.isEditable()) + { + configureEditor(); + addEditor(); + } + else + { + unconfigureEditor(); + removeEditor(); + } + + comboBox.revalidate(); + comboBox.repaint(); + } + else if (e.getPropertyName().equals("dataModel")) + { + // remove ListDataListener from old model and add it to new model + ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue(); + if (oldModel != null) + oldModel.removeListDataListener(listDataListener); + + if ((ComboBoxModel) e.getNewValue() != null) + comboBox.getModel().addListDataListener(listDataListener); + } + + // 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. + */ + private class MouseHandler extends MouseAdapter + { + /** + * This method is invoked when mouse is pressed over the combo box. It + * repaints the combo box accordinglly + * + * @param e the MouseEvent + */ + 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(); + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java new file mode 100644 index 0000000..73aac8d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java @@ -0,0 +1,1055 @@ +/* BasicComboPopup.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.ComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.ListCellRenderer; +import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/** + * UI Delegate for ComboPopup + * + * @author Olga Rodimina + */ +public class BasicComboPopup extends JPopupMenu implements ComboPopup +{ + /* Timer for autoscrolling */ + protected Timer autoscrollTimer; + + /** ComboBox associated with this popup */ + protected JComboBox comboBox; + + /** FIXME: Need to document */ + protected boolean hasEntered; + + /** + * Indicates whether the scroll bar located in popup menu with comboBox's + * list of items is currently autoscrolling. This happens when mouse event + * originated in the combo box and is dragged outside of its bounds + */ + protected boolean isAutoScrolling; + + /** ItemListener listening to the selection changes in the combo box */ + protected ItemListener itemListener; + + /** This listener is not used */ + protected KeyListener keyListener; + + /** JList which is used to display item is the combo box */ + protected JList list; + + /** This listener is not used */ + protected ListDataListener listDataListener; + + /** + * MouseListener listening to mouse events occuring in the combo box's + * list. + */ + protected MouseListener listMouseListener; + + /** + * MouseMotionListener listening to mouse motion events occuring in the + * combo box's list + */ + protected MouseMotionListener listMouseMotionListener; + + /** This listener is not used */ + protected ListSelectionListener listSelectionListener; + + /** MouseListener listening to mouse events occuring in the combo box */ + protected MouseListener mouseListener; + + /** + * MouseMotionListener listening to mouse motion events occuring in the + * combo box + */ + protected MouseMotionListener mouseMotionListener; + + /** + * PropertyChangeListener listening to changes occuring in the bound + * properties of the combo box + */ + protected PropertyChangeListener propertyChangeListener; + + /** direction for scrolling down list of combo box's items */ + protected static final int SCROLL_DOWN = 1; + + /** direction for scrolling up list of combo box's items */ + protected static final int SCROLL_UP = 0; + + /** Indicates auto scrolling direction */ + protected int scrollDirection; + + /** JScrollPane that contains list portion of the combo box */ + protected JScrollPane scroller; + + /** This field is not used */ + protected boolean valueIsAdjusting; + + /** + * Creates a new BasicComboPopup object. + * + * @param comboBox the combo box with which this popup should be associated + */ + public BasicComboPopup(JComboBox comboBox) + { + this.comboBox = comboBox; + installComboBoxListeners(); + configurePopup(); + setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled()); + } + + /** + * This method displays drow down list of combo box items on the screen. + */ + public void show() + { + Rectangle cbBounds = comboBox.getBounds(); + + // popup should have same width as the comboBox and should be hight anough + // 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); + + // Highlight selected item in the combo box's drop down list + if (comboBox.getSelectedIndex() != -1) + list.setSelectedIndex(comboBox.getSelectedIndex()); + + //scroll scrollbar s.t. selected item is visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int selectedIndex = comboBox.getSelectedIndex(); + if (selectedIndex > comboBox.getMaximumRowCount()) + scrollbar.setValue(getPopupHeightForRowCount(selectedIndex)); + + // location specified is relative to comboBox + super.show(comboBox, 0, cbBounds.height); + } + + /** + * This method hides drop down list of items + */ + public void hide() + { + super.setVisible(false); + } + + /** + * Return list cointaining JComboBox's items + * + * @return list cointaining JComboBox's items + */ + public JList getList() + { + return list; + } + + /** + * Returns MouseListener that is listening to mouse events occuring in the + * combo box. + * + * @return MouseListener + */ + public MouseListener getMouseListener() + { + return mouseListener; + } + + /** + * Returns MouseMotionListener that is listening to mouse motion events + * occuring in the combo box. + * + * @return MouseMotionListener + */ + public MouseMotionListener getMouseMotionListener() + { + return mouseMotionListener; + } + + /** + * Returns KeyListener listening to key events occuring in the combo box. + * This method returns null because KeyHandler is not longer used. + * + * @return KeyListener + */ + public KeyListener getKeyListener() + { + return keyListener; + } + + /** + * This method uninstalls the UI for the given JComponent. + */ + public void uninstallingUI() + { + uninstallComboBoxModelListeners(comboBox.getModel()); + + uninstallListeners(); + uninstallKeyboardActions(); + } + + /** + * This method uninstalls listeners that were listening to changes occuring + * in the comb box's data model + * + * @param model data model for the combo box from which to uninstall + * listeners + */ + protected void uninstallComboBoxModelListeners(ComboBoxModel model) + { + model.removeListDataListener(listDataListener); + } + + /** + * This method uninstalls keyboard actions installed by the UI. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items will become visible + */ + protected void firePopupMenuWillBecomeVisible() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuWillBecomeVisible(new PopupMenuEvent(comboBox)); + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items will become invisible. + */ + protected void firePopupMenuWillBecomeInvisible() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuWillBecomeInvisible(new PopupMenuEvent(comboBox)); + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items was closed without selection. + */ + protected void firePopupMenuCanceled() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuCanceled(new PopupMenuEvent(comboBox)); + } + + /** + * Creates MouseListener to listen to mouse events occuring in the combo + * box. Note that this listener doesn't listen to mouse events occuring in + * the popup portion of the combo box, it only listens to main combo box + * part. + * + * @return new MouseMotionListener that listens to mouse events occuring in + * the combo box + */ + protected MouseListener createMouseListener() + { + return new InvocationMouseHandler(); + } + + /** + * Create Mouse listener that listens to mouse dragging events occuring in + * the combo box. This listener is responsible for changing the selection + * in the combo box list to the component over which mouse is being + * currently dragged + * + * @return new MouseMotionListener that listens to mouse dragging events + * occuring in the combo box + */ + protected MouseMotionListener createMouseMotionListener() + { + return new InvocationMouseMotionHandler(); + } + + /** + * KeyListener created in this method is not used anymore. + * + * @return KeyListener that does nothing + */ + protected KeyListener createKeyListener() + { + return new InvocationKeyHandler(); + } + + /** + * ListSelectionListener created in this method is not used anymore + * + * @return ListSelectionListener that does nothing + */ + protected ListSelectionListener createListSelectionListener() + { + return new ListSelectionHandler(); + } + + /** + * Creates ListDataListener. This method returns null, because + * ListDataHandler class is obsolete and is no longer used. + * + * @return null + */ + protected ListDataListener createListDataListener() + { + return null; + } + + /** + * This method creates ListMouseListener to listen to mouse events occuring + * in the combo box's item list. + * + * @return MouseListener to listen to mouse events occuring in the combo + * box's items list. + */ + protected MouseListener createListMouseListener() + { + return new ListMouseHandler(); + } + + /** + * Creates ListMouseMotionlistener to listen to mouse motion events occuring + * in the combo box's list. This listener is responsible for highlighting + * items in the list when mouse is moved over them. + * + * @return MouseMotionListener that handles mouse motion events occuring in + * the list of the combo box. + */ + protected MouseMotionListener createListMouseMotionListener() + { + return new ListMouseMotionHandler(); + } + + /** + * Creates PropertyChangeListener to handle changes in the JComboBox's bound + * properties. + * + * @return PropertyChangeListener to handle changes in the JComboBox's bound + * properties. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates new ItemListener that will listen to ItemEvents occuring in the + * combo box. + * + * @return ItemListener to listen to ItemEvents occuring in the combo box. + */ + protected ItemListener createItemListener() + { + return new ItemHandler(); + } + + /** + * Creates JList that will be used to display items in the combo box. + * + * @return JList that will be used to display items in the combo box. + */ + protected JList createList() + { + JList l = new JList(comboBox.getModel()); + l.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + return l; + } + + /** + * This method configures the list of comboBox's items by setting default + * properties and installing listeners. + */ + protected void configureList() + { + list.setModel(comboBox.getModel()); + list.setVisibleRowCount(comboBox.getMaximumRowCount()); + installListListeners(); + } + + /** + * This method installs list listeners. + */ + protected void installListListeners() + { + // mouse listener listening to mouse events occuring in the + // combo box's list of items. + listMouseListener = createListMouseListener(); + list.addMouseListener(listMouseListener); + + // mouse listener listening to mouse motion events occuring in the + // combo box's list of items + listMouseMotionListener = createListMouseMotionListener(); + list.addMouseMotionListener(listMouseMotionListener); + + listSelectionListener = createListSelectionListener(); + list.addListSelectionListener(listSelectionListener); + } + + /** + * This method creates scroll pane that will contain the list of comboBox's + * items inside of it. + * + * @return JScrollPane + */ + protected JScrollPane createScroller() + { + return new JScrollPane(); + } + + /** + * This method configures scroll pane to contain list of comboBox's items + */ + protected void configureScroller() + { + scroller.getViewport().setView(list); + scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + + /** + * This method configures popup menu that will be used to display Scrollpane + * with list of items inside of it. + */ + protected void configurePopup() + { + // initialize list that will be used to display combo box's items + this.list = createList(); + ((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT); + configureList(); + + // initialize scroller. Add list to the scroller. + scroller = createScroller(); + configureScroller(); + + // add scroller with list inside of it to JPopupMenu + super.add(scroller); + } + + /* + * This method installs listeners that will listen to changes occuring + * in the combo box. + */ + protected void installComboBoxListeners() + { + // mouse listener that listens to mouse event in combo box + mouseListener = createMouseListener(); + comboBox.addMouseListener(mouseListener); + + // mouse listener that listens to mouse dragging events in the combo box + mouseMotionListener = createMouseMotionListener(); + comboBox.addMouseMotionListener(mouseMotionListener); + + // item listener listenening to selection events in the combo box + itemListener = createItemListener(); + comboBox.addItemListener(itemListener); + + propertyChangeListener = createPropertyChangeListener(); + comboBox.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method installs listeners that will listen to changes occuring in + * the comb box's data model + * + * @param model data model for the combo box for which to install listeners + */ + protected void installComboBoxModelListeners(ComboBoxModel model) + { + // list data listener to listen for ListDataEvents in combo box. + // This listener is now obsolete and nothing is done here + listDataListener = createListDataListener(); + comboBox.getModel().addListDataListener(listDataListener); + } + + /** + * DOCUMENT ME! + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method always returns false to indicate that items in the combo box + * list are not focus traversable. + * + * @return false + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * This method start scrolling combo box's list of items either up or down + * depending on the specified 'direction' + * + * @param direction of the scrolling. + */ + protected void startAutoScrolling(int direction) + { + // FIXME: add timer + isAutoScrolling = true; + + if (direction == SCROLL_UP) + autoScrollUp(); + else + autoScrollDown(); + } + + /** + * This method stops scrolling the combo box's list of items + */ + protected void stopAutoScrolling() + { + // FIXME: add timer + isAutoScrolling = false; + } + + /** + * This method scrolls up list of combo box's items up and highlights that + * just became visible. + */ + protected void autoScrollUp() + { + // scroll up the scroll bar to make the item above visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), + SwingConstants.VERTICAL, + SCROLL_UP); + + scrollbar.setValue(scrollbar.getValue() - scrollToNext); + + // If we haven't reached the begging of the combo box's list of items, + // then highlight next element above currently highlighted element + if (list.getSelectedIndex() != 0) + list.setSelectedIndex(list.getSelectedIndex() - 1); + } + + /** + * This method scrolls down list of combo box's and highlights item in the + * list that just became visible. + */ + protected void autoScrollDown() + { + // scroll scrollbar down to make next item visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), + SwingConstants.VERTICAL, + SCROLL_DOWN); + scrollbar.setValue(scrollbar.getValue() + scrollToNext); + + // If we haven't reached the end of the combo box's list of items + // then highlight next element below currently highlighted element + if (list.getSelectedIndex() + 1 != comboBox.getItemCount()) + list.setSelectedIndex(list.getSelectedIndex() + 1); + } + + /** + * This method helps to delegate focus to the right component in the + * JComboBox. If the comboBox is editable then focus is sent to + * ComboBoxEditor, otherwise it is delegated to JComboBox. + * + * @param e MouseEvent + */ + protected void delegateFocus(MouseEvent e) + { + // FIXME: Need to implement + } + + /** + * This method displays combo box popup if the popup is not currently shown + * on the screen and hides it if it is currently visible + */ + protected void togglePopup() + { + if (BasicComboPopup.this.isVisible()) + hide(); + else + show(); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MouseEvent convertMouseEvent(MouseEvent e) + { + return null; + } + + /** + * Returns required height of the popup such that number of items visible in + * it are equal to the maximum row count. By default + * comboBox.maximumRowCount=8 + * + * @param maxRowCount number of maximum visible rows in the combo box's + * popup list of items + * + * @return height of the popup required to fit number of items equal to + * JComboBox.maximumRowCount. + */ + protected int getPopupHeightForRowCount(int maxRowCount) + { + int totalHeight = 0; + ListCellRenderer rend = list.getCellRenderer(); + + if (comboBox.getItemCount() < maxRowCount) + maxRowCount = comboBox.getItemCount(); + + for (int i = 0; i < maxRowCount; i++) + { + Component comp = rend.getListCellRendererComponent(list, + comboBox.getModel() + .getElementAt(i), + -1, false, false); + Dimension dim = comp.getPreferredSize(); + totalHeight += dim.height; + } + + return totalHeight; + } + + /** + * DOCUMENT ME! + * + * @param px DOCUMENT ME! + * @param py DOCUMENT ME! + * @param pw DOCUMENT ME! + * @param ph DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Rectangle computePopupBounds(int px, int py, int pw, int ph) + { + return new Rectangle(px, py, pw, ph); + } + + /** + * This method changes the selection in the list to the item over which the + * mouse is currently located. + * + * @param anEvent MouseEvent + * @param shouldScroll DOCUMENT ME! + */ + protected void updateListBoxSelectionForEvent(MouseEvent anEvent, + boolean shouldScroll) + { + // FIXME: Need to implement + } + + /** + * InvocationMouseHandler is a listener that listens to mouse events + * occuring in the combo box. Note that this listener doesn't listen to + * mouse events occuring in the popup portion of the combo box, it only + * listens to main combo box part(area that displays selected item). This + * listener is responsible for showing and hiding popup portion of the + * combo box. + */ + protected class InvocationMouseHandler extends MouseAdapter + { + /** + * Creates a new InvocationMouseHandler object. + */ + protected InvocationMouseHandler() + { + } + + /** + * This method is invoked whenever mouse is being pressed over the main + * part of the combo box. This method will show popup if the popup is + * not shown on the screen right now, and it will hide popup otherwise. + * + * @param e MouseEvent that should be handled + */ + public void mousePressed(MouseEvent e) + { + if (comboBox.isEnabled()) + togglePopup(); + } + + /** + * This method is invoked whenever mouse event was originated in the combo + * box and released either in the combBox list of items or in the combo + * box itself. + * + * @param e MouseEvent that should be handled + */ + public void mouseReleased(MouseEvent e) + { + // Get component over which mouse was released + Component src = (Component) e.getSource(); + int x = e.getX(); + int y = e.getY(); + Component releasedComponent = SwingUtilities.getDeepestComponentAt(src, + x, y); + + // if mouse was released inside the bounds of combo box then do nothing, + // Otherwise if mouse was released inside the list of combo box items + // 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(); + } + } + } + + /** + * InvocationMouseMotionListener is a mouse listener that listens to mouse + * dragging events occuring in the combo box. + */ + protected class InvocationMouseMotionHandler extends MouseMotionAdapter + { + /** + * Creates a new InvocationMouseMotionHandler object. + */ + protected InvocationMouseMotionHandler() + { + } + + /** + * This method is responsible for highlighting item in the drop down list + * over which the mouse is currently being dragged. + */ + public void mouseDragged(MouseEvent e) + { + // convert point of the drag event relative to combo box list component + // figure out over which list cell the mouse is currently being dragged + // and highlight the cell. The list model is changed but the change has + // no effect on combo box's data model. The list model is changed so + // that the appropriate item would be highlighted in the combo box's + // list. + if (BasicComboPopup.this.isVisible()) + { + int cbHeight = (int) comboBox.getPreferredSize().getHeight(); + int popupHeight = BasicComboPopup.this.getSize().height; + + // if mouse is dragged inside the the combo box's items list. + if (e.getY() > cbHeight && ! (e.getY() - cbHeight >= popupHeight)) + { + int index = list.locationToIndex(new Point(e.getX(), + (int) (e.getY() + - cbHeight))); + + int firstVisibleIndex = list.getFirstVisibleIndex(); + + // list.locationToIndex returns item's index that would + // be located at the specified point if the first item that + // is visible is item 0. However in the JComboBox it is not + // necessarily the case since list is contained in the + // JScrollPane so we need to adjust the index returned. + if (firstVisibleIndex != 0) + // FIXME: adjusted index here is off by one. I am adding one + // here to compensate for that. This should be + // index += firstVisibleIndex. Remove +1 once the bug is fixed. + index += firstVisibleIndex + 1; + + list.setSelectedIndex(index); + } + else + { + // if mouse is being dragged at the bottom of combo box's list + // of items or at the very top then scroll the list in the + // desired direction. + boolean movingUP = e.getY() < cbHeight; + boolean movingDown = e.getY() > cbHeight; + + if (movingUP) + { + scrollDirection = SCROLL_UP; + startAutoScrolling(SCROLL_UP); + } + else if (movingDown) + { + scrollDirection = SCROLL_DOWN; + startAutoScrolling(SCROLL_DOWN); + } + } + } + } + } + + /** + * ItemHandler is an item listener that listens to selection events occuring + * in the combo box. FIXME: should specify here what it does when item is + * selected or deselected in the combo box list. + */ + protected class ItemHandler extends Object implements ItemListener + { + /** + * Creates a new ItemHandler object. + */ + protected ItemHandler() + { + } + + /** + * This method responds to the selection events occuring in the combo box. + * + * @param e ItemEvent specifying the combo box's selection + */ + public void itemStateChanged(ItemEvent e) + { + } + } + + /** + * ListMouseHandler is a listener that listens to mouse events occuring in + * the combo box's list of items. This class is responsible for hiding + * popup portion of the combo box if the mouse is released inside the combo + * box's list. + */ + protected class ListMouseHandler extends MouseAdapter + { + protected ListMouseHandler() + { + } + + public void mousePressed(MouseEvent e) + { + } + + public void mouseReleased(MouseEvent anEvent) + { + int index = list.locationToIndex(anEvent.getPoint()); + comboBox.setSelectedIndex(index); + hide(); + } + } + + /** + * ListMouseMotionHandler listens to mouse motion events occuring in the + * combo box's list. This class is responsible for highlighting items in + * the list when mouse is moved over them + */ + protected class ListMouseMotionHandler extends MouseMotionAdapter + { + protected ListMouseMotionHandler() + { + } + + 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(); + } + } + + /** + * This class listens to changes occuring in the bound properties of the + * combo box + */ + protected class PropertyChangeHandler extends Object + implements PropertyChangeListener + { + protected PropertyChangeHandler() + { + } + + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("renderer")) + { + list.setCellRenderer((ListCellRenderer) e.getNewValue()); + revalidate(); + repaint(); + } + if (e.getPropertyName().equals("dataModel")) + { + list.setModel((ComboBoxModel) e.getNewValue()); + revalidate(); + repaint(); + } + } + } + + // ------ private helper methods -------------------- + + /** + * This method uninstalls listeners installed by the UI + */ + private void uninstallListeners() + { + uninstallListListeners(); + uninstallComboBoxListeners(); + uninstallComboBoxModelListeners(comboBox.getModel()); + } + + /** + * This method uninstalls Listeners registered with combo boxes list of + * items + */ + private void uninstallListListeners() + { + list.removeMouseListener(listMouseListener); + listMouseListener = null; + + list.removeMouseMotionListener(listMouseMotionListener); + listMouseMotionListener = null; + } + + /** + * This method uninstalls listeners listening to combo box associated with + * this popup menu + */ + private void uninstallComboBoxListeners() + { + comboBox.removeMouseListener(mouseListener); + mouseListener = null; + + comboBox.removeMouseMotionListener(mouseMotionListener); + mouseMotionListener = null; + + comboBox.removeItemListener(itemListener); + itemListener = null; + + comboBox.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + // -------------------------------------------------------------------- + // The following classes are here only for backwards API compatibility + // They aren't used. + // -------------------------------------------------------------------- + + /** + * This class is not used any more. + */ + public class ListDataHandler extends Object implements ListDataListener + { + public ListDataHandler() + { + } + + public void contentsChanged(ListDataEvent e) + { + } + + public void intervalAdded(ListDataEvent e) + { + } + + public void intervalRemoved(ListDataEvent e) + { + } + } + + /** + * This class is not used anymore + */ + protected class ListSelectionHandler extends Object + implements ListSelectionListener + { + protected ListSelectionHandler() + { + } + + public void valueChanged(ListSelectionEvent e) + { + } + } + + /** + * This class is not used anymore + */ + public class InvocationKeyHandler extends KeyAdapter + { + public InvocationKeyHandler() + { + } + + public void keyReleased(KeyEvent e) + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java new file mode 100644 index 0000000..561b497 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java @@ -0,0 +1,590 @@ +/* BasicDesktopIconUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.JInternalFrame.JDesktopIcon; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.DesktopIconUI; + +/** + * This class acts as the UI delegate for JDesktopIcons for the Basic look and feel. + */ +public class BasicDesktopIconUI extends DesktopIconUI +{ + /** + * This helper class handles mouse events that occur on the JDesktopIcon. + */ + public class MouseInputHandler extends MouseInputAdapter + { + /** The x offset from the MouseEvent coordinates to the top left corner. */ + private transient int xOffset; + + /** The y offset fromt he MouseEvent coordinates to the top left corner. */ + private transient int yOffset; + + /** A cached value of the JDesktopPane that parents this JDesktopIcon. */ + private transient JDesktopPane pane; + + /** + * This method is called when the mouse is dragged in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + Rectangle b = desktopIcon.getBounds(); + + moveAndRepaint(desktopIcon, b.x + e.getX() - xOffset, + b.y + e.getY() - yOffset, b.width, b.height); + } + + /** + * This method is called when the mouse is moved in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Nothing to do. + } + + /** + * This method is called when the mouse is pressed in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + xOffset = e.getX(); + yOffset = e.getY(); + pane = frame.getDesktopPane(); + if (pane != null) + pane.getDesktopManager().beginDraggingFrame(desktopIcon); + } + + /** + * This method is called when the mouse is released in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (pane != null) + pane.getDesktopManager().endDraggingFrame(desktopIcon); + xOffset = 0; + yOffset = 0; + } + + /** + * This method moves and repaints the JDesktopIcon to the given bounds. + * + * @param f The JComponent to move and repaint. + * @param newX The new x coordinate. + * @param newY The new y coordinate. + * @param newWidth The new width. + * @param newHeight The new height. + */ + public void moveAndRepaint(JComponent f, int newX, int newY, int newWidth, + int newHeight) + { + if (pane != null) + pane.getDesktopManager().dragFrame(f, newX, newY); + else + desktopIcon.setBounds(newX, newY, newWidth, newHeight); + } + } + + /** + * This class acts as the border for the JDesktopIcon. + */ + private class DesktopIconBorder implements Border + { + /** The left inset value. */ + int left = 10; + + /** The top inset value. */ + int top = 4; + + /** The right inset value. */ + int right = top; + + /** The bottom inset value. */ + int bottom = top; + + /** + * This method returns the insets of the border. + * + * @param c The Component to find border insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(top, left, bottom, right); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method paints the border. + * + * @param c The Component the border is in. + * @param g The Graphics object to paint with. + * @param x The x coordinate of the Component. + * @param y The y coordinate of the Component. + * @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) + { + g.translate(x, y); + Color saved = g.getColor(); + + g.setColor(Color.LIGHT_GRAY); + + g.fillRect(0, 0, left, height); + g.fillRect(0, 0, width, top); + g.fillRect(0, height - bottom, width, bottom); + g.fillRect(width - right, 0, right, height); + + g.setColor(Color.BLACK); + g.drawRect(0, 0, width - 1, height - 1); + + int fHeight = height / 4; + int hLeft = left / 2; + + g.setColor(Color.BLACK); + g.fillRect(hLeft, fHeight, 2, 2); + g.fillRect(hLeft, fHeight * 2, 2, 2); + g.fillRect(hLeft, fHeight * 3, 2, 2); + + g.setColor(saved); + g.translate(-x, -y); + } + } + + /** The static width and height of the iconSize. */ + private static final int iconSize = 16; + + /** + * This class represents the default frame icon when none + * is supplied by the JInternalFrame. + */ + static class InternalFrameDefaultMenuIcon implements Icon + { + /** + * This returns the icon height. + * + * @return The icon height. + */ + public int getIconHeight() + { + return iconSize; + } + + /** + * This returns the icon width. + * + * @return The icon width. + */ + public int getIconWidth() + { + return iconSize; + } + + /** + * This method paints the icon. + * + * @param c The Component this icon belongs to. + * @param g The Graphics object to paint with. + * @param x The x coordinate to paint at. + * @param y The y coordinate to paint at. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + + g.setColor(Color.BLUE); + g.fillRect(0, 0, iconSize, (int) ((double) iconSize / 3) + 1); + + g.setColor(Color.WHITE); + g.fillRect(0, (int) ((double) iconSize / 3), iconSize, iconSize * 5 / 6); + + g.setColor(Color.GRAY); + g.drawRect(0, 0, iconSize, iconSize); + + g.setColor(saved); + g.translate(-x, -y); + } + } + + /** The default JDesktopIcon width. */ + private static final int iconWidth = 160; + + /** The default JDesktopIcon height */ + private static final int iconHeight = 35; + + /** The JDesktopIcon this UI delegate represents. */ + protected JDesktopIcon desktopIcon; + + /** The JInternalFrame associated with the JDesktopIcon. */ + protected JInternalFrame frame; + + /** The MouseListener responsible for reacting to MouseEvents on the JDesktopIcon. */ + private transient MouseInputListener mouseHandler; + + /** The Button in the JDesktopIcon responsible for deiconifying it. + * This is package-private to avoid an accessor method. */ + transient BoundButton button; + + /** The PropertyChangeListener listening to the JDesktopIcon. */ + private transient PropertyChangeListener propertyHandler; + + /** The default icon used when no frame icon is given by the JInternalFrame. */ + static Icon defaultIcon = new InternalFrameDefaultMenuIcon(); + + /** + * This is a helper class that is used in JDesktopIcon and gives the Button a predetermined size. + */ + private class BoundButton extends JButton + { + /** + * Creates a new BoundButton object. + * + * @param title The title of the button. + */ + public BoundButton(String title) + { + super(title); + } + + /** + * This method returns a standard size (based on the defaults of the JDesktopIcon) and the insets. + * + * @return The preferred size of the JDesktopIcon. + */ + public Dimension getPreferredSize() + { + Insets insets = desktopIcon.getInsets(); + return new Dimension(iconWidth - insets.left - insets.right, + iconHeight - insets.top - insets.bottom); + } + + /** + * This method returns the minimum size of the button. + * + * @return The minimum size of the button. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * This method returns the maximum size of the button. + * + * @return The maximum size of the button. + */ + public Dimension getMaximumSize() + { + return getPreferredSize(); + } + } + + /** + * Creates a new BasicDesktopIconUI object. + */ + public BasicDesktopIconUI() + { + } + + /** + * This method creates a new BasicDesktopIconUI for the given JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicDesktopIconUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicDesktopIconUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JDesktopIcon) + { + desktopIcon = (JDesktopIcon) c; + desktopIcon.setLayout(new BorderLayout()); + frame = desktopIcon.getInternalFrame(); + + installDefaults(); + installComponents(); + installListeners(); + + desktopIcon.setOpaque(true); + } + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + desktopIcon.setOpaque(false); + + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + + frame = null; + desktopIcon.setLayout(null); + desktopIcon = null; + } + + /** + * This method installs the necessary sub components for the JDesktopIcon. + */ + protected void installComponents() + { + // Try to create a button based on what the frame's + // state is currently + button = new BoundButton(frame.getTitle()); + button.setHorizontalAlignment(SwingConstants.LEFT); + button.setHorizontalTextPosition(SwingConstants.TRAILING); + + Icon use = frame.getFrameIcon(); + if (use == null) + use = defaultIcon; + button.setIcon(use); + + desktopIcon.add(button, SwingConstants.CENTER); + } + + /** + * This method uninstalls the sub components for the JDesktopIcon. + */ + protected void uninstallComponents() + { + desktopIcon.remove(button); + + button = null; + } + + /** + * This method installs the listeners needed by this UI. + */ + protected void installListeners() + { + mouseHandler = createMouseInputListener(); + + desktopIcon.addMouseMotionListener(mouseHandler); + desktopIcon.addMouseListener(mouseHandler); + + propertyHandler = new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JInternalFrame.TITLE_PROPERTY)) + button.setText(desktopIcon.getInternalFrame().getTitle()); + else if (e.getPropertyName().equals(JInternalFrame.FRAME_ICON_PROPERTY)) + { + Icon use = desktopIcon.getInternalFrame().getFrameIcon(); + if (use == null) + use = defaultIcon; + button.setIcon(use); + } + desktopIcon.revalidate(); + desktopIcon.repaint(); + } + }; + frame.addPropertyChangeListener(propertyHandler); + + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + deiconize(); + } + }); + } + + /** + * This method uninstalls the listeners needed by the UI. + */ + protected void uninstallListeners() + { + // button is nulled so no need to remove it. + + frame.removePropertyChangeListener(propertyHandler); + propertyHandler = null; + + desktopIcon.removeMouseMotionListener(mouseHandler); + desktopIcon.removeMouseListener(mouseHandler); + } + + /** + * This method installs the defaults for the JDesktopIcon. + */ + protected void installDefaults() + { + // FIXME: Move border to defaults. + desktopIcon.setBorder(new DesktopIconBorder()); + } + + /** + * This method uninstalls the defaults for the JDesktopIcon. + */ + protected void uninstallDefaults() + { + desktopIcon.setBorder(null); + } + + /** + * This method creates a new MouseInputListener for the JDesktopIcon. + * + * @return A new MouseInputListener. + */ + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + /** + * This method returns the preferred size for the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return new Dimension(iconWidth, iconHeight); + } + + /** + * This method returns the minimum size for the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size for the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the insets of the given JComponent. + * + * @param c The JComponent to find insets for. + * + * @return The insets of the given JComponent. + */ + public Insets getInsets(JComponent c) + { + return c.getInsets(); + } + + /** + * This method deiconizes the JInternalFrame associated with the JDesktopIcon. + */ + public void deiconize() + { + try + { + frame.setIcon(false); + } + catch (PropertyVetoException pve) + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java new file mode 100644 index 0000000..b15700d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -0,0 +1,464 @@ +/* BasicDesktopPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.beans.PropertyVetoException; + +import javax.swing.AbstractAction; +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.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.DesktopPaneUI; + +/** + * This class is the UI delegate for JDesktopPane for the Basic look and feel. + */ +public class BasicDesktopPaneUI extends DesktopPaneUI +{ + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be closed. + */ + protected class CloseAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setClosed(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isClosable(); + return false; + } + } + + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be maximized. + */ + protected class MaximizeAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setMaximum(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isMaximizable(); + return false; + } + } + + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be minimized. + */ + protected class MinimizeAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setIcon(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isIconifiable(); + return false; + } + } + + /** + * This helper class is used to handle key events that pass the SELECTED + * property to the next JInternalFrame in the JDesktopPane's list of + * children. + */ + protected class NavigateAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // This is supposed to set the next selected frame. + JInternalFrame[] frames = desktop.getAllFrames(); + if (frames.length == 0) + return; + + JInternalFrame sFrame = frames[0]; + if (desktop.getSelectedFrame() != null) + sFrame = desktop.getSelectedFrame(); + + int i = 0; + for (; i < frames.length; i++) + if (frames[i] == sFrame) + break; + + // FIXME: Navigate actions go reverse too. + if (i == frames.length) + i = 0; + + desktop.setSelectedFrame(frames[i]); + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether this action is enabled. + */ + public boolean isEnabled() + { + // Always true. + return true; + } + } + + /** + * This helper class is used to restore the JInternalFrame to its original + * size before maximizing or iconifying. + */ + protected class OpenAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + JInternalFrame frame = desktop.getSelectedFrame(); + if (frame != null) + { + try + { + if (frame.isIcon()) + frame.setIcon(false); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether this action is enabled. + */ + public boolean isEnabled() + { + // JInternalFrames are always restorable. + return true; + } + } + + /** + * The KeyStroke associated with closing JInternalFrames. + * @deprecated + */ + protected KeyStroke closeKey; + + /** + * The KeyStroke associated with maximizing JInternalFrames. + * @deprecated + */ + protected KeyStroke maximizeKey; + + /** + * The KeyStroke associated with minimizing JInternalFrames. + * @deprecated + */ + protected KeyStroke minimizeKey; + + /** + * The KeyStroke associated with navigating (forward?) through + * JInternalFrames. + * @deprecated + */ + protected KeyStroke navigateKey; + + /** + * The KeyStroke associated with navigating (backward?) through + * JInternalFrames. + * @deprecated + */ + protected KeyStroke navigateKey2; + + /** The default desktop manager used with JDesktopPane. */ + protected DesktopManager desktopManager; + + /** The JDesktopPane this UI is used with. */ + protected JDesktopPane desktop; + + /** + * Creates a new BasicDesktopPaneUI object. + */ + public BasicDesktopPaneUI() + { + } + + /** + * This method creates a BasicDesktopPaneUI for the given JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicDesktopPaneUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicDesktopPaneUI(); + } + + /** + * This method returns the maximum size for the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size for the given JComponent. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size for the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size for the given JComponent. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size for the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size for the given JComponent. + */ + public Dimension getPreferredSize(JComponent c) + { + // return null because JDesktopPanes don't have preferred sizes. + return null; + } + + /** + * This method installs the defaults for the JDesktopPane provided by the + * current look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + desktop.setBackground(defaults.getColor("Desktop.background")); + } + + /** + * This method installs the desktop manager for the JDesktopPane. + */ + protected void installDesktopManager() + { + desktopManager = new DefaultDesktopManager(); + desktop.setDesktopManager(desktopManager); + } + + /** + * This method installs the keyboard actions for the JDesktopPane. + */ + protected void installKeyboardActions() + { + // FIXME: create actions and keystrokes. + registerKeyboardAction(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JDesktopPane) + { + desktop = (JDesktopPane) c; + + installDefaults(); + installDesktopManager(); + installKeyboardActions(); + } + } + + /** + * This method registers the actions to the appropriate Action and Input + * maps. + */ + protected void registerKeyboardAction() + { + // FIXME: Do the binding. + // XXX: the gtk windows tend to intercept a lot of the + // key events for themselves. must figure a way past that + // before binding + } + + /** + * This method reverses the work done by the installDefaults method. + */ + protected void uninstallDefaults() + { + desktop.setBackground(null); + } + + /** + * This method reverses the work done by the installDesktopManager method. + */ + protected void uninstallDesktopManager() + { + desktopManager = null; + desktop.setDesktopManager(null); + } + + /** + * This method reverses the work done by the installKeyboardActions method. + */ + protected void uninstallKeyboardActions() + { + unregisterKeyboardActions(); + // FIXME: null the actions and keystrokes. + } + + /** + * This method reverses the work done by the registerKeyboardActions method. + */ + protected void unregisterKeyboardActions() + { + // FIXME: unmap the keystrokes + } + + /** + * This method uninstalls the UI for the given JComponent. It should reverse + * all the work done by the installUI method. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallDesktopManager(); + uninstallDefaults(); + + desktop = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java b/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java new file mode 100644 index 0000000..a694f32 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -0,0 +1,313 @@ +/* BasicDirectoryModel.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.basic; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Vector; +import javax.swing.AbstractListModel; +import javax.swing.JFileChooser; +import javax.swing.event.ListDataEvent; +import javax.swing.filechooser.FileSystemView; + + +/** + * DOCUMENT ME! + */ +public class BasicDirectoryModel extends AbstractListModel + implements PropertyChangeListener +{ + /** DOCUMENT ME! */ + private Vector contents; + + /** DOCUMENT ME! */ + private int directories; + + /** DOCUMENT ME! */ + private int listingMode; + + /** DOCUMENT ME! */ + private JFileChooser filechooser; + + /** DOCUMENT ME! */ + private Comparator comparator = new Comparator() + { + public int compare(Object o1, Object o2) + { + if (lt((File) o1, (File) o2)) + return -1; + else + return 1; + } + }; + + /** + * Creates a new BasicDirectoryModel object. + * + * @param filechooser DOCUMENT ME! + */ + public BasicDirectoryModel(JFileChooser filechooser) + { + this.filechooser = filechooser; + filechooser.addPropertyChangeListener(this); + listingMode = filechooser.getFileSelectionMode(); + contents = new Vector(); + } + + /** + * DOCUMENT ME! + * + * @param o DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean contains(Object o) + { + return contents.contains(o); + } + + /** + * DOCUMENT ME! + */ + public void fireContentsChanged() + { + fireContentsChanged(this, 0, getSize() - 1); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Vector getDirectories() + { + Vector tmp = new Vector(); + for (int i = 0; i < directories; i++) + tmp.add(contents.get(i)); + return tmp; + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Object getElementAt(int index) + { + if (index > getSize() - 1) + return null; + if (listingMode == JFileChooser.FILES_ONLY) + return contents.get(directories + index); + else + return contents.elementAt(index); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Vector getFiles() + { + Vector tmp = new Vector(); + for (int i = directories; i < getSize(); i++) + tmp.add(contents.get(i)); + return tmp; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getSize() + { + if (listingMode == JFileChooser.DIRECTORIES_ONLY) + return directories; + else if (listingMode == JFileChooser.FILES_ONLY) + return contents.size() - directories; + return contents.size(); + } + + /** + * DOCUMENT ME! + * + * @param o DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int indexOf(Object o) + { + if (listingMode == JFileChooser.FILES_ONLY) + return contents.indexOf(o) - directories; + return contents.indexOf(o); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void intervalAdded(ListDataEvent e) + { + // obsoleted + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void intervalRemoved(ListDataEvent e) + { + // obsoleted + } + + /** + * DOCUMENT ME! + */ + public void invalidateFileCache() + { + // obsoleted + } + + /** + * DOCUMENT ME! + * + * @param a DOCUMENT ME! + * @param b DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected boolean lt(File a, File b) + { + boolean aTrav = filechooser.isTraversable(a); + boolean bTrav = filechooser.isTraversable(b); + + if (aTrav == bTrav) + { + String aname = a.getName().toLowerCase(); + String bname = b.getName().toLowerCase(); + return ((aname.compareTo(bname) < 0) ? true : false); + } + else + { + if (aTrav) + return true; + else + return false; + } + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) + listingMode = filechooser.getFileSelectionMode(); + } + + /** + * DOCUMENT ME! + * + * @param oldFile DOCUMENT ME! + * @param newFile DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean renameFile(File oldFile, File newFile) + { + // FIXME: implement + return false; + } + + /** + * DOCUMENT ME! + * + * @param v DOCUMENT ME! + */ + protected void sort(Vector v) + { + Collections.sort(v, comparator); + Enumeration e = Collections.enumeration(v); + Vector tmp = new Vector(); + for (; e.hasMoreElements();) + tmp.add(e.nextElement()); + + contents = tmp; + } + + /** + * DOCUMENT ME! + */ + public void validateFileCache() + { + contents.clear(); + directories = 0; + FileSystemView fsv = filechooser.getFileSystemView(); + File[] list = fsv.getFiles(filechooser.getCurrentDirectory(), + filechooser.isFileHidingEnabled()); + + if (list == null) + return; + + for (int i = 0; i < list.length; i++) + { + if (list[i] == null) + continue; + if (filechooser.accept(list[i])) + { + contents.add(list[i]); + if (filechooser.isTraversable(list[i])) + directories++; + } + } + sort(contents); + filechooser.revalidate(); + filechooser.repaint(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java new file mode 100644 index 0000000..6dd15a8 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java @@ -0,0 +1,68 @@ +/* BasicEditorPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicEditorPaneUI extends BasicTextUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicEditorPaneUI(); + } + + public BasicEditorPaneUI() + { + // Do nothing here. + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "EditorPane"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java new file mode 100644 index 0000000..fd34fbd --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -0,0 +1,1921 @@ +/* BasicFileChooserUI.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.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +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; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +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; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.ListCellRenderer; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.FileChooserUI; + + +/** + * DOCUMENT ME! + */ +public class BasicFileChooserUI extends FileChooserUI +{ + /** + * DOCUMENT ME! + */ + protected class AcceptAllFileFilter extends FileFilter + { + public AcceptAllFileFilter() + { + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean accept(File f) + { + return true; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDescription() + { + return acceptAllFileFilterText; + } + } + + /** + * DOCUMENT ME! + */ + protected class ApproveSelectionAction extends AbstractAction + { + /** + * Creates a new ApproveSelectionAction object. + */ + protected ApproveSelectionAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + Object obj = filelist.getSelectedValue(); + if (obj != null) + { + File f = filechooser.getFileSystemView().createFileObject(obj + .toString()); + if (filechooser.isTraversable(f) && + filechooser.getFileSelectionMode() == JFileChooser.FILES_ONLY) + filechooser.setCurrentDirectory(f); + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } + } + } + } + + /** + * DOCUMENT ME! + */ + protected class BasicFileView extends FileView + { + /** DOCUMENT ME! */ + protected Hashtable iconCache = new Hashtable(); + + public BasicFileView() + { + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * @param i DOCUMENT ME! + */ + public void cacheIcon(File f, Icon i) + { + iconCache.put(f, i); + } + + /** + * DOCUMENT ME! + */ + public void clearIconCache() + { + iconCache.clear(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getCachedIcon(File f) + { + return (Icon) iconCache.get(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDescription(File f) + { + return getName(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getIcon(File f) + { + Icon val = getCachedIcon(f); + if (val != null) + return val; + if (filechooser.isTraversable(f)) + val = directoryIcon; + else + val = fileIcon; + cacheIcon(f, val); + return val; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getName(File f) + { + return f.getName(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getTypeDescription(File f) + { + if (filechooser.isTraversable(f)) + return dirDescText; + else + return fileDescText; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Boolean isHidden(File f) + { + return new Boolean(filechooser.getFileSystemView().isHiddenFile(f)); + } + } + + /** + * DOCUMENT ME! + */ + protected class CancelSelectionAction extends AbstractAction + { + /** + * Creates a new CancelSelectionAction object. + */ + protected CancelSelectionAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.cancelSelection(); + closeDialog(); + } + } + + /** + * DOCUMENT ME! + */ + protected class ChangeToParentDirectoryAction extends AbstractAction + { + /** + * Creates a new ChangeToParentDirectoryAction object. + */ + protected ChangeToParentDirectoryAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.changeToParentDirectory(); + filechooser.revalidate(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class DoubleClickListener extends MouseAdapter + { + /** DOCUMENT ME! */ + private Timer timer = null; + + /** DOCUMENT ME! */ + private Object lastSelected = null; + + /** DOCUMENT ME! */ + private JList list = null; + + /** + * Creates a new DoubleClickListener object. + * + * @param list DOCUMENT ME! + */ + public DoubleClickListener(JList list) + { + this.list = list; + timer = new Timer(1000, null); + timer.setRepeats(false); + lastSelected = list.getSelectedValue(); + setDirectorySelected(false); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseClicked(MouseEvent e) + { + if (list.getSelectedValue() == null) + 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(); + } + } + 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(); + } + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseEntered(MouseEvent e) + { + // FIXME: Implement + } + } + + /** + * DOCUMENT ME! + */ + protected class GoHomeAction extends AbstractAction + { + /** + * Creates a new GoHomeAction object. + */ + protected GoHomeAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.setCurrentDirectory(filechooser.getFileSystemView() + .getHomeDirectory()); + filechooser.revalidate(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class NewFolderAction extends AbstractAction + { + /** + * Creates a new NewFolderAction object. + */ + protected NewFolderAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + try + { + filechooser.getFileSystemView().createNewFolder(filechooser + .getCurrentDirectory()); + } + catch (IOException ioe) + { + return; + } + filechooser.rescanCurrentDirectory(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class SelectionListener implements ListSelectionListener + { + /** + * Creates a new SelectionListener object. + */ + protected SelectionListener() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void valueChanged(ListSelectionEvent e) + { + Object f = filelist.getSelectedValue(); + if (f == null) + return; + File file = filechooser.getFileSystemView().createFileObject(f.toString()); + if (! filechooser.isTraversable(file)) + filechooser.setSelectedFile(file); + else + filechooser.setSelectedFile(null); + } + } + + /** + * DOCUMENT ME! + */ + protected class UpdateAction extends AbstractAction + { + /** + * Creates a new UpdateAction object. + */ + protected UpdateAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + } + } + + /** DOCUMENT ME! */ + protected int cancelButtonMnemonic; + + /** DOCUMENT ME! */ + protected String cancelButtonText; + + /** DOCUMENT ME! */ + protected String cancelButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon computerIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected Icon detailsViewIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + g.setColor(Color.GRAY); + g.drawRect(1, 1, 15, 20); + g.drawLine(17, 6, 23, 6); + g.drawLine(17, 12, 23, 12); + g.drawLine(17, 18, 23, 18); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon directoryIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point ap = new Point(3, 7); + Point bp = new Point(3, 21); + Point cp = new Point(21, 21); + Point dp = new Point(21, 12); + Point ep = new Point(16, 12); + Point fp = new Point(13, 7); + + Polygon dir = new Polygon(new int[] { ap.x, bp.x, cp.x, dp.x, ep.x, fp.x }, + new int[] { ap.y, bp.y, cp.y, dp.y, ep.y, fp.y }, + 6); + + g.setColor(new Color(153, 204, 255)); + g.fillPolygon(dir); + g.setColor(Color.BLACK); + g.drawPolygon(dir); + + g.translate(-x, -y); + g.setColor(saved); + } + }; + + /** DOCUMENT ME! */ + protected int directoryOpenButtonMnemonic; + + /** DOCUMENT ME! */ + protected String directoryOpenButtonText; + + /** DOCUMENT ME! */ + protected String directoryOpenButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon fileIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(5, 4); + Point b = new Point(5, 20); + Point d = new Point(19, 20); + Point e = new Point(19, 7); + Point f = new Point(16, 4); + + Polygon p = new Polygon(new int[] { a.x, b.x, d.x, e.x, f.x, }, + new int[] { a.y, b.y, d.y, e.y, f.y }, 5); + + g.setColor(Color.WHITE); + g.fillPolygon(p); + g.setColor(Color.BLACK); + g.drawPolygon(p); + + g.drawLine(16, 4, 14, 6); + g.drawLine(14, 6, 19, 7); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon floppyDriveIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected Icon hardDriveIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected int helpButtonMnemonic; + + /** DOCUMENT ME! */ + protected String helpButtonText; + + /** DOCUMENT ME! */ + protected String helpButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon homeFolderIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(12, 3); + Point b = new Point(4, 10); + Point d = new Point(20, 10); + + Polygon p = new Polygon(new int[] { a.x, b.x, d.x }, + new int[] { a.y, b.y, d.y }, 3); + + g.setColor(new Color(104, 51, 0)); + g.fillPolygon(p); + g.setColor(Color.BLACK); + g.drawPolygon(p); + + g.setColor(Color.WHITE); + g.fillRect(8, 10, 8, 10); + g.setColor(Color.BLACK); + g.drawRect(8, 10, 8, 10); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon listViewIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + // Not needed. Only simplifies things until we get real icons. + private void paintPartial(Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + g.setColor(Color.GRAY); + g.drawRect(1, 1, 7, 10); + g.drawLine(8, 6, 11, 6); + + g.setColor(saved); + g.translate(-x, -y); + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + paintPartial(g, 0, 0); + paintPartial(g, 12, 0); + paintPartial(g, 0, 12); + paintPartial(g, 12, 12); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon newFolderIcon = directoryIcon; + + /** DOCUMENT ME! */ + protected int openButtonMnemonic; + + /** DOCUMENT ME! */ + protected String openButtonText; + + /** DOCUMENT ME! */ + protected String openButtonToolTipText; + + /** DOCUMENT ME! */ + protected int saveButtonMnemonic; + + /** DOCUMENT ME! */ + protected String saveButtonText; + + /** DOCUMENT ME! */ + protected String saveButtonToolTipText; + + /** DOCUMENT ME! */ + protected int updateButtonMnemonic; + + /** DOCUMENT ME! */ + protected String updateButtonText; + + /** DOCUMENT ME! */ + protected String updateButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon upFolderIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component comp, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(3, 7); + Point b = new Point(3, 21); + Point c = new Point(21, 21); + Point d = new Point(21, 12); + Point e = new Point(16, 12); + Point f = new Point(13, 7); + + Polygon dir = new Polygon(new int[] { a.x, b.x, c.x, d.x, e.x, f.x }, + new int[] { a.y, b.y, c.y, d.y, e.y, f.y }, 6); + + g.setColor(new Color(153, 204, 255)); + g.fillPolygon(dir); + g.setColor(Color.BLACK); + g.drawPolygon(dir); + + a = new Point(12, 15); + b = new Point(9, 18); + c = new Point(15, 18); + + Polygon arrow = new Polygon(new int[] { a.x, b.x, c.x }, + new int[] { a.y, b.y, c.y }, 3); + + g.fillPolygon(arrow); + + g.drawLine(12, 15, 12, 22); + + g.translate(-x, -y); + g.setColor(saved); + } + }; + + // -- begin private, but package local since used in inner classes -- + + JFileChooser filechooser; + + /** DOCUMENT ME! */ + JList filelist; + + /** DOCUMENT ME! */ + JComboBox filters; + + /** DOCUMENT ME! */ + BasicDirectoryModel model; + + /** DOCUMENT ME! */ + FileFilter acceptAll = new AcceptAllFileFilter(); + + /** DOCUMENT ME! */ + FileView fv = new BasicFileView(); + + /** DOCUMENT ME! */ + static final int ICON_SIZE = 24; + + /** DOCUMENT ME! */ + JComboBox parents; + + /** DOCUMENT ME! */ + String filename; + + /** DOCUMENT ME! */ + JButton accept; + + /** DOCUMENT ME! */ + JButton cancel; + + /** DOCUMENT ME! */ + JButton upFolderButton; + + /** DOCUMENT ME! */ + JButton newFolderButton; + + /** DOCUMENT ME! */ + JButton homeFolderButton; + + /** DOCUMENT ME! */ + JPanel accessoryPanel; + + /** DOCUMENT ME! */ + PropertyChangeListener propertyChangeListener; + + /** DOCUMENT ME! */ + String acceptAllFileFilterText; + + /** DOCUMENT ME! */ + String dirDescText; + + /** DOCUMENT ME! */ + String fileDescText; + + /** DOCUMENT ME! */ + boolean dirSelected = false; + + /** DOCUMENT ME! */ + File currDir = null; + + JPanel bottomPanel; + + /** DOCUMENT ME! */ + JPanel closePanel; + + // -- end private -- + private class ListLabelRenderer + extends JLabel + implements ListCellRenderer + { + /** DOCUMENT ME! */ + final Color selected = new Color(153, 204, 255); + + /** + * Creates a new ListLabelRenderer object. + */ + public ListLabelRenderer() + { + 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); + File file = (File) value; + setText(filechooser.getName(file)); + setIcon(filechooser.getIcon(file)); + setBackground(isSelected ? selected : Color.WHITE); + setForeground(Color.BLACK); + + return this; + } + } + + /** + * DOCUMENT ME! + */ + 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); + if (owner instanceof JDialog) + ((JDialog) owner).dispose(); + } + + /** + * Creates a new BasicFileChooserUI object. + * + * @param b DOCUMENT ME! + */ + public BasicFileChooserUI(JFileChooser b) + { + this.filechooser = b; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicFileChooserUI((JFileChooser) c); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void installUI(JComponent c) + { + if (c instanceof JFileChooser) + { + JFileChooser fc = (JFileChooser) c; + fc.resetChoosableFileFilters(); + createModel(); + clearIconCache(); + installDefaults(fc); + installComponents(fc); + installListeners(fc); + } + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + model = null; + uninstallListeners(filechooser); + uninstallComponents(filechooser); + uninstallDefaults(filechooser); + filechooser = null; + } + + // FIXME: Indent the entries in the combobox + private void boxEntries() + { + ArrayList parentFiles = new ArrayList(); + File parent = filechooser.getCurrentDirectory(); + if (parent == null) + parent = filechooser.getFileSystemView().getDefaultDirectory(); + while (parent != null) + { + String name = parent.getName(); + if (name.equals("")) + name = parent.getAbsolutePath(); + + parentFiles.add(parentFiles.size(), name); + parent = parent.getParentFile(); + } + + if (parentFiles.size() == 0) + return; + + if (parents.getItemCount() > 0) + parents.removeAllItems(); + for (int i = parentFiles.size() - 1; i >= 0; i--) + parents.addItem(parentFiles.get(i)); + parents.setSelectedIndex(parentFiles.size() - 1); + parents.revalidate(); + parents.repaint(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private ItemListener createBoxListener() + { + return new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + if (parents.getItemCount() - 1 == parents.getSelectedIndex()) + return; + StringBuffer dir = new StringBuffer(); + for (int i = 0; i <= parents.getSelectedIndex(); i++) + { + dir.append(parents.getItemAt(i)); + dir.append(File.separatorChar); + } + filechooser.setCurrentDirectory(filechooser.getFileSystemView() + .createFileObject(dir + .toString())); + } + }; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private ItemListener createFilterListener() + { + return new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + int index = filters.getSelectedIndex(); + if (index == -1) + return; + filechooser.setFileFilter(filechooser.getChoosableFileFilters()[index]); + } + }; + } + + void filterEntries() + { + FileFilter[] list = filechooser.getChoosableFileFilters(); + if (filters.getItemCount() > 0) + filters.removeAllItems(); + + int index = -1; + String selected = filechooser.getFileFilter().getDescription(); + for (int i = 0; i < list.length; i++) + { + if (selected.equals(list[i].getDescription())) + index = i; + filters.addItem(list[i].getDescription()); + } + filters.setSelectedIndex(index); + filters.revalidate(); + filters.repaint(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void installComponents(JFileChooser fc) + { + JLabel look = new JLabel("Look In:"); + + parents = new JComboBox(); + parents.setRenderer(new CBLabelRenderer()); + boxEntries(); + look.setLabelFor(parents); + JPanel parentsPanel = new JPanel(); + parentsPanel.add(look); + parentsPanel.add(parents); + JPanel buttonPanel = new JPanel(); + + upFolderButton = new JButton(); + upFolderButton.setIcon(upFolderIcon); + buttonPanel.add(upFolderButton); + + homeFolderButton = new JButton(); + homeFolderButton = new JButton(homeFolderIcon); + buttonPanel.add(homeFolderButton); + + newFolderButton = new JButton(); + newFolderButton.setIcon(newFolderIcon); + buttonPanel.add(newFolderButton); + + ButtonGroup toggles = new ButtonGroup(); + JToggleButton listViewButton = new JToggleButton(); + listViewButton.setIcon(listViewIcon); + toggles.add(listViewButton); + buttonPanel.add(listViewButton); + + JToggleButton detailsViewButton = new JToggleButton(); + detailsViewButton.setIcon(detailsViewIcon); + toggles.add(detailsViewButton); + buttonPanel.add(detailsViewButton); + + JPanel topPanel = new JPanel(); + topPanel.setLayout(new java.awt.FlowLayout()); + topPanel.add(parentsPanel); + topPanel.add(buttonPanel); + + accessoryPanel = new JPanel(); + if (filechooser.getAccessory() != null) + accessoryPanel.add(filechooser.getAccessory(), BorderLayout.CENTER); + + filelist = new JList(model); + filelist.setVisibleRowCount(6); + JScrollPane scrollp = new JScrollPane(filelist); + scrollp.setPreferredSize(new Dimension(400, 175)); + filelist.setBackground(Color.WHITE); + + filelist.setLayoutOrientation(JList.VERTICAL_WRAP); + filelist.setCellRenderer(new ListLabelRenderer()); + + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + + JPanel centrePanel = new JPanel(); + centrePanel.setLayout(new GridBagLayout()); + centrePanel.add(scrollp, c); + + c.gridx = 1; + centrePanel.add(accessoryPanel, c); + + JLabel fileNameLabel = new JLabel("File Name:"); + JLabel fileTypesLabel = new JLabel("Files of Type:"); + + JTextField entry = new JTextField(); + filters = new JComboBox(); + filterEntries(); + + fileNameLabel.setLabelFor(entry); + fileNameLabel.setHorizontalTextPosition(SwingConstants.LEFT); + fileTypesLabel.setLabelFor(filters); + fileTypesLabel.setHorizontalTextPosition(SwingConstants.LEFT); + + closePanel = new JPanel(); + accept = getApproveButton(filechooser); + cancel = new JButton(cancelButtonText); + cancel.setMnemonic(cancelButtonMnemonic); + cancel.setToolTipText(cancelButtonToolTipText); + closePanel.add(accept); + closePanel.add(cancel); + + c.anchor = GridBagConstraints.WEST; + c.weighty = 0; + c.weightx = 0; + c.gridx = 0; + + bottomPanel = new JPanel(); + bottomPanel.setLayout(new GridBagLayout()); + bottomPanel.add(fileNameLabel, c); + + c.gridy = 1; + bottomPanel.add(fileTypesLabel, c); + c.gridx = 1; + c.gridy = 0; + c.weightx = 1; + c.weighty = 1; + bottomPanel.add(entry, c); + + c.gridy = 1; + bottomPanel.add(filters, c); + + c.fill = GridBagConstraints.NONE; + c.gridy = 2; + c.anchor = GridBagConstraints.EAST; + bottomPanel.add(closePanel, c); + + filechooser.setLayout(new BorderLayout()); + filechooser.add(topPanel, BorderLayout.NORTH); + filechooser.add(centrePanel, BorderLayout.CENTER); + filechooser.add(bottomPanel, BorderLayout.SOUTH); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void uninstallComponents(JFileChooser fc) + { + parents = null; + + accept = null; + cancel = null; + upFolderButton = null; + homeFolderButton = null; + newFolderButton = null; + + filelist = null; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installListeners(JFileChooser fc) + { + propertyChangeListener = createPropertyChangeListener(filechooser); + filechooser.addPropertyChangeListener(propertyChangeListener); + + //parents.addItemListener(createBoxListener()); + accept.addActionListener(getApproveSelectionAction()); + cancel.addActionListener(getCancelSelectionAction()); + upFolderButton.addActionListener(getChangeToParentDirectoryAction()); + homeFolderButton.addActionListener(getGoHomeAction()); + newFolderButton.addActionListener(getNewFolderAction()); + filters.addItemListener(createFilterListener()); + + filelist.addMouseListener(createDoubleClickListener(filechooser, filelist)); + filelist.addListSelectionListener(createListSelectionListener(filechooser)); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallListeners(JFileChooser fc) + { + filechooser.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installDefaults(JFileChooser fc) + { + installIcons(fc); + installStrings(fc); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallDefaults(JFileChooser fc) + { + uninstallStrings(fc); + uninstallIcons(fc); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installIcons(JFileChooser fc) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallIcons(JFileChooser fc) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installStrings(JFileChooser fc) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + acceptAllFileFilterText = defaults.getString("FileChooser.acceptAllFileFilterText"); + cancelButtonMnemonic = defaults.getInt("FileChooser.cancelButtonMnemonic"); + cancelButtonText = defaults.getString("FileChooser.cancelButtonText"); + cancelButtonToolTipText = defaults.getString("FileChooser.cancelButtonToolTipText"); + + dirDescText = defaults.getString("FileChooser.directoryDescriptionText"); + fileDescText = defaults.getString("FileChooser.fileDescriptionText"); + + helpButtonMnemonic = defaults.getInt("FileChooser.helpButtonMnemonic"); + helpButtonText = defaults.getString("FileChooser.helpButtonText"); + helpButtonToolTipText = defaults.getString("FileChooser.helpButtonToolTipText"); + + openButtonMnemonic = defaults.getInt("FileChooser.openButtonMnemonic"); + openButtonText = defaults.getString("FileChooser.openButtonText"); + openButtonToolTipText = defaults.getString("FileChooser.openButtonToolTipText"); + + saveButtonMnemonic = defaults.getInt("FileChooser.saveButtonMnemonic"); + saveButtonText = defaults.getString("FileChooser.saveButtonText"); + saveButtonToolTipText = defaults.getString("FileChooser.saveButtonToolTipText"); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallStrings(JFileChooser fc) + { + acceptAllFileFilterText = null; + cancelButtonMnemonic = 0; + cancelButtonText = null; + cancelButtonToolTipText = null; + + dirDescText = null; + fileDescText = null; + + helpButtonMnemonic = 0; + helpButtonText = null; + helpButtonToolTipText = null; + + openButtonMnemonic = 0; + openButtonText = null; + openButtonToolTipText = null; + + saveButtonMnemonic = 0; + saveButtonText = null; + saveButtonToolTipText = null; + } + + /** + * DOCUMENT ME! + */ + protected void createModel() + { + model = new BasicDirectoryModel(filechooser); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public BasicDirectoryModel getModel() + { + return model; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) + { + return new PropertyChangeListener() + { + 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)) + { + //boxEntries(); + filelist.clearSelection(); + filelist.revalidate(); + filelist.repaint(); + setDirectorySelected(false); + setDirectory(filechooser.getCurrentDirectory()); + } + 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! + */ + public String getFileName() + { + return filename; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDirectoryName() + { + // XXX: I don't see a case where the thing returns something non-null.. + return null; + } + + /** + * DOCUMENT ME! + * + * @param filename DOCUMENT ME! + */ + public void setFileName(String filename) + { + this.filename = filename; + } + + /** + * DOCUMENT ME! + * + * @param dirname DOCUMENT ME! + */ + public void setDirectoryName(String dirname) + { + // FIXME: Implement + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void rescanCurrentDirectory(JFileChooser fc) + { + getModel().validateFileCache(); + filelist.revalidate(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * @param f DOCUMENT ME! + */ + public void ensureFileIsVisible(JFileChooser fc, File f) + { + // XXX: Not sure what this does. + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JFileChooser getFileChooser() + { + return filechooser; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JPanel getAccessoryPanel() + { + return accessoryPanel; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JButton getApproveButton(JFileChooser fc) + { + accept = new JButton(getApproveButtonText(fc)); + accept.setMnemonic(getApproveButtonMnemonic(fc)); + accept.setToolTipText(getApproveButtonToolTipText(fc)); + return accept; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonToolTipText(JFileChooser fc) + { + if (fc.getApproveButtonToolTipText() != null) + return fc.getApproveButtonToolTipText(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonToolTipText; + else + return openButtonToolTipText; + } + + /** + * DOCUMENT ME! + */ + public void clearIconCache() + { + if (fv instanceof BasicFileView) + ((BasicFileView) fv).clearIconCache(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public ListSelectionListener createListSelectionListener(JFileChooser fc) + { + return new SelectionListener(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * @param list DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) + { + return new DoubleClickListener(list); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected boolean isDirectorySelected() + { + return dirSelected; + } + + /** + * DOCUMENT ME! + * + * @param selected DOCUMENT ME! + */ + protected void setDirectorySelected(boolean selected) + { + dirSelected = selected; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected File getDirectory() + { + return currDir; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + */ + protected void setDirectory(File f) + { + currDir = f; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileFilter getAcceptAllFileFilter(JFileChooser fc) + { + return acceptAll; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileView getFileView(JFileChooser fc) + { + if (fc.getFileView() != null) + return fc.getFileView(); + return fv; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDialogTitle(JFileChooser fc) + { + String ret = fc.getDialogTitle(); + if (ret != null) + return ret; + switch (fc.getDialogType()) + { + case JFileChooser.OPEN_DIALOG: + ret = openButtonText; + break; + case JFileChooser.SAVE_DIALOG: + ret = saveButtonText; + break; + default: + ret = fc.getApproveButtonText(); + break; + } + if (ret == null) + ret = openButtonText; + return ret; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getApproveButtonMnemonic(JFileChooser fc) + { + if (fc.getApproveButtonMnemonic() != 0) + return fc.getApproveButtonMnemonic(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonMnemonic; + else + return openButtonMnemonic; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonText(JFileChooser fc) + { + if (fc.getApproveButtonText() != null) + return fc.getApproveButtonText(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonText; + else + return openButtonText; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getNewFolderAction() + { + return new NewFolderAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getGoHomeAction() + { + return new GoHomeAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getChangeToParentDirectoryAction() + { + return new ChangeToParentDirectoryAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getApproveSelectionAction() + { + return new ApproveSelectionAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getCancelSelectionAction() + { + return new CancelSelectionAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getUpdateAction() + { + return new UpdateAction(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java new file mode 100644 index 0000000..3abd76f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java @@ -0,0 +1,62 @@ +/* BasicFormattedTextFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +/** + * @since 1.4 + */ +public class BasicFormattedTextFieldUI extends BasicTextFieldUI +{ + public BasicFormattedTextFieldUI() + { + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicFormattedTextFieldUI(); + } + + protected String getPropertyPrefix() + { + return "FormattedTextField"; + } +} \ No newline at end of file diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java new file mode 100644 index 0000000..78ee62f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java @@ -0,0 +1,641 @@ +/* BasicGraphicsUtils.java + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; + +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + + +/** + * A utility class providing commonly used drawing and measurement + * routines. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BasicGraphicsUtils +{ + /** + * Constructor. It is utterly unclear why this class should + * be constructable, but this is what the API specification + * says. + */ + public BasicGraphicsUtils() + { + } + + + /** + * Draws a rectangle that appears etched into the surface, given + * four colors that are used for drawing. + * + *

[An illustration that shows which pixels
+   * get painted in what color] + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting + * the outer side of the top and left edges. + * + * @param darkShadow the color that will be used for painting + * the inner side of the top and left edges. + * + * @param highlight the color that will be used for painting + * the inner side of the bottom and right edges. + * + * @param lightHighlight the color that will be used for painting + * the outer side of the bottom and right edges. + * + * @see #getEtchedInsets() + * @see javax.swing.border.EtchedBorder + */ + public static void drawEtchedRect(Graphics g, + int x, int y, int width, int height, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + Color oldColor; + int x2, y2; + + oldColor = g.getColor(); + x2 = x + width - 1; + y2 = y + height - 1; + + try + { + /* To understand this code, it might be helpful to look at the + * image "BasicGraphicsUtils-1.png" that is included with the + * JavaDoc. The file is located in the "doc-files" subdirectory. + * + * (x2, y2) is the coordinate of the most right and bottom pixel + * to be painted. + */ + g.setColor(shadow); + g.drawLine(x, y, x2 - 1, y); // top, outer + g.drawLine(x, y + 1, x, y2 - 1); // left, outer + + g.setColor(darkShadow); + g.drawLine(x + 1, y + 1, x2 - 2, y + 1); // top, inner + g.drawLine(x + 1, y + 2, x + 1, y2 - 2); // left, inner + + g.setColor(highlight); + g.drawLine(x + 1, y2 - 1, x2 - 1, y2 - 1); // bottom, inner + g.drawLine(x2 - 1, y + 1, x2 - 1, y2 - 2); // right, inner + + g.setColor(lightHighlight); + g.drawLine(x, y2, x2, y2); // bottom, outer + g.drawLine(x2, y, x2, y2 - 1); // right, outer + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Determines the width of the border that gets painted by + * {@link #drawEtchedRect}. + * + * @return an Insets object whose top, + * left, bottom and + * right field contain the border width at the + * respective edge in pixels. + */ + public static Insets getEtchedInsets() + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Draws a rectangle that appears etched into the surface, given + * two colors that are used for drawing. + * + *

[An illustration that shows which pixels
+   * get painted in what color] + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting the outer + * side of the top and left edges, and for the inner side of + * the bottom and right ones. + * + * @param highlight the color that will be used for painting the + * inner side of the top and left edges, and for the outer + * side of the bottom and right ones. + * + * @see #getGrooveInsets() + * @see javax.swing.border.EtchedBorder + */ + public static void drawGroove(Graphics g, + int x, int y, int width, int height, + Color shadow, Color highlight) + { + /* To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-2.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + drawEtchedRect(g, x, y, width, height, + /* outer topLeft */ shadow, + /* inner topLeft */ highlight, + /* inner bottomRight */ shadow, + /* outer bottomRight */ highlight); + } + + + /** + * Determines the width of the border that gets painted by + * {@link #drawGroove}. + * + * @return an Insets object whose top, + * left, bottom and + * right field contain the border width at the + * respective edge in pixels. + */ + public static Insets getGrooveInsets() + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Draws a border that is suitable for buttons of the Basic look and + * feel. + * + *

[An illustration that shows which pixels
+   * get painted in what color] + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param isPressed true to draw the button border + * with a pressed-in appearance; false for + * normal (unpressed) appearance. + * + * @param isDefault true to draw the border with + * the appearance it has when hitting the enter key in a + * dialog will simulate a click to this button; + * false for normal appearance. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public static void drawBezel(Graphics g, + int x, int y, int width, int height, + boolean isPressed, boolean isDefault, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + Color oldColor = g.getColor(); + + /* To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-3.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + try + { + if ((isPressed == false) && (isDefault == false)) + { + drawEtchedRect(g, x, y, width, height, + lightHighlight, highlight, + shadow, darkShadow); + } + + if ((isPressed == true) && (isDefault == false)) + { + g.setColor(shadow); + g.drawRect(x + 1, y + 1, width - 2, height - 2); + } + + if ((isPressed == false) && (isDefault == true)) + { + g.setColor(darkShadow); + g.drawRect(x, y, width - 1, height - 1); + drawEtchedRect(g, x + 1, y + 1, width - 2, height - 2, + lightHighlight, highlight, + shadow, darkShadow); + } + + if ((isPressed == true) && (isDefault == true)) + { + g.setColor(darkShadow); + g.drawRect(x, y, width - 1, height - 1); + g.setColor(shadow); + g.drawRect(x + 1, y + 1, width - 3, height - 3); + } + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Draws a rectangle that appears lowered into the surface, given + * four colors that are used for drawing. + * + *

[An illustration that shows which pixels
+   * get painted in what color] + * + *

Compatibility with the Sun reference + * implementation: The Sun reference implementation seems + * to ignore the x and y arguments, at + * least in JDK 1.3.1 and 1.4.1_01. The method always draws the + * rectangular area at location (0, 0). A bug report has been filed + * with Sun; its “bug ID” is 4880003. The GNU Classpath + * implementation behaves correctly, thus not replicating this bug. + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting + * the inner side of the top and left edges. + * + * @param darkShadow the color that will be used for painting + * the outer side of the top and left edges. + * + * @param highlight the color that will be used for painting + * the inner side of the bottom and right edges. + * + * @param lightHighlight the color that will be used for painting + * the outer side of the bottom and right edges. + */ + public static void drawLoweredBezel(Graphics g, + int x, int y, int width, int height, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* Like drawEtchedRect, but swapping darkShadow and shadow. + * + * To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-4.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + drawEtchedRect(g, x, y, width, height, + darkShadow, shadow, + highlight, lightHighlight); + } + + + /** + * Draws a String at the given location, underlining the first + * occurence of a specified character. The algorithm for determining + * the underlined position is not sensitive to case. If the + * character is not part of text, the text will be + * drawn without underlining. Drawing is performed in the current + * color and font of g. + * + *

[An illustration showing how to use the
+   * method] + * + * @param g the graphics into which the String is drawn. + * + * @param text the String to draw. + * + * @param underlinedChar the character whose first occurence in + * text will be underlined. It is not clear + * why the API specification declares this argument to be + * of type int instead of char. + * While this would allow to pass Unicode characters outside + * Basic Multilingual Plane 0 (U+0000 .. U+FFFE), at least + * the GNU Classpath implementation does not underline + * anything if underlinedChar is outside + * the range of char. + * + * @param x the x coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @param y the y coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + */ + public static void drawString(Graphics g, String text, + int underlinedChar, int x, int y) + { + int index = -1; + + /* It is intentional that lower case is used. In some languages, + * the set of lowercase characters is larger than the set of + * uppercase ones. Therefore, it is good practice to use lowercase + * for such comparisons (which really means that the author of this + * code can vaguely remember having read some Unicode techreport + * with this recommendation, but is too lazy to look for the URL). + */ + if ((underlinedChar >= 0) || (underlinedChar <= 0xffff)) + index = text.toLowerCase().indexOf( + Character.toLowerCase((char) underlinedChar)); + + drawStringUnderlineCharAt(g, text, index, x, y); + } + + + /** + * Draws a String at the given location, underlining the character + * at the specified index. Drawing is performed in the current color + * and font of g. + * + *

[An illustration showing how to use the
+   * method] + * + * @param g the graphics into which the String is drawn. + * + * @param text the String to draw. + * + * @param underlinedIndex the index of the underlined character in + * text. If underlinedIndex falls + * outside the range [0, text.length() - 1], the + * text will be drawn without underlining anything. + * + * @param x the x coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @param y the y coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @since 1.4 + */ + public static void drawStringUnderlineCharAt(Graphics g, String text, + int underlinedIndex, + int x, int y) + { + Graphics2D g2; + Rectangle2D.Double underline; + FontRenderContext frc; + FontMetrics fmet; + LineMetrics lineMetrics; + Font font; + TextLayout layout; + double underlineX1, underlineX2; + boolean drawUnderline; + int textLength; + + textLength = text.length(); + if (textLength == 0) + return; + + drawUnderline = (underlinedIndex >= 0) && (underlinedIndex < textLength); + + // FIXME: unfortunately pango and cairo can't agree on metrics + // so for the time being we continue to *not* use TextLayouts. + if (true || !(g instanceof Graphics2D)) + { + /* Fall-back. This is likely to produce garbage for any text + * containing right-to-left (Hebrew or Arabic) characters, even + * if the underlined character is left-to-right. + */ + g.drawString(text, x, y); + if (drawUnderline) + { + fmet = g.getFontMetrics(); + g.fillRect( + /* x */ x + fmet.stringWidth(text.substring(0, underlinedIndex)), + /* y */ y + fmet.getDescent() - 1, + /* width */ fmet.charWidth(text.charAt(underlinedIndex)), + /* height */ 1); + } + + return; + } + + g2 = (Graphics2D) g; + font = g2.getFont(); + frc = g2.getFontRenderContext(); + lineMetrics = font.getLineMetrics(text, frc); + layout = new TextLayout(text, font, frc); + + /* Draw the text. */ + layout.draw(g2, x, y); + if (!drawUnderline) + return; + + underlineX1 = x + layout.getLogicalHighlightShape( + underlinedIndex, underlinedIndex).getBounds2D().getX(); + underlineX2 = x + layout.getLogicalHighlightShape( + underlinedIndex + 1, underlinedIndex + 1).getBounds2D().getX(); + + underline = new Rectangle2D.Double(); + if (underlineX1 < underlineX2) + { + underline.x = underlineX1; + underline.width = underlineX2 - underlineX1; + } + else + { + underline.x = underlineX2; + underline.width = underlineX1 - underlineX2; + } + + + underline.height = lineMetrics.getUnderlineThickness(); + underline.y = lineMetrics.getUnderlineOffset(); + if (underline.y == 0) + { + /* Some fonts do not specify an underline offset, although they + * actually should do so. In that case, the result of calling + * lineMetrics.getUnderlineOffset() will be zero. Since it would + * look very ugly if the underline was be positioned immediately + * below the baseline, we check for this and move the underline + * below the descent, as shown in the following ASCII picture: + * + * ##### ##### # + * # # # # + * # # # # + * # # # # + * ##### ###### ---- baseline (0) + * # + * # + * ------------------###----------- lineMetrics.getDescent() + */ + underline.y = lineMetrics.getDescent(); + } + + underline.y += y; + g2.fill(underline); + } + + + /** + * Draws a rectangle, simulating a dotted stroke by painting only + * every second pixel along the one-pixel thick edge. The color of + * those pixels is the current color of the Graphics g. + * Any other pixels are left unchanged. + * + *

[An illustration that shows which pixels
+   * get painted] + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + */ + public static void drawDashedRect(Graphics g, + int x, int y, int width, int height) + { + int right = x + width - 1; + int bottom = y + height - 1; + + /* Draw the top and bottom edge of the dotted rectangle. */ + for (int i = x; i <= right; i += 2) + { + g.drawLine(i, y, i, y); + g.drawLine(i, bottom, i, bottom); + } + + /* Draw the left and right edge of the dotted rectangle. */ + for (int i = y; i <= bottom; i += 2) + { + g.drawLine(x, i, x, i); + g.drawLine(right, i, right, i); + } + } + + + /** + * Determines the preferred width and height of an AbstractButton, + * given the gap between the button’s text and icon. + * + * @param b the button whose preferred size is determined. + * + * @param textIconGap the gap between the button’s text and + * icon. + * + * @return a Dimension object whose width + * and height fields indicate the preferred + * extent in pixels. + * + * @see javax.swing.SwingUtilities#layoutCompoundLabel(JComponent, + * FontMetrics, String, Icon, int, int, int, int, Rectangle, Rectangle, + * Rectangle, int) + */ + public static Dimension getPreferredButtonSize(AbstractButton b, + int textIconGap) + { + Rectangle contentRect; + Rectangle viewRect; + Rectangle iconRect = new Rectangle(); + Rectangle textRect = new Rectangle(); + Insets insets = b.getInsets(); + + viewRect = new Rectangle(); + + /* java.awt.Toolkit.getFontMetrics is deprecated. However, it + * seems not obvious how to get to the correct FontMetrics object + * otherwise. The real problem probably is that the method + * javax.swing.SwingUtilities.layoutCompundLabel should take a + * LineMetrics, not a FontMetrics argument. But fixing this that + * would change the public API. + */ + SwingUtilities.layoutCompoundLabel( + b, // for the component orientation + b.getToolkit().getFontMetrics(b.getFont()), // see comment above + b.getText(), + b.getIcon(), + b.getVerticalAlignment(), + b.getHorizontalAlignment(), + b.getVerticalTextPosition(), + b.getHorizontalTextPosition(), + viewRect, iconRect, textRect, + textIconGap); + + /* +------------------------+ +------------------------+ + * | | | | + * | ICON | | CONTENTCONTENTCONTENT | + * | TEXTTEXTTEXT | --> | CONTENTCONTENTCONTENT | + * | TEXTTEXTTEXT | | CONTENTCONTENTCONTENT | + * +------------------------+ +------------------------+ + */ + + contentRect = textRect.union(iconRect); + + return new Dimension(insets.left + + contentRect.width + + insets.right, + insets.top + + contentRect.height + + insets.bottom); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java new file mode 100644 index 0000000..e7aad89 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java @@ -0,0 +1,238 @@ +/* BasicIconFactory.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.AbstractButton; +import javax.swing.Icon; +import javax.swing.UIDefaults; +import javax.swing.UIManager; + +/** + * STUBBED + */ +public class BasicIconFactory implements Serializable +{ + static final long serialVersionUID = 5605588811185324383L; + + private static class DummyIcon + implements Icon + { + public int getIconHeight() { return 10; } + public int getIconWidth() { return 10; } + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color save = g.getColor(); + g.setColor(c.getForeground()); + g.drawRect(x, y, 10, 10); + g.setColor(save); + } + } + + + public BasicIconFactory() + { + } + public static Icon getMenuItemCheckIcon() + { + return new DummyIcon(); + } + public static Icon getMenuItemArrowIcon() + { + return new DummyIcon(); + } + public static Icon getMenuArrowIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 12; + } + + public int getIconWidth() + { + return 12; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + + Color saved = g.getColor(); + + g.setColor(Color.BLACK); + + g.fillPolygon(new Polygon(new int[] { 3, 9, 3 }, + new int[] { 2, 6, 10 }, + 3)); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + } + + public static Icon getCheckBoxIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 10; + } + public int getIconWidth() + { + return 10; + } + public void paintIcon(Component c, Graphics g, int x, int y) + { + if (c instanceof AbstractButton) + { + UIDefaults defaults; + defaults = UIManager.getLookAndFeelDefaults(); + Color hi = defaults.getColor("CheckBox.highlight"); + Color low = defaults.getColor("CheckBox.darkShadow"); + Color sel = defaults.getColor("CheckBox.foreground"); + Color dim = defaults.getColor("CheckBox.shadow"); + Polygon check = new Polygon(new int[] {x+3, x+3, x+8}, + new int[] {y+5, y+9, y+3}, 3); + AbstractButton b = (AbstractButton) c; + Color saved = g.getColor(); + if (b.isEnabled()) + { + g.setColor(low); + g.drawRect(x, y, 10, 10); + g.setColor(hi); + g.drawRect(x+1, y+1, 10, 10); + if (b.isSelected()) + { + g.setColor(sel); + if (b.isSelected()) + { + g.drawLine(x+3, y+5, x+3, y+8); + g.drawLine(x+4, y+5, x+4, y+8); + g.drawLine(x+3, y+8, x+8, y+3); + g.drawLine(x+4, y+8, x+8, y+3); + } + } + } + else + { + g.setColor(hi); + g.drawRect(x, y, 10, 10); + if (b.isSelected()) + { + g.drawLine(x+3, y+5, x+3, y+9); + g.drawLine(x+3, y+9, x+8, y+3); + } + } + g.setColor(saved); + } + } + }; + } + + public static Icon getRadioButtonIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 12; + } + public int getIconWidth() + { + return 12; + } + public void paintIcon(Component c, Graphics g, int x, int y) + { + UIDefaults defaults; + defaults = UIManager.getLookAndFeelDefaults(); + Color hi = defaults.getColor("RadioButton.highlight"); + Color low = defaults.getColor("RadioButton.darkShadow"); + Color sel = defaults.getColor("RadioButton.foreground"); + Color dim = defaults.getColor("RadioButton.shadow"); + + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + Color saved = g.getColor(); + if (b.isEnabled()) + { + g.setColor(low); + g.drawOval(x, y, 12, 12); + g.setColor(hi); + g.drawOval(x+1, y+1, 12, 12); + if (b.isSelected()) + { + g.setColor(sel); + g.fillOval(x+4, y+4, 6, 6); + } + } + else + { + g.setColor(hi); + g.drawOval(x, y, 12, 12); + if (b.isSelected()) + g.fillOval(x+4, y+4, 6, 6); + } + g.setColor(saved); + } + } + }; + } + public static Icon getCheckBoxMenuItemIcon() + { + return getCheckBoxIcon(); + } + public static Icon getRadioButtonMenuItemIcon() + { + return getRadioButtonIcon(); + } + public static Icon createEmptyFrameIcon() + { + return new DummyIcon(); + } +} // class BasicIconFactory diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java new file mode 100644 index 0000000..91db0cb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -0,0 +1,940 @@ +/* BasicInternalFrameTitlePane.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +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; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; + +/** + * This class acts as a titlebar for JInternalFrames. + */ +public class BasicInternalFrameTitlePane extends JComponent +{ + /** + * The Action responsible for closing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class CloseAction extends AbstractAction + { + /** + * This method is called when something closes the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isClosable()) + { + try + { + frame.setClosed(true); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This Action is responsible for iconifying the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class IconifyAction extends AbstractAction + { + /** + * This method is called when the user wants to iconify the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isIconifiable() && ! frame.isIcon()) + { + try + { + frame.setIcon(true); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This Action is responsible for maximizing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MaximizeAction extends AbstractAction + { + /** + * This method is called when the user wants to maximize the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + try + { + if (frame.isMaximizable() && ! frame.isMaximum()) + frame.setMaximum(true); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This Action is responsible for dragging the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MoveAction extends AbstractAction + { + /** + * This method is called when the user wants to drag the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // FIXME: Implement keyboard driven? move actions. + } + } + + /** + * This Action is responsible for restoring the JInternalFrame. Restoring + * the JInternalFrame is the same as setting the maximum property to false. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class RestoreAction extends AbstractAction + { + /** + * This method is called when the user wants to restore the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isMaximum()) + { + try + { + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This action is responsible for sizing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class SizeAction extends AbstractAction + { + /** + * This method is called when the user wants to resize the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // FIXME: Not sure how size actions should be handled. + } + } + + /** + * This class is responsible for handling property change events from the + * JInternalFrame and adjusting the Title Pane as necessary. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when a PropertyChangeEvent is received by the + * Title Pane. + * + * @param evt The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent evt) + { + String propName = evt.getPropertyName(); + if (propName.equals("closable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + closeButton.setVisible(true); + else + closeButton.setVisible(false); + } + else if (propName.equals("iconifiable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + iconButton.setVisible(true); + else + iconButton.setVisible(false); + } + else if (propName.equals("maximizable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + maxButton.setVisible(true); + else + maxButton.setVisible(false); + } + + } + } + + /** + * This class acts as the MenuBar for the TitlePane. Clicking on the Frame + * Icon in the top left corner will activate it. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class SystemMenuBar extends JMenuBar + { + /** + * This method returns true if it can receive focus. + * + * @return True if this Component can receive focus. + */ + public boolean isFocusTransversable() + { + return true; + } + + /** + * This method returns true if this Component is expected to paint all of + * itself. + * + * @return True if this Component is expect to paint all of itself. + */ + public boolean isOpaque() + { + return true; + } + + /** + * This method paints this Component. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + Icon frameIcon = frame.getFrameIcon(); + if (frameIcon == null) + frameIcon = BasicDesktopIconUI.defaultIcon; + frameIcon.paintIcon(this, g, 0, 0); + } + + /** + * This method requests that focus be given to this Component. + */ + public void requestFocus() + { + super.requestFocus(); + } + } + + /** + * This class acts as the Layout Manager for the TitlePane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TitlePaneLayout implements LayoutManager + { + /** + * Creates a new TitlePaneLayout object. + */ + public TitlePaneLayout() + { + // Do nothing. + } + + /** + * This method is called when adding 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; + + // MenuBar is always present and located at the top left corner. + Dimension menupref = menuBar.getPreferredSize(); + menuBar.setBounds(insets.left, insets.top, menupref.width, height); + + 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); + } + + if (maxButton.isVisible()) + { + loc -= buttonWidth + 2; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (iconButton.isVisible()) + { + loc -= buttonWidth + 2; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (title != null) + title.setBounds(insets.left + menupref.width, insets.top, + loc - menupref.width - insets.left, 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); + } + + /** + * This method 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) + { + return new Dimension(22, 18); + } + + /** + * This method is called when removing a Component from the Container. + * + * @param c The Component to remove. + */ + public void removeLayoutComponent(Component c) + { + } + } + + /** + * This helper class is used to create the minimize, maximize and close + * buttons in the top right corner of the Title Pane. These buttons are + * special since they cannot be given focus and have no border. + */ + private class PaneButton extends JButton + { + /** + * Creates a new PaneButton object with the given Action. + * + * @param a The Action that the button uses. + */ + public PaneButton(Action a) + { + super(a); + setMargin(new Insets(0, 0, 0, 0)); + } + + /** + * This method returns true if the Component can be focused. + * + * @return false. + */ + public boolean isFocusable() + { + // These buttons cannot be given focus. + return false; + } + } + + /** The action command for the Close action. */ + protected static final String CLOSE_CMD = "Close"; + + /** The action command for the Minimize action. */ + protected static final String ICONIFY_CMD = "Minimize"; + + /** The action command for the Maximize action. */ + protected static final String MAXIMIZE_CMD = "Maximize"; + + /** The action command for the Move action. */ + protected static final String MOVE_CMD = "Move"; + + /** The action command for the Restore action. */ + protected static final String RESTORE_CMD = "Restore"; + + /** The action command for the Size action. */ + protected static final String SIZE_CMD = "Size"; + + /** The action associated with closing the JInternalFrame. */ + protected Action closeAction; + + /** The action associated with iconifying the JInternalFrame. */ + protected Action iconifyAction; + + /** The action associated with maximizing the JInternalFrame. */ + protected Action maximizeAction; + + /** The action associated with moving the JInternalFrame. */ + protected Action moveAction; + + /** The action associated with restoring the JInternalFrame. */ + protected Action restoreAction; + + /** The action associated with resizing the JInternalFrame. */ + protected Action sizeAction; + + /** The button that closes the JInternalFrame. */ + protected JButton closeButton; + + /** The button that iconifies the JInternalFrame. */ + protected JButton iconButton; + + /** The button that maximizes the JInternalFrame. */ + protected JButton maxButton; + + /** Active background color. */ + protected Color activeBGColor; + + /** Active foreground color. */ + protected Color activeFGColor; + + /** Inactive background color. */ + protected Color inactiveBGColor; + + /** Inactive foreground color. */ + protected Color inactiveFGColor; + + /** The icon displayed in the restore button. */ + protected Icon minIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The icon displayed in the maximize button. */ + protected Icon maxIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The icon displayed in the iconify button. */ + protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The JInternalFrame that this TitlePane is used in. */ + protected JInternalFrame frame; + + /** The JMenuBar that is located at the top left of the Title Pane. */ + protected JMenuBar menuBar; + + /** The JMenu inside the menuBar. */ + protected JMenu windowMenu; + + /** + * The text color of the TitlePane when the JInternalFrame is not selected. + */ + protected Color notSelectedTextColor; + + /** + * The background color of the TitlePane when the JInternalFrame is not + * selected. + */ + protected Color notSelectedTitleColor; + + /** The text color of the titlePane when the JInternalFrame is selected. */ + protected Color selectedTextColor; + + /** + * The background color of the TitlePane when the JInternalFrame is + * selected. + */ + protected Color selectedTitleColor; + + /** The Property Change listener that listens to the JInternalFrame. */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The label used to display the title. This label is not added to the + * TitlePane. + * This is package-private to avoid an accessor method. + */ + transient JLabel title; + + /** + * Creates a new BasicInternalFrameTitlePane object that is used in the + * given JInternalFrame. + * + * @param f The JInternalFrame this BasicInternalFrameTitlePane will be used + * in. + */ + public BasicInternalFrameTitlePane(JInternalFrame f) + { + frame = f; + setLayout(createLayout()); + title = new JLabel(); + title.setHorizontalAlignment(SwingConstants.LEFT); + title.setHorizontalTextPosition(SwingConstants.LEFT); + title.setOpaque(false); + setOpaque(true); + + setBackground(Color.LIGHT_GRAY); + + installTitlePane(); + } + + /** + * This method installs the TitlePane onto the JInternalFrameTitlePane. It + * also creates any children components that need to be created and adds + * listeners to the appropriate components. + */ + protected void installTitlePane() + { + installDefaults(); + installListeners(); + createActions(); + + assembleSystemMenu(); + + createButtons(); + setButtonIcons(); + addSubComponents(); + enableActions(); + } + + /** + * This method adds the sub components to the TitlePane. + */ + protected void addSubComponents() + { + add(menuBar); + + add(closeButton); + add(iconButton); + add(maxButton); + } + + /** + * This method creates the actions that are used to manipulate the + * JInternalFrame. + */ + protected void createActions() + { + closeAction = new CloseAction(); + closeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, CLOSE_CMD); + + iconifyAction = new IconifyAction(); + iconifyAction.putValue(AbstractAction.ACTION_COMMAND_KEY, ICONIFY_CMD); + + maximizeAction = new MaximizeAction(); + maximizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MAXIMIZE_CMD); + + sizeAction = new SizeAction(); + sizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, SIZE_CMD); + + restoreAction = new RestoreAction(); + restoreAction.putValue(AbstractAction.ACTION_COMMAND_KEY, RESTORE_CMD); + + moveAction = new MoveAction(); + moveAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MOVE_CMD); + } + + /** + * This method is used to install the listeners. + */ + protected void installListeners() + { + propertyChangeListener = new PropertyChangeHandler(); + frame.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method is used to uninstall the listeners. + */ + protected void uninstallListeners() + { + frame.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * This method installs the defaults determined by the look and feel. + */ + protected void installDefaults() + { + // FIXME: move icons to defaults. + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + setFont(defaults.getFont("InternalFrame.titleFont")); + activeFGColor = defaults.getColor("InternalFrame.activeTitleForeground"); + activeBGColor = defaults.getColor("InternalFrame.activeTitleBackground"); + inactiveFGColor = defaults.getColor("InternalFrame.inactiveTitleForeground"); + inactiveBGColor = defaults.getColor("InternalFrame.inactiveTitleBackground"); + } + + /** + * This method uninstalls the defaults. + */ + protected void uninstallDefaults() + { + setFont(null); + activeFGColor = null; + activeBGColor = null; + inactiveFGColor = null; + inactiveBGColor = null; + } + + /** + * This method creates the buttons used in the TitlePane. + */ + protected void createButtons() + { + closeButton = new PaneButton(closeAction); + if (!frame.isClosable()) + closeButton.setVisible(false); + iconButton = new PaneButton(iconifyAction); + if (!frame.isIconifiable()) + iconButton.setVisible(false); + maxButton = new PaneButton(maximizeAction); + if (!frame.isMaximizable()) + maxButton.setVisible(false); + } + + /** + * This method sets the icons in the buttons. This is a no-op method here, it + * can be overridden by subclasses to set icons for the minimize-, maximize- + * and close-buttons. + */ + protected void setButtonIcons() + { + } + + /** + * This method creates the MenuBar used in the TitlePane. + */ + protected void assembleSystemMenu() + { + menuBar = createSystemMenuBar(); + windowMenu = createSystemMenu(); + + menuBar.add(windowMenu); + + addSystemMenuItems(windowMenu); + enableActions(); + } + + /** + * This method adds the MenuItems to the given JMenu. + * + * @param systemMenu The JMenu to add MenuItems to. + */ + protected void addSystemMenuItems(JMenu systemMenu) + { + JMenuItem tmp; + + tmp = new JMenuItem(RESTORE_CMD); + tmp.addActionListener(restoreAction); + tmp.setMnemonic(KeyEvent.VK_R); + systemMenu.add(tmp); + + tmp = new JMenuItem(MOVE_CMD); + tmp.addActionListener(moveAction); + tmp.setMnemonic(KeyEvent.VK_M); + systemMenu.add(tmp); + + tmp = new JMenuItem(SIZE_CMD); + tmp.addActionListener(sizeAction); + tmp.setMnemonic(KeyEvent.VK_S); + systemMenu.add(tmp); + + tmp = new JMenuItem(ICONIFY_CMD); + tmp.addActionListener(iconifyAction); + tmp.setMnemonic(KeyEvent.VK_N); + systemMenu.add(tmp); + + tmp = new JMenuItem(MAXIMIZE_CMD); + tmp.addActionListener(maximizeAction); + tmp.setMnemonic(KeyEvent.VK_X); + systemMenu.add(tmp); + + systemMenu.addSeparator(); + + tmp = new JMenuItem(CLOSE_CMD); + tmp.addActionListener(closeAction); + tmp.setMnemonic(KeyEvent.VK_C); + systemMenu.add(tmp); + } + + /** + * This method creates a new JMenubar. + * + * @return A new JMenuBar. + */ + protected JMenuBar createSystemMenuBar() + { + if (menuBar == null) + menuBar = new SystemMenuBar(); + menuBar.removeAll(); + return menuBar; + } + + /** + * This method creates a new JMenu. + * + * @return A new JMenu. + */ + protected JMenu createSystemMenu() + { + if (windowMenu == null) + windowMenu = new JMenu(); + windowMenu.removeAll(); + return windowMenu; + } + + /** + * This method programmatically shows the JMenu. + */ + protected void showSystemMenu() + { + // FIXME: Untested as KeyEvents are not hooked up. + menuBar.getMenu(1).getPopupMenu().show(); + } + + /** + * This method paints the TitlePane. + * + * @param g The Graphics object to paint with. + */ + 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(); + if (frame.isSelected()) + g.setColor(activeFGColor); + else + g.setColor(inactiveFGColor); + title.setText(getTitle(frame.getTitle(), fm, title.getBounds().width)); + SwingUtilities.paintComponent(g, title, null, title.getBounds()); + g.setColor(saved); + } + } + + /** + * This method paints the TitlePane's background. + * + * @param g The Graphics object to paint with. + */ + protected void paintTitleBackground(Graphics g) + { + Color saved = g.getColor(); + Dimension dims = getSize(); + + Color bg = getBackground(); + if (frame.isSelected()) + bg = activeBGColor; + else + bg = inactiveBGColor; + g.setColor(bg); + g.fillRect(0, 0, dims.width, dims.height); + g.setColor(saved); + } + + /** + * This method returns the title string based on the available width and the + * font metrics. + * + * @param text The desired title. + * @param fm The FontMetrics of the font used. + * @param availableWidth The available width. + * + * @return The allowable string. + */ + protected String getTitle(String text, FontMetrics fm, int availableWidth) + { + Rectangle vr = new Rectangle(0, 0, availableWidth, fm.getHeight()); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + String value = SwingUtilities.layoutCompoundLabel(this, fm, text, null, + SwingConstants.CENTER, + SwingConstants.LEFT, + SwingConstants.CENTER, + SwingConstants.LEFT, vr, + ir, tr, 0); + return value; + } + + /** + * This method fires something similar to a WINDOW_CLOSING event. + * + * @param frame The JInternalFrame that is being closed. + */ + protected void postClosingEvent(JInternalFrame frame) + { + // FIXME: Implement postClosingEvent when I figure out what + // it's supposed to do. + // It says that this fires an WINDOW_CLOSING like event. + // So the closest thing is some kind of InternalFrameEvent. + // But none is fired. + // Can't see it called or anything. + } + + /** + * This method enables the actions for the TitlePane given the frame's + * properties. + */ + protected void enableActions() + { + closeAction.setEnabled(frame.isClosable()); + + iconifyAction.setEnabled(frame.isIconifiable()); + // The maximize action is responsible for restoring it + // as well, if clicked from the button + maximizeAction.setEnabled(frame.isMaximizable()); + + // The restoring action is only active when selected + // from the menu. + restoreAction.setEnabled(frame.isMaximum()); + + sizeAction.setEnabled(frame.isResizable()); + + // FIXME: Tie MoveAction enabled status to a variable. + moveAction.setEnabled(false); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new LayoutManager for the TitlePane. + * + * @return A new LayoutManager. + */ + protected LayoutManager createLayout() + { + return new TitlePaneLayout(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java new file mode 100644 index 0000000..1637966 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -0,0 +1,1719 @@ +/* BasicInternalFrameUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.AWTEvent; +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.Point; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +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.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; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InternalFrameUI; +import javax.swing.plaf.UIResource; + +/** + * This is the UI delegate for the Basic look and feel for JInternalFrames. + */ +public class BasicInternalFrameUI extends InternalFrameUI +{ + /** + * This is a helper class that listens to the JInternalFrame for + * InternalFrameEvents. + */ + protected class BasicInternalFrameListener implements InternalFrameListener + { + /** + * This method is called when the JInternalFrame is activated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameActivated(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is closed. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosed(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is closing. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosing(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is deactivated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeactivated(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is deiconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeiconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is iconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameIconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is opened. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameOpened(InternalFrameEvent e) + { + // FIXME: Implement. + } + } + + /** + * This helper class listens to the edges of the JInternalFrame and the + * TitlePane for mouse events. It is responsible for dragging and resizing + * the JInternalFrame in response to the MouseEvents. + */ + protected class BorderListener extends MouseInputAdapter + implements SwingConstants + { + /** FIXME: Use for something. */ + protected final int RESIZE_NONE = 0; + + /** The x offset from the top left corner of the JInternalFrame. */ + private transient int xOffset = 0; + + /** The y offset from the top left corner of the JInternalFrame. */ + private transient int yOffset = 0; + + /** The direction that the resize is occuring in. */ + private transient int direction = -1; + + /** Cache rectangle that can be reused. */ + private transient Rectangle cacheRect = new Rectangle(); + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // There is nothing to do when the mouse is clicked + // on the border. + } + + /** + * This method is called when the mouse is dragged. This method is + * responsible for resizing or dragging the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + // If the frame is maximized, there is nothing that + // can be dragged around. + if (frame.isMaximum()) + return; + DesktopManager dm = getDesktopManager(); + Rectangle b = frame.getBounds(); + Dimension min = frame.getMinimumSize(); + if (min == null) + 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)); + } + else if (e.getSource() == titlePane) + { + Rectangle fBounds = frame.getBounds(); + + dm.dragFrame(frame, e.getX() - xOffset + b.x, + e.getY() - yOffset + b.y); + } + } + + /** + * This method is called when the mouse exits the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + // There is nothing to do when the mouse exits + // the border area. + } + + /** + * This method is called when the mouse is moved inside the + * JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // There is nothing to do when the mouse moves + // over the border area. + } + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + activateFrame(frame); + DesktopManager dm = getDesktopManager(); + int x = e.getX(); + int y = e.getY(); + Insets insets = frame.getInsets(); + + if (e.getSource() == frame && frame.isResizable()) + { + direction = sectionOfClick(x, y); + dm.beginResizingFrame(frame, direction); + } + else if (e.getSource() == titlePane) + { + Rectangle tBounds = titlePane.getBounds(); + + xOffset = e.getX() - tBounds.x + insets.left; + yOffset = e.getY() - tBounds.y + insets.top; + + dm.beginDraggingFrame(frame); + } + } + + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + DesktopManager dm = getDesktopManager(); + xOffset = 0; + yOffset = 0; + if (e.getSource() == frame && frame.isResizable()) + dm.endResizingFrame(frame); + else if (e.getSource() == titlePane) + dm.endDraggingFrame(frame); + } + + /** + * This method determines the direction of the resize based on the + * coordinates and the size of the JInternalFrame. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The direction of the resize (a SwingConstant direction). + */ + private int sectionOfClick(int x, int y) + { + Insets insets = frame.getInsets(); + Rectangle b = frame.getBounds(); + if (x < insets.left && y < insets.top) + return NORTH_WEST; + else if (x > b.width - insets.right && y < insets.top) + return NORTH_EAST; + else if (x > b.width - insets.right && y > b.height - insets.bottom) + return SOUTH_EAST; + else if (x < insets.left && y > b.height - insets.bottom) + return SOUTH_WEST; + else if (y < insets.top) + return NORTH; + else if (x < insets.left) + return WEST; + else if (y > b.height - insets.bottom) + return SOUTH; + else if (x > b.width - insets.right) + return EAST; + + return -1; + } + } + + /** + * This helper class listens to the JDesktopPane that parents this + * JInternalFrame and listens for resize events and resizes the + * JInternalFrame appropriately. + */ + protected class ComponentHandler implements ComponentListener + { + /** + * This method is called when the JDesktopPane is hidden. + * + * @param e The ComponentEvent fired. + */ + public void componentHidden(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is moved. + * + * @param e The ComponentEvent fired. + */ + public void componentMoved(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is resized. + * + * @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(); + } + + // Sun also resizes the icons. but it doesn't seem to do anything. + } + + /** + * This method is called when the JDesktopPane is shown. + * + * @param e The ComponentEvent fired. + */ + public void componentShown(ComponentEvent e) + { + // Do nothing. + } + } + + /** + * This helper class acts as the LayoutManager for JInternalFrames. + */ + public class InternalFrameLayout implements LayoutManager + { + /** + * 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. + */ + public void addLayoutComponent(String name, Component c) + { + } + + /** + * This method is used to set the bounds of the children of the + * JInternalFrame. + * + * @param c The Container to lay out. + */ + public void layoutContainer(Container c) + { + Dimension dims = frame.getSize(); + Insets insets = frame.getInsets(); + + dims.width -= insets.left + insets.right; + dims.height -= insets.top + insets.bottom; + + frame.getRootPane().getGlassPane().setBounds(0, 0, dims.width, + dims.height); + int nh = 0; + int sh = 0; + int ew = 0; + int ww = 0; + + if (northPane != null) + { + Dimension nDims = northPane.getPreferredSize(); + nh = Math.min(nDims.height, dims.height); + + northPane.setBounds(insets.left, insets.top, dims.width, nh); + } + + if (southPane != null) + { + Dimension sDims = southPane.getPreferredSize(); + sh = Math.min(sDims.height, dims.height - nh); + + 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); + + westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); + } + + if (eastPane != null) + { + Dimension eDims = eastPane.getPreferredSize(); + ew = Math.min(eDims.width, dims.width - ww); + + eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, + ew, remHeight); + } + + int remWidth = dims.width - ww - ew; + + frame.getRootPane().setBounds(insets.left + ww, insets.top + nh, + remWidth, remHeight); + } + + /** + * This method returns the minimum layout size. + * + * @param c The Container to find a minimum layout size for. + * + * @return The minimum dimensions for the JInternalFrame. + */ + public Dimension minimumLayoutSize(Container c) + { + return getSize(c, true); + } + + /** + * This method returns the maximum layout size. + * + * @param c The Container to find a maximum layout size for. + * + * @return The maximum dimensions for the JInternalFrame. + */ + public Dimension maximumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * Th8is method returns the preferred layout size. + * + * @param c The Container to find a preferred layout size for. + * + * @return The preferred dimensions for the JInternalFrame. + */ + public Dimension preferredLayoutSize(Container c) + { + return getSize(c, false); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * @param min DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private Dimension getSize(Container c, boolean min) + { + Insets insets = frame.getInsets(); + + Dimension contentDims = frame.getContentPane().getPreferredSize(); + if (min) + contentDims.width = contentDims.height = 0; + int nWidth = 0; + int nHeight = 0; + int sWidth = 0; + int sHeight = 0; + int eWidth = 0; + int eHeight = 0; + int wWidth = 0; + int wHeight = 0; + Dimension dims; + + if (northPane != null) + { + 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; + } + } + + if (eastPane != null) + { + 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; + } + } + + int width = Math.max(sWidth, nWidth); + width = Math.max(width, contentDims.width + eWidth + wWidth); + + int height = Math.max(eHeight, wHeight); + height = Math.max(height, contentDims.height); + height += nHeight + sHeight; + + width += insets.left + insets.right; + height += insets.top + insets.bottom; + + return new Dimension(width, height); + } + + /** + * This method is called when a Component is removed from the + * JInternalFrame. + * + * @param c The Component that was removed. + */ + public void removeLayoutComponent(Component c) + { + } + } + + /** + * This helper class is used to listen to the JDesktopPane's glassPane for + * MouseEvents. The JInternalFrame can then be selected if a click is + * detected on its children. + */ + protected class GlassPaneDispatcher implements MouseInputListener + { + /** The MouseEvent target. */ + private transient Component mouseEventTarget; + + /** The component pressed. */ + private transient Component pressedComponent; + + /** The last component entered. */ + private transient Component lastComponentEntered; + + /** Used to store/reset lastComponentEntered. */ + private transient Component tempComponent; + + /** The number of presses. */ + private transient int pressCount; + + /** + * This method is called when the mouse enters the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is clicked on the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is dragged in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse exits the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is moved in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is pressed in the glass pane. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + activateFrame(frame); + handleEvent(e); + } + + /** + * This method is called when the mouse is released in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + handleEvent(e); + } + + /** + * 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) + { + int x = me.getX(); + int y = me.getY(); + + // Find the candidate which should receive this event. + Component parent = frame.getContentPane(); + if (parent == null) + 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(); + } + } + + // If the only candidate we found was the native container itself, + // don't dispatch any event at all. We only care about the lightweight + // children here. + if (candidate == frame.getContentPane()) + 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()); + tempComponent = lastComponentEntered; + 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); + } + } + + 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; + 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; + } + } + + /** + * 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; + } + } + } + } + } + + /** + * This helper class listens for PropertyChangeEvents from the + * JInternalFrame. + */ + 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. + */ + public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException + { + if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY)) + { + if (frame.getDefaultCloseOperation() == JInternalFrame.HIDE_ON_CLOSE) + { + frame.setVisible(false); + frame.getDesktopPane().repaint(); + 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); + } + } + + /** + * 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); + } + else if (evt.getPropertyName().equals(JInternalFrame.IS_ICON_PROPERTY)) + { + 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); + } + else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY) + || evt.getPropertyName().equals(JInternalFrame.GLASS_PANE_PROPERTY)) + { + Component old = (Component) evt.getOldValue(); + old.removeMouseListener(glassPaneDispatcher); + old.removeMouseMotionListener(glassPaneDispatcher); + + Component newPane = (Component) evt.getNewValue(); + newPane.addMouseListener(glassPaneDispatcher); + newPane.addMouseMotionListener(glassPaneDispatcher); + + 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); + } + */ + } + } + + /** + * This helper class is the border for the JInternalFrame. + */ + private class InternalFrameBorder extends AbstractBorder + implements UIResource + { + /** The width of the border. */ + private static final int bSize = 5; + + /** The size of the corners. */ + private static final int offset = 10; + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method returns the insets of the border. + * + * @param c The Component to find border insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(bSize, bSize, bSize, bSize); + } + + /** + * 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. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) + { + g.translate(x, y); + Color saved = g.getColor(); + Rectangle b = frame.getBounds(); + + Color d = c.getBackground(); + g.setColor(d); + g.fillRect(0, 0, bSize, b.height); + g.fillRect(0, 0, b.width, bSize); + g.fillRect(0, b.height - bSize, b.width, bSize); + g.fillRect(b.width - bSize, 0, bSize, b.height); + + int x1 = 0; + int x2 = bSize; + int x3 = b.width - bSize; + int x4 = b.width; + + int y1 = 0; + int y2 = bSize; + int y3 = b.height - bSize; + int y4 = b.height; + + g.setColor(Color.GRAY); + g.fillRect(0, 0, bSize, y4); + g.fillRect(0, 0, x4, bSize); + g.fillRect(0, y3, b.width, bSize); + g.fillRect(x3, 0, bSize, b.height); + + g.fill3DRect(0, offset, bSize, b.height - 2 * offset, false); + g.fill3DRect(offset, 0, b.width - 2 * offset, bSize, false); + g.fill3DRect(offset, b.height - bSize, b.width - 2 * offset, bSize, false); + g.fill3DRect(b.width - bSize, offset, bSize, b.height - 2 * offset, false); + + g.translate(-x, -y); + g.setColor(saved); + } + } + + /** + * The MouseListener that is responsible for dragging and resizing the + * JInternalFrame in response to MouseEvents. + */ + protected MouseInputAdapter borderListener; + + /** + * The ComponentListener that is responsible for resizing the JInternalFrame + * in response to ComponentEvents from the JDesktopPane. + */ + protected ComponentListener componentListener; + + /** + * The MouseListener that is responsible for activating the JInternalFrame + * when the mouse press activates one of its descendents. + */ + protected MouseInputListener glassPaneDispatcher; + + /** + * The PropertyChangeListener that is responsible for listening to + * PropertyChangeEvents from the JInternalFrame. + */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The VetoableChangeListener. Listens to PropertyChangeEvents + * from the JInternalFrame and allows the JInternalFrame to + * veto attempts to close it. + */ + private VetoableChangeListener internalFrameVetoableChangeListener; + + /** The InternalFrameListener that listens to the JInternalFrame. */ + private transient BasicInternalFrameListener internalFrameListener; + + /** The JComponent placed at the east region of the JInternalFrame. */ + protected JComponent eastPane; + + /** The JComponent placed at the north region of the JInternalFrame. */ + protected JComponent northPane; + + /** The JComponent placed at the south region of the JInternalFrame. */ + protected JComponent southPane; + + /** The JComponent placed at the west region of the JInternalFrame. */ + protected JComponent westPane; + + /** + * The Keystroke bound to open the menu. + * @deprecated + */ + protected KeyStroke openMenuKey; + + /** The TitlePane displayed at the top of the JInternalFrame. */ + protected BasicInternalFrameTitlePane titlePane; + + /** The JInternalFrame this UI is responsible for. */ + protected JInternalFrame frame; + + /** The LayoutManager used in the JInternalFrame. */ + protected LayoutManager internalFrameLayout; + + /** The JDesktopPane that is the parent of the JInternalFrame. */ + private transient JDesktopPane desktopPane; + + /** + * Creates a new BasicInternalFrameUI object. + * + * @param b The JInternalFrame this UI will represent. + */ + public BasicInternalFrameUI(JInternalFrame b) + { + } + + /** + * This method will create a new BasicInternalFrameUI for the given + * JComponent. + * + * @param b The JComponent to create a BasicInternalFrameUI for. + * + * @return A new BasicInternalFrameUI. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicInternalFrameUI((JInternalFrame) b); + } + + /** + * This method installs a UI for the JInternalFrame. + * + * @param c The JComponent to install this UI on. + */ + public void installUI(JComponent c) + { + if (c instanceof JInternalFrame) + { + frame = (JInternalFrame) c; + + internalFrameLayout = createLayoutManager(); + frame.setLayout(internalFrameLayout); + + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); + frame.getRootPane().getGlassPane().setVisible(true); + + installDefaults(); + installListeners(); + installComponents(); + installKeyboardActions(); + + frame.setOpaque(true); + titlePane.setOpaque(true); + frame.invalidate(); + } + } + + /** + * This method reverses the work done by installUI. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallComponents(); + uninstallListeners(); + uninstallDefaults(); + + frame.setLayout(null); + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(true); + frame.getRootPane().getGlassPane().setVisible(false); + + frame = null; + } + + /** + * This method installs the defaults specified by the look and feel. + */ + protected void installDefaults() + { + // This is the border of InternalFrames in the BasicLookAndFeel. + // Note that there exist entries for various border colors in + // BasicLookAndFeel's defaults, but obviously they differ + // from the colors that are actually used by the JDK. + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + Color borderColor = defaults.getColor("InternalFrame.borderColor"); + Border inner = BorderFactory.createLineBorder(borderColor, 1); + Color borderDarkShadow = defaults.getColor + ("InternalFrame.borderDarkShadow"); + Color borderHighlight = defaults.getColor + ("InternalFrame.borderHighlight"); + Color borderShadow = defaults.getColor("InternalFrame.borderShadow"); + Color borderLight = defaults.getColor("InternalFrame.borderLight"); + Border outer = BorderFactory.createBevelBorder(BevelBorder.RAISED, + borderShadow, + borderHighlight, + borderDarkShadow, + borderShadow); + Border border = new BorderUIResource.CompoundBorderUIResource(outer, + inner); + frame.setBorder(border); + + // InternalFrames are invisible by default. + frame.setVisible(false); + } + + /** + * This method installs the keyboard actions for the JInternalFrame. + */ + protected void installKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method installs the Components for the JInternalFrame. + */ + protected void installComponents() + { + setNorthPane(createNorthPane(frame)); + setSouthPane(createSouthPane(frame)); + setEastPane(createEastPane(frame)); + setWestPane(createWestPane(frame)); + } + + /** + * This method installs the listeners for the JInternalFrame. + */ + protected void installListeners() + { + glassPaneDispatcher = createGlassPaneDispatcher(); + createInternalFrameListener(); + borderListener = createBorderListener(frame); + componentListener = createComponentListener(); + propertyChangeListener = createPropertyChangeListener(); + internalFrameVetoableChangeListener = new InternalFramePropertyChangeListener(); + + frame.addMouseListener(borderListener); + frame.addMouseMotionListener(borderListener); + frame.addInternalFrameListener(internalFrameListener); + frame.addPropertyChangeListener(propertyChangeListener); + frame.addVetoableChangeListener(internalFrameVetoableChangeListener); + frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher); + } + + /** + * This method uninstalls the defaults for the JInternalFrame. + */ + protected void uninstallDefaults() + { + frame.setBorder(null); + } + + /** + * This method uninstalls the Components for the JInternalFrame. + */ + protected void uninstallComponents() + { + setNorthPane(null); + setSouthPane(null); + setEastPane(null); + setWestPane(null); + } + + /** + * This method uninstalls the listeners for the JInternalFrame. + */ + protected void uninstallListeners() + { + if (desktopPane != null) + desktopPane.removeComponentListener(componentListener); + + frame.getRootPane().getGlassPane().removeMouseMotionListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().removeMouseListener(glassPaneDispatcher); + + frame.removePropertyChangeListener(propertyChangeListener); + frame.removeInternalFrameListener(internalFrameListener); + frame.removeMouseMotionListener(borderListener); + frame.removeMouseListener(borderListener); + + propertyChangeListener = null; + componentListener = null; + borderListener = null; + internalFrameListener = null; + glassPaneDispatcher = null; + } + + /** + * This method uninstalls the keyboard actions for the JInternalFrame. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method creates a new LayoutManager for the JInternalFrame. + * + * @return A new LayoutManager for the JInternalFrame. + */ + protected LayoutManager createLayoutManager() + { + return new InternalFrameLayout(); + } + + /** + * This method creates a new PropertyChangeListener for the JInternalFrame. + * + * @return A new PropertyChangeListener for the JInternalFrame. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new InternalFramePropertyChangeListener(); + } + + /** + * This method returns the preferred size of the given JComponent. + * + * @param x The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent x) + { + return internalFrameLayout.preferredLayoutSize(x); + } + + /** + * This method returns the minimum size of the given JComponent. + * + * @param x The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent x) + { + return internalFrameLayout.minimumLayoutSize(x); + } + + /** + * This method returns the maximum size of the given JComponent. + * + * @param x The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent x) + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * This method replaces the currentPane with the newPane. When replacing it + * also removes the MouseHandlers for the old pane and installs them on + * the new pane. + * + * @param currentPane The old pane to remove. + * @param newPane The new pane to install. + */ + protected void replacePane(JComponent currentPane, JComponent newPane) + { + if (currentPane != null) + { + deinstallMouseHandlers(currentPane); + frame.remove(currentPane); + } + + if (newPane != null) + { + installMouseHandlers(newPane); + frame.add(newPane); + } + } + + /** + * This method removes the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to remove MouseListeners from. + */ + protected void deinstallMouseHandlers(JComponent c) + { + c.removeMouseListener(borderListener); + c.removeMouseMotionListener(borderListener); + } + + /** + * This method installs the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to install MouseListeners on. + */ + protected void installMouseHandlers(JComponent c) + { + c.addMouseListener(borderListener); + c.addMouseMotionListener(borderListener); + } + + /** + * This method creates the north pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a north pane for. + * + * @return The north pane. + */ + protected JComponent createNorthPane(JInternalFrame w) + { + titlePane = new BasicInternalFrameTitlePane(w); + return titlePane; + } + + /** + * This method creates the west pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a west pane for. + * + * @return The west pane. + */ + protected JComponent createWestPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the south pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a south pane for. + * + * @return The south pane. + */ + protected JComponent createSouthPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the east pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create an east pane for. + * + * @return The east pane. + */ + protected JComponent createEastPane(JInternalFrame w) + { + return null; + } + + /** + * This method returns a new BorderListener for the given JInternalFrame. + * + * @param w The JIntenalFrame to create a BorderListener for. + * + * @return A new BorderListener. + */ + protected MouseInputAdapter createBorderListener(JInternalFrame w) + { + return new BorderListener(); + } + + /** + * This method creates a new InternalFrameListener for the JInternalFrame. + */ + protected void createInternalFrameListener() + { + internalFrameListener = new BasicInternalFrameListener(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected final boolean isKeyBindingRegistered() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingRegistered(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public final boolean isKeyBindingActive() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingActive(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuOpenKey() + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuCloseKey() + { + // FIXME: Implement. + } + + /** + * This method returns the north pane. + * + * @return The north pane. + */ + public JComponent getNorthPane() + { + return northPane; + } + + /** + * This method sets the north pane to be the given JComponent. + * + * @param c The new north pane. + */ + public void setNorthPane(JComponent c) + { + replacePane(northPane, c); + northPane = c; + } + + /** + * This method returns the south pane. + * + * @return The south pane. + */ + public JComponent getSouthPane() + { + return southPane; + } + + /** + * This method sets the south pane to be the given JComponent. + * + * @param c The new south pane. + */ + public void setSouthPane(JComponent c) + { + replacePane(southPane, c); + southPane = c; + } + + /** + * This method sets the east pane to be the given JComponent. + * + * @param c The new east pane. + */ + public void setEastPane(JComponent c) + { + replacePane(eastPane, c); + eastPane = c; + } + + /** + * This method returns the east pane. + * + * @return The east pane. + */ + public JComponent getEastPane() + { + return eastPane; + } + + /** + * This method sets the west pane to be the given JComponent. + * + * @param c The new west pane. + */ + public void setWestPane(JComponent c) + { + replacePane(westPane, c); + westPane = c; + } + + /** + * This method returns the west pane. + * + * @return The west pane. + */ + public JComponent getWestPane() + { + return westPane; + } + + /** + * This method returns the DesktopManager to use with the JInternalFrame. + * + * @return The DesktopManager to use with the JInternalFrame. + */ + protected DesktopManager getDesktopManager() + { + DesktopManager value = null; + JDesktopPane pane = frame.getDesktopPane(); + if (pane != null) + value = frame.getDesktopPane().getDesktopManager(); + if (value == null) + value = createDesktopManager(); + return value; + } + + /** + * This method returns a default DesktopManager that can be used with this + * JInternalFrame. + * + * @return A default DesktopManager that can be used with this + * JInternalFrame. + */ + protected DesktopManager createDesktopManager() + { + return new DefaultDesktopManager(); + } + + /** + * This is a convenience method that closes the JInternalFrame. + * + * @param f The JInternalFrame to close. + */ + protected void closeFrame(JInternalFrame f) + { + getDesktopManager().closeFrame(f); + } + + /** + * This is a convenience method that maximizes the JInternalFrame. + * + * @param f The JInternalFrame to maximize. + */ + protected void maximizeFrame(JInternalFrame f) + { + getDesktopManager().maximizeFrame(f); + } + + /** + * This is a convenience method that minimizes the JInternalFrame. + * + * @param f The JInternalFrame to minimize. + */ + protected void minimizeFrame(JInternalFrame f) + { + getDesktopManager().minimizeFrame(f); + } + + /** + * This is a convenience method that iconifies the JInternalFrame. + * + * @param f The JInternalFrame to iconify. + */ + protected void iconifyFrame(JInternalFrame f) + { + getDesktopManager().iconifyFrame(f); + } + + /** + * This is a convenience method that deiconifies the JInternalFrame. + * + * @param f The JInternalFrame to deiconify. + */ + protected void deiconifyFrame(JInternalFrame f) + { + getDesktopManager().deiconifyFrame(f); + } + + /** + * This is a convenience method that activates the JInternalFrame. + * + * @param f The JInternalFrame to activate. + */ + protected void activateFrame(JInternalFrame f) + { + getDesktopManager().activateFrame(f); + } + + /** + * This method returns a new ComponentListener for the JDesktopPane. + * + * @return A new ComponentListener. + */ + protected ComponentListener createComponentListener() + { + return new ComponentHandler(); + } + + /** + * This method returns a new GlassPaneDispatcher. + * + * @return A new GlassPaneDispatcher. + */ + protected MouseInputListener createGlassPaneDispatcher() + { + return new GlassPaneDispatcher(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java new file mode 100644 index 0000000..e71e82f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java @@ -0,0 +1,425 @@ +/* BasicLabelUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +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.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +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 +{ + /** The labelUI that is shared by all labels. */ + protected static BasicLabelUI labelUI; + + /** + * Creates a new BasicLabelUI object. + */ + public BasicLabelUI() + { + super(); + } + + /** + * Creates and returns a UI for the label. Since one UI is shared by all + * labels, this means creating only if necessary and returning the shared + * UI. + * + * @param c The {@link JComponent} that a UI is being created for. + * + * @return A label UI for the Basic Look and Feel. + */ + public static ComponentUI createUI(JComponent c) + { + if (labelUI == null) + labelUI = new BasicLabelUI(); + return labelUI; + } + + /** + * Returns the preferred size of this component as calculated by the + * {@link #layoutCL(JLabel, FontMetrics, String, Icon, Rectangle, Rectangle, + * Rectangle)} method. + * + * @param c This {@link JComponent} to get a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + JLabel lab = (JLabel)c; + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + Insets insets = lab.getInsets(); + FontMetrics fm = lab.getToolkit().getFontMetrics(lab.getFont()); + layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr); + Rectangle cr = tr.union(ir); + return new Dimension(insets.left + cr.width + insets.right, + insets.top + cr.height + insets.bottom); + + } + + /** + * This method returns the minimum size of the {@link JComponent} given. If + * this method returns null, then it is up to the Layout Manager to give + * this component a minimum size. + * + * @param c The {@link JComponent} to get a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size of the {@link JComponent} given. If + * this method returns null, then it is up to the Layout Manager to give + * this component a maximum size. + * + * @param c The {@link JComponent} to get a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * The method that paints the label according to its current state. + * + * @param g The {@link Graphics} object to paint with. + * @param c The {@link JComponent} to paint. + */ + public void paint(Graphics g, JComponent c) + { + JLabel b = (JLabel) c; + + Font saved_font = g.getFont(); + + Rectangle tr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle vr = new Rectangle(); + + Font f = c.getFont(); + + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + + vr = SwingUtilities.calculateInnerArea(c, vr); + + if (vr.width < 0) + vr.width = 0; + if (vr.height < 0) + vr.height = 0; + + Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon(); + + String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr); + + if (icon != null) + icon.paintIcon(b, g, ir.x, ir.y); + if (text != null && ! text.equals("")) + { + if (b.isEnabled()) + paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + else + paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + } + g.setFont(saved_font); + } + + /** + * This method is simply calls SwingUtilities's layoutCompoundLabel. + * + * @param label The label to lay out. + * @param fontMetrics The FontMetrics for the font used. + * @param text The text to paint. + * @param icon The icon to draw. + * @param viewR The entire viewable rectangle. + * @param iconR The icon bounds rectangle. + * @param textR The text bounds rectangle. + * + * @return A possibly clipped version of the text. + */ + protected String layoutCL(JLabel label, FontMetrics fontMetrics, + String text, Icon icon, Rectangle viewR, + Rectangle iconR, Rectangle textR) + { + return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon, + label.getVerticalAlignment(), + label.getHorizontalAlignment(), + label.getVerticalTextPosition(), + label.getHorizontalTextPosition(), + viewR, iconR, textR, + label.getIconTextGap()); + } + + /** + * Paints the text if the label is disabled. By default, this paints the + * clipped text returned by layoutCompoundLabel using the + * background.brighter() color. It also paints the same text using the + * background.darker() color one pixel to the right and one pixel down. + * + * @param l The {@link JLabel} being painted. + * @param g The {@link Graphics} object to paint with. + * @param s The String to paint. + * @param textX The x coordinate of the start of the baseline. + * @param textY The y coordinate of the start of the baseline. + */ + protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, + int textY) + { + Color saved_color = g.getColor(); + + g.setColor(l.getBackground().brighter()); + + int mnemIndex = l.getDisplayedMnemonicIndex(); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX, + textY); + else + g.drawString(s, textX, textY); + + g.setColor(l.getBackground().darker()); + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX + 1, + textY + 1); + else + g.drawString(s, textX + 1, textY + 1); + + g.setColor(saved_color); + } + + /** + * Paints the text if the label is enabled. The text is painted using the + * foreground color. + * + * @param l The {@link JLabel} being painted. + * @param g The {@link Graphics} object to paint with. + * @param s The String to paint. + * @param textX The x coordinate of the start of the baseline. + * @param textY The y coordinate of the start of the baseline. + */ + protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, + int textY) + { + Color saved_color = g.getColor(); + g.setColor(l.getForeground()); + + int mnemIndex = l.getDisplayedMnemonicIndex(); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX, + textY); + else + g.drawString(s, textX, textY); + + g.setColor(saved_color); + } + + /** + * This method installs the UI for the given {@link JComponent}. This + * method will install the component, defaults, listeners, and keyboard + * actions. + * + * @param c The {@link JComponent} that this UI is being installed on. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JLabel) + { + JLabel l = (JLabel) c; + + installComponents(l); + installDefaults(l); + installListeners(l); + installKeyboardActions(l); + } + } + + /** + * This method uninstalls the UI for the given {@link JComponent}. This + * method will uninstall the component, defaults, listeners, and keyboard + * actions. + * + * @param c The {@link JComponent} that this UI is being installed on. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + if (c instanceof JLabel) + { + JLabel l = (JLabel) c; + + uninstallKeyboardActions(l); + uninstallListeners(l); + uninstallDefaults(l); + uninstallComponents(l); + } + } + + /** + * This method installs the components for this {@link JLabel}. + * + * @param c The {@link JLabel} to install components for. + */ + protected void installComponents(JLabel c) + { + //FIXME: fix javadoc + implement. + } + + /** + * This method uninstalls the components for this {@link JLabel}. + * + * @param c The {@link JLabel} to uninstall components for. + */ + protected void uninstallComponents(JLabel c) + { + //FIXME: fix javadoc + implement. + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this {@link JLabel}. + * + * @param c The {@link JLabel} to install defaults for. + */ + 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")); + //XXX: There are properties we don't use called disabledForeground + //and disabledShadow. + } + + /** + * This method uninstalls the defaults that are defined in the Basic look + * and feel for this {@link JLabel}. + * + * @param c The {@link JLabel} to uninstall defaults for. + */ + protected void uninstallDefaults(JLabel c) + { + c.setForeground(null); + c.setBackground(null); + c.setFont(null); + } + + /** + * This method installs the keyboard actions for the given {@link JLabel}. + * + * @param l The {@link JLabel} to install keyboard actions for. + */ + protected void installKeyboardActions(JLabel l) + { + //FIXME: implement. + } + + /** + * This method uninstalls the keyboard actions for the given {@link JLabel}. + * + * @param l The {@link JLabel} to uninstall keyboard actions for. + */ + protected void uninstallKeyboardActions(JLabel l) + { + //FIXME: implement. + } + + /** + * This method installs the listeners for the given {@link JLabel}. The UI + * delegate only listens to the label. + * + * @param c The {@link JLabel} to install listeners for. + */ + protected void installListeners(JLabel c) + { + c.addPropertyChangeListener(this); + } + + /** + * This method uninstalls the listeners for the given {@link JLabel}. The UI + * delegate only listens to the label. + * + * @param c The {@link JLabel} to uninstall listeners for. + */ + protected void uninstallListeners(JLabel c) + { + c.removePropertyChangeListener(this); + } + + /** + * This method is called whenever any JLabel's that use this UI has one of + * their properties change. + * + * @param e The {@link PropertyChangeEvent} that describes the change. + */ + public void propertyChange(PropertyChangeEvent e) + { + JLabel c = (JLabel) e.getSource(); + c.revalidate(); + c.repaint(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java new file mode 100644 index 0000000..24c6cd2 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java @@ -0,0 +1,1004 @@ +/* BasicListUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.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.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JViewport; +import javax.swing.ListCellRenderer; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ListUI; + +/** + * The Basic Look and Feel UI delegate for the + * JList. + */ +public class BasicListUI extends ListUI +{ + + /** + * A helper class which listens for {@link ComponentEvent}s from + * the JList. + */ + private class ComponentHandler extends ComponentAdapter { + + /** + * Called when the component is hidden. Invalidates the internal + * layout. + */ + public void componentResized(ComponentEvent ev) { + BasicListUI.this.damageLayout(); + } + } + + /** + * A helper class which listens for {@link FocusEvent}s + * from the JList. + */ + public class FocusHandler implements FocusListener + { + /** + * Called when the JList acquires focus. + * + * @param e The FocusEvent representing focus acquisition + */ + public void focusGained(FocusEvent e) + { + repaintCellFocus(); + } + + /** + * Called when the JList loses focus. + * + * @param e The FocusEvent representing focus loss + */ + public void focusLost(FocusEvent e) + { + repaintCellFocus(); + } + + /** + * Helper method to repaint the focused cell's + * lost or acquired focus state. + */ + void repaintCellFocus() + { + } + } + + /** + * A helper class which listens for {@link ListDataEvent}s generated by + * the {@link JList}'s {@link ListModel}. + * + * @see javax.swing.JList#getModel() + */ + public class ListDataHandler implements ListDataListener + { + /** + * Called when a general change has happened in the model which cannot + * be represented in terms of a simple addition or deletion. + * + * @param e The event representing the change + */ + public void contentsChanged(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + + /** + * Called when an interval of objects has been added to the model. + * + * @param e The event representing the addition + */ + public void intervalAdded(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + + /** + * Called when an inteval of objects has been removed from the model. + * + * @param e The event representing the removal + */ + public void intervalRemoved(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + } + + /** + * A helper class which listens for {@link ListSelectionEvent}s + * from the {@link JList}'s {@link ListSelectionModel}. + */ + public class ListSelectionHandler implements ListSelectionListener + { + /** + * Called when the list selection changes. + * + * @param e The event representing the change + */ + public void valueChanged(ListSelectionEvent e) + { + } + } + + /** + * A helper class which listens for {@link KeyEvents}s + * from the {@link JList}. + */ + private class KeyHandler extends KeyAdapter + { + public KeyHandler() + { + } + + public void keyPressed( KeyEvent evt ) + { + int lead = BasicListUI.this.list.getLeadSelectionIndex(); + int max = BasicListUI.this.list.getModel().getSize() - 1; + // 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 (!evt.isShiftDown()) + { + BasicListUI.this.list.clearSelection(); + BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max)); + } + else + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.min(lead+1,max)); + } + } + else if ((evt.getKeyCode() == KeyEvent.VK_UP) + || (evt.getKeyCode() == KeyEvent.VK_KP_UP)) + { + if (!evt.isShiftDown()) + { + BasicListUI.this.list.clearSelection(); + BasicListUI.this.list.setSelectedIndex(Math.max(lead-1,0)); + } + else + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.max(lead-1,0)); + } + } + else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP) + { + // FIXME: implement, need JList.ensureIndexIsVisible to work + } + else if (evt.getKeyCode() == KeyEvent.VK_PAGE_DOWN) + { + // FIXME: implement, need JList.ensureIndexIsVisible to work + } + else if (evt.getKeyCode() == KeyEvent.VK_BACK_SLASH + && evt.isControlDown()) + { + BasicListUI.this.list.clearSelection(); + } + else if ((evt.getKeyCode() == KeyEvent.VK_HOME) + || evt.getKeyCode() == KeyEvent.VK_END) + { + // 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); + } + else if ((evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() + == KeyEvent.VK_SLASH) && evt.isControlDown()) + { + BasicListUI.this.list.setSelectionInterval(0, max); + } + else if (evt.getKeyCode() == KeyEvent.VK_SPACE && evt.isControlDown()) + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.min(lead+1,max)); + } + + } + } + + /** + * A helper class which listens for {@link MouseEvent}s + * from the {@link JList}. + */ + public class MouseInputHandler implements MouseInputListener + { + /** + * Called when a mouse button press/release cycle completes + * on the {@link JList} + * + * @param event The event representing the mouse click + */ + public void mouseClicked(MouseEvent event) + { + Point click = event.getPoint(); + int index = BasicListUI.this.locationToIndex(list, click); + if (index == -1) + return; + 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); + else + BasicListUI.this.list.addSelectionInterval(index,index); + } + else if (event.isShiftDown()) + { + if (BasicListUI.this.list.getSelectionMode() == + ListSelectionModel.SINGLE_SELECTION) + BasicListUI.this.list.setSelectedIndex(index); + else if (BasicListUI.this.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); + else + // COMPAT: both Sun and IBM are compatible instead with: + // BasicListUI.this.list.setSelectionInterval + // (BasicListUI.this.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); + } + else + BasicListUI.this.list.setSelectedIndex(index); + } + + /** + * Called when a mouse button is pressed down on the + * {@link JList}. + * + * @param event The event representing the mouse press + */ + public void mousePressed(MouseEvent event) + { + } + + /** + * Called when a mouse button is released on + * the {@link JList} + * + * @param event The event representing the mouse press + */ + public void mouseReleased(MouseEvent event) + { + } + + /** + * Called when the mouse pointer enters the area bounded + * by the {@link JList} + * + * @param event The event representing the mouse entry + */ + public void mouseEntered(MouseEvent event) + { + } + + /** + * Called when the mouse pointer leaves the area bounded + * by the {@link JList} + * + * @param event The event representing the mouse exit + */ + public void mouseExited(MouseEvent event) + { + } + + /** + * Called when the mouse pointer moves over the area bounded + * by the {@link JList} while a button is held down. + * + * @param event The event representing the mouse drag + */ + public void mouseDragged(MouseEvent event) + { + } + + /** + * Called when the mouse pointer moves over the area bounded + * by the {@link JList}. + * + * @param event The event representing the mouse move + */ + public void mouseMoved(MouseEvent event) + { + } + } + + /** + * Helper class which listens to {@link PropertyChangeEvent}s + * from the {@link JList}. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when the {@link JList} changes one of its bound properties. + * + * @param e The event representing the property change + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getSource() == BasicListUI.this.list) + { + if (e.getOldValue() != null && e.getOldValue() instanceof ListModel) + ((ListModel) e.getOldValue()).removeListDataListener(BasicListUI.this.listDataListener); + + if (e.getNewValue() != null && e.getNewValue() instanceof ListModel) + ((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener); + } + BasicListUI.this.damageLayout(); + } + } + + /** + * Creates a new BasicListUI for the component. + * + * @param c The component to create a UI for + * + * @return A new UI + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicListUI(); + } + + /** The current focus listener. */ + protected FocusListener focusListener; + + /** The data listener listening to the model. */ + protected ListDataListener listDataListener; + + /** The selection listener listening to the selection model. */ + protected ListSelectionListener listSelectionListener; + + /** 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; + + + /** The component listener that receives notification for resizing the + * JList component.*/ + private ComponentListener componentListener; + + /** Saved reference to the list this UI was created for. */ + protected JList list; + + /** The height of a single cell in the list. */ + protected int cellHeight; + + /** The width of a single cell in the list. */ + protected int cellWidth; + + /** + * An array of varying heights of cells in the list, in cases where each + * cell might have a different height. + */ + protected int[] cellHeights; + + /** + * A simple counter. 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. + */ + protected int updateLayoutStateNeeded; + + /** + * The {@link CellRendererPane} that is used for painting. + */ + protected CellRendererPane rendererPane; + + /** + * Calculate the height of a particular row. If there is a fixed {@link + * #cellHeight}, return it; otherwise return the specific row height + * requested from the {@link #cellHeights} array. If the requested row + * is invalid, return -1. + * + * @param row The row to get the height of + * + * @return The height, in pixels, of the specified row + */ + protected int getRowHeight(int row) + { + if (row < 0 || row >= cellHeights.length) + return -1; + else if (cellHeight != -1) + return cellHeight; + else + return cellHeights[row]; + } + + /** + * Calculate the bounds of a particular cell, considering the upper left + * corner of the list as the origin position (0,0). + * + * @param l Ignored; calculates over this.list + * @param index1 The first row to include in the bounds + * @param index2 The last row to incude in the bounds + * + * @return A rectangle encompassing the range of rows between + * index1 and index2 inclusive + */ + public Rectangle getCellBounds(JList l, int index1, int index2) + { + maybeUpdateLayoutState(); + + if (l != list || cellWidth == -1) + return null; + + int minIndex = Math.min(index1, index2); + int maxIndex = Math.max(index1, index2); + Point loc = indexToLocation(list, minIndex); + Rectangle bounds = new Rectangle(loc.x, loc.y, cellWidth, + getRowHeight(minIndex)); + + for (int i = minIndex + 1; i <= maxIndex; i++) + { + Point hiLoc = indexToLocation(list, i); + Rectangle hibounds = new Rectangle(hiLoc.x, hiLoc.y, cellWidth, + getRowHeight(i)); + bounds = bounds.union(hibounds); + } + + return bounds; + } + + /** + * Calculate the Y coordinate of the upper edge of a particular row, + * considering the Y coordinate 0 to occur at the top of the + * list. + * + * @param row The row to calculate the Y coordinate of + * + * @return The Y coordinate of the specified row, or -1 if + * the specified row number is invalid + */ + protected int convertRowToY(int row) + { + int y = 0; + for (int i = 0; i < row; ++i) + { + int h = getRowHeight(i); + if (h == -1) + return -1; + y += h; + } + return y; + } + + /** + * Calculate the row number containing a particular Y coordinate, + * considering the Y coodrinate 0 to occur at the top of the + * list. + * + * @param y0 The Y coordinate to calculate the row number for + * + * @return The row number containing the specified Y value, or -1 + * if the specified Y coordinate is invalid + */ + protected int convertYToRow(int y0) + { + for (int row = 0; row < cellHeights.length; ++row) + { + int h = getRowHeight(row); + + if (y0 < h) + return row; + y0 -= h; + } + return -1; + } + + /** + * Recomputes the {@link #cellHeights}, {@link #cellHeight}, and {@link + * #cellWidth} properties by examining the variouis properties of the + * {@link JList}. + */ + protected void updateLayoutState() + { + int nrows = list.getModel().getSize(); + cellHeight = -1; + cellWidth = -1; + if (cellHeights == null || cellHeights.length != nrows) + cellHeights = new int[nrows]; + if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1) + { + ListCellRenderer rend = list.getCellRenderer(); + for (int i = 0; i < nrows; ++i) + { + Component flyweight = rend.getListCellRendererComponent(list, + list.getModel() + .getElementAt(i), + 0, false, + false); + 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); + } + } + else + { + cellHeight = list.getFixedCellHeight(); + cellWidth = list.getFixedCellWidth(); + } + } + + /** + * Marks the current layout as damaged and requests revalidation from the + * JList. + * This is package-private to avoid an accessor method. + * + * @see #updateLayoutStateNeeded + */ + void damageLayout() + { + updateLayoutStateNeeded = 1; + } + + /** + * Calls {@link #updateLayoutState} if {@link #updateLayoutStateNeeded} + * is nonzero, then resets {@link #updateLayoutStateNeeded} to zero. + */ + protected void maybeUpdateLayoutState() + { + if (updateLayoutStateNeeded != 0) + { + updateLayoutState(); + updateLayoutStateNeeded = 0; + } + } + + /** + * Creates a new BasicListUI object. + */ + 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(); + } + + /** + * Installs various default settings (mostly colors) from the {@link + * UIDefaults} into the {@link JList} + * + * @see #uninstallDefaults + */ + 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")); + list.setOpaque(true); + } + + /** + * Resets to null those defaults which were installed in + * {@link #installDefaults} + */ + protected void uninstallDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + list.setForeground(null); + list.setBackground(null); + list.setSelectionForeground(null); + list.setSelectionBackground(null); + } + + /** + * Attaches all the listeners we have in the UI class to the {@link + * JList}, its model and its selection model. + * + * @see #uninstallListeners + */ + protected void installListeners() + { + list.addFocusListener(focusListener); + list.getModel().addListDataListener(listDataListener); + list.addListSelectionListener(listSelectionListener); + list.addMouseListener(mouseInputListener); + list.addKeyListener(keyListener); + list.addMouseMotionListener(mouseInputListener); + list.addPropertyChangeListener(propertyChangeListener); + list.addComponentListener(componentListener); + } + + /** + * Detaches all the listeners we attached in {@link #installListeners}. + */ + protected void uninstallListeners() + { + list.removeFocusListener(focusListener); + list.getModel().removeListDataListener(listDataListener); + list.removeListSelectionListener(listSelectionListener); + list.removeMouseListener(mouseInputListener); + list.removeKeyListener(keyListener); + list.removeMouseMotionListener(mouseInputListener); + list.removePropertyChangeListener(propertyChangeListener); + } + + /** + * Installs keyboard actions for this UI in the {@link JList}. + */ + protected void installKeyboardActions() + { + } + + /** + * Uninstalls keyboard actions for this UI in the {@link JList}. + */ + protected void uninstallKeyboardActions() + { + } + + /** + * Installs the various aspects of the UI in the {@link JList}. In + * particular, calls {@link #installDefaults}, {@link #installListeners} + * and {@link #installKeyboardActions}. Also saves a reference to the + * provided component, cast to a {@link JList}. + * + * @param c The {@link JList} to install the UI into + */ + public void installUI(final JComponent c) + { + super.installUI(c); + list = (JList) c; + installDefaults(); + installListeners(); + installKeyboardActions(); + maybeUpdateLayoutState(); + } + + /** + * Uninstalls all the aspects of the UI which were installed in {@link + * #installUI}. When finished uninstalling, drops the saved reference to + * the {@link JList}. + * + * @param c Ignored; the UI is uninstalled from the {@link JList} + * reference saved during the call to {@link #installUI} + */ + public void uninstallUI(final JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + list = null; + } + + /** + * Gets the size this list would prefer to assume. This is calculated by + * calling {@link #getCellBounds} over the entire list. + * + * @param c Ignored; uses the saved {@link JList} reference + * + * @return DOCUMENT ME! + */ + public Dimension getPreferredSize(JComponent c) + { + int size = list.getModel().getSize(); + if (size == 0) + return new Dimension(0, 0); + int visibleRows = list.getVisibleRowCount(); + int layoutOrientation = list.getLayoutOrientation(); + Rectangle bounds = getCellBounds(list, 0, list.getModel().getSize() - 1); + Dimension retVal = bounds.getSize(); + Component parent = list.getParent(); + if ((visibleRows == -1) && (parent instanceof JViewport)) + { + JViewport viewport = (JViewport) parent; + + if (layoutOrientation == JList.HORIZONTAL_WRAP) + { + int h = viewport.getSize().height; + int cellsPerCol = h / cellHeight; + int w = size / cellsPerCol * cellWidth; + retVal = new Dimension(w, h); + } + else if (layoutOrientation == JList.VERTICAL_WRAP) + { + int w = viewport.getSize().width; + int cellsPerRow = Math.max(w / cellWidth, 1); + int h = size / cellsPerRow * cellHeight; + retVal = new Dimension(w, h); + } + } + return retVal; + } + + /** + * 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 + * @param row The row number to paint + * @param bounds The bounds of the cell to paint, assuming a coordinate + * system beginning at (0,0) in the upper left corner of the + * list + * @param rend A cell renderer to paint with + * @param data The data to provide to the cell renderer + * @param sel A selection model to provide to the cell renderer + * @param lead The lead selection index of the list + */ + protected void paintCell(Graphics g, int row, Rectangle bounds, + ListCellRenderer rend, ListModel data, + ListSelectionModel sel, int lead) + { + boolean is_sel = list.isSelectedIndex(row); + boolean has_focus = false; + Component comp = rend.getListCellRendererComponent(list, + data.getElementAt(row), + 0, is_sel, has_focus); + //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. + * + * @param g The graphics context to paint with + * @param c Ignored; uses the saved {@link JList} reference + */ + public void paint(Graphics g, JComponent c) + { + int nrows = list.getModel().getSize(); + if (nrows == 0) + return; + + maybeUpdateLayoutState(); + ListCellRenderer render = list.getCellRenderer(); + ListModel model = list.getModel(); + ListSelectionModel sel = list.getSelectionModel(); + int lead = sel.getLeadSelectionIndex(); + Rectangle clip = g.getClipBounds(); + paintBackground(g, list); + + for (int row = 0; row < nrows; ++row) + { + Rectangle bounds = getCellBounds(list, row, row); + if (bounds.intersects(clip)) + paintCell(g, row, bounds, render, model, sel, lead); + } + } + + /** + * Computes the index of a list cell given a point within the list. + * + * @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 null if the location is invalid + */ + public int locationToIndex(JList list, Point location) + { + int layoutOrientation = list.getLayoutOrientation(); + int index = -1; + switch (layoutOrientation) + { + case JList.VERTICAL: + index = convertYToRow(location.y); + break; + case JList.HORIZONTAL_WRAP: + // determine visible rows and cells per row + int visibleRows = list.getVisibleRowCount(); + int cellsPerRow = -1; + int numberOfItems = list.getModel().getSize(); + Dimension listDim = list.getSize(); + if (visibleRows <= 0) + { + try + { + cellsPerRow = listDim.width / cellWidth; + } + catch (ArithmeticException ex) + { + cellsPerRow = 1; + } + } + else + { + cellsPerRow = numberOfItems / visibleRows + 1; + } + + // determine index for the given location + int cellsPerColumn = numberOfItems / cellsPerRow + 1; + int gridX = Math.min(location.x / cellWidth, cellsPerRow - 1); + int gridY = Math.min(location.y / cellHeight, cellsPerColumn); + index = gridX + gridY * cellsPerRow; + break; + case JList.VERTICAL_WRAP: + // determine visible rows and cells per column + int visibleRows2 = list.getVisibleRowCount(); + if (visibleRows2 <= 0) + { + Dimension listDim2 = list.getSize(); + visibleRows2 = listDim2.height / cellHeight; + } + 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; + break; + } + return index; + } + + public Point indexToLocation(JList list, int index) + { + int layoutOrientation = list.getLayoutOrientation(); + Point loc = null; + switch (layoutOrientation) + { + case JList.VERTICAL: + loc = new Point(0, convertRowToY(index)); + break; + case JList.HORIZONTAL_WRAP: + // determine visible rows and cells per row + int visibleRows = list.getVisibleRowCount(); + int numberOfCellsPerRow = -1; + if (visibleRows <= 0) + { + Dimension listDim = list.getSize(); + numberOfCellsPerRow = Math.max(listDim.width / cellWidth, 1); + } + else + { + int numberOfItems = list.getModel().getSize(); + numberOfCellsPerRow = numberOfItems / visibleRows + 1; + } + // compute coordinates inside the grid + int gridX = index % numberOfCellsPerRow; + int gridY = index / numberOfCellsPerRow; + int locX = gridX * cellWidth; + int locY = gridY * cellHeight; + loc = new Point(locX, locY); + break; + case JList.VERTICAL_WRAP: + // determine visible rows and cells per column + int visibleRows2 = list.getVisibleRowCount(); + if (visibleRows2 <= 0) + { + Dimension listDim2 = list.getSize(); + visibleRows2 = listDim2.height / cellHeight; + } + // compute coordinates inside the grid + if (visibleRows2 > 0) + { + int gridY2 = index % visibleRows2; + int gridX2 = index / visibleRows2; + int locX2 = gridX2 * cellWidth; + int locY2 = gridY2 * cellHeight; + loc = new Point(locX2, locY2); + } + else + loc = new Point(0, convertRowToY(index)); + break; + } + return loc; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java new file mode 100644 index 0000000..14fe28f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -0,0 +1,1058 @@ +/* BasicLookAndFeel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.ResourceBundle; + +import javax.swing.BorderFactory; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.UIDefaults; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.DimensionUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.text.JTextComponent; + +/** + * BasicLookAndFeel + * @author Andrew Selkirk + */ +public abstract class BasicLookAndFeel extends LookAndFeel + implements Serializable +{ + static final long serialVersionUID = -6096995660290287879L; + + /** + * Creates a new instance of the Basic look and feel. + */ + public BasicLookAndFeel() + { + // TODO + } + + /** + * Creates and returns a new instance of the default resources for this look + * and feel. + * + * @return The UI defaults. + */ + public UIDefaults getDefaults() + { + // Variables + UIDefaults def = new UIDefaults(); + // Initialize Class Defaults + initClassDefaults(def); + // Initialize System Colour Defaults + initSystemColorDefaults(def); + // Initialize Component Defaults + initComponentDefaults(def); + // Return UI Defaults + return def; + } + + /** + * Populates the defaults table with mappings between class IDs + * and fully qualified class names for the UI delegates. + * + * @param defaults the defaults table (null not permitted). + */ + protected void initClassDefaults(UIDefaults defaults) + { + // Variables + Object[] uiDefaults; + // Initialize Class Defaults + uiDefaults = new Object[] { + "ButtonUI", "javax.swing.plaf.basic.BasicButtonUI", + "CheckBoxMenuItemUI", "javax.swing.plaf.basic.BasicCheckBoxMenuItemUI", + "CheckBoxUI", "javax.swing.plaf.basic.BasicCheckBoxUI", + "ColorChooserUI", "javax.swing.plaf.basic.BasicColorChooserUI", + "ComboBoxUI", "javax.swing.plaf.basic.BasicComboBoxUI", + "DesktopIconUI", "javax.swing.plaf.basic.BasicDesktopIconUI", + "DesktopPaneUI", "javax.swing.plaf.basic.BasicDesktopPaneUI", + "EditorPaneUI", "javax.swing.plaf.basic.BasicEditorPaneUI", + "FileChooserUI", "javax.swing.plaf.basic.BasicFileChooserUI", + "FormattedTextFieldUI", "javax.swing.plaf.basic.BasicFormattedTextFieldUI", + "InternalFrameUI", "javax.swing.plaf.basic.BasicInternalFrameUI", + "LabelUI", "javax.swing.plaf.basic.BasicLabelUI", + "ListUI", "javax.swing.plaf.basic.BasicListUI", + "MenuBarUI", "javax.swing.plaf.basic.BasicMenuBarUI", + "MenuItemUI", "javax.swing.plaf.basic.BasicMenuItemUI", + "MenuUI", "javax.swing.plaf.basic.BasicMenuUI", + "OptionPaneUI", "javax.swing.plaf.basic.BasicOptionPaneUI", + "PanelUI", "javax.swing.plaf.basic.BasicPanelUI", + "PasswordFieldUI", "javax.swing.plaf.basic.BasicPasswordFieldUI", + "PopupMenuSeparatorUI", "javax.swing.plaf.basic.BasicPopupMenuSeparatorUI", + "PopupMenuUI", "javax.swing.plaf.basic.BasicPopupMenuUI", + "ProgressBarUI", "javax.swing.plaf.basic.BasicProgressBarUI", + "RadioButtonMenuItemUI", "javax.swing.plaf.basic.BasicRadioButtonMenuItemUI", + "RadioButtonUI", "javax.swing.plaf.basic.BasicRadioButtonUI", + "RootPaneUI", "javax.swing.plaf.basic.BasicRootPaneUI", + "ScrollBarUI", "javax.swing.plaf.basic.BasicScrollBarUI", + "ScrollPaneUI", "javax.swing.plaf.basic.BasicScrollPaneUI", + "SeparatorUI", "javax.swing.plaf.basic.BasicSeparatorUI", + "SliderUI", "javax.swing.plaf.basic.BasicSliderUI", + "SplitPaneUI", "javax.swing.plaf.basic.BasicSplitPaneUI", + "SpinnerUI", "javax.swing.plaf.basic.BasicSpinnerUI", + "StandardDialogUI", "javax.swing.plaf.basic.BasicStandardDialogUI", + "TabbedPaneUI", "javax.swing.plaf.basic.BasicTabbedPaneUI", + "TableHeaderUI", "javax.swing.plaf.basic.BasicTableHeaderUI", + "TableUI", "javax.swing.plaf.basic.BasicTableUI", + "TextPaneUI", "javax.swing.plaf.basic.BasicTextPaneUI", + "TextAreaUI", "javax.swing.plaf.basic.BasicTextAreaUI", + "TextFieldUI", "javax.swing.plaf.basic.BasicTextFieldUI", + "TextPaneUI", "javax.swing.plaf.basic.BasicTextPaneUI", + "ToggleButtonUI", "javax.swing.plaf.basic.BasicToggleButtonUI", + "ToolBarSeparatorUI", "javax.swing.plaf.basic.BasicToolBarSeparatorUI", + "ToolBarUI", "javax.swing.plaf.basic.BasicToolBarUI", + "ToolTipUI", "javax.swing.plaf.basic.BasicToolTipUI", + "TreeUI", "javax.swing.plaf.basic.BasicTreeUI", + "ViewportUI", "javax.swing.plaf.basic.BasicViewportUI" + }; + // Add Class Defaults to UI Defaults table + defaults.putDefaults(uiDefaults); + } + + /** + * Populates the defaults table with system color defaults. + * + * @param defaults the defaults table (null not permitted). + */ + protected void initSystemColorDefaults(UIDefaults defaults) + { + Color highLight = new Color(249, 247, 246); + Color light = new Color(239, 235, 231); + Color shadow = new Color(139, 136, 134); + Color darkShadow = new Color(16, 16, 16); + + Object[] uiDefaults; + uiDefaults = new Object[] { + "activeCaption", new ColorUIResource(0, 0, 128), + "activeCaptionBorder", new ColorUIResource(Color.lightGray), + "activeCaptionText", new ColorUIResource(Color.white), + "control", new ColorUIResource(light), + "controlDkShadow", new ColorUIResource(shadow), + "controlHighlight", new ColorUIResource(highLight), + "controlLtHighlight", new ColorUIResource(highLight), + "controlShadow", new ColorUIResource(shadow), + "controlText", new ColorUIResource(darkShadow), + "desktop", new ColorUIResource(0, 92, 92), + "inactiveCaption", new ColorUIResource(Color.gray), + "inactiveCaptionBorder", new ColorUIResource(Color.lightGray), + "inactiveCaptionText", new ColorUIResource(Color.lightGray), + "info", new ColorUIResource(light), + "infoText", new ColorUIResource(darkShadow), + "menu", new ColorUIResource(light), + "menuText", new ColorUIResource(darkShadow), + "scrollbar", new ColorUIResource(light), + "text", new ColorUIResource(Color.white), + "textHighlight", new ColorUIResource(Color.black), + "textHighlightText", new ColorUIResource(Color.white), + "textInactiveText", new ColorUIResource(Color.gray), + "textText", new ColorUIResource(Color.black), + "window", new ColorUIResource(light), + "windowBorder", new ColorUIResource(Color.black), + "windowText", new ColorUIResource(darkShadow) + }; + defaults.putDefaults(uiDefaults); + } + + /** + * Loads the system colors. This method is not implemented yet. + * + * @param defaults the defaults table (null not permitted). + * @param systemColors TODO + * @param useNative TODO + */ + protected void loadSystemColors(UIDefaults defaults, String[] systemColors, + boolean useNative) + { + // TODO + } + + /** + * loadResourceBundle + * @param defaults TODO + */ + private void loadResourceBundle(UIDefaults defaults) + { + ResourceBundle bundle; + Enumeration e; + String key; + String value; + bundle = ResourceBundle.getBundle("resources/basic"); + // Process Resources + e = bundle.getKeys(); + while (e.hasMoreElements()) + { + key = (String) e.nextElement(); + value = bundle.getString(key); + defaults.put(key, value); + } + } + + /** + * initComponentDefaults + * @param defaults the defaults table (null not permitted). + */ + protected void initComponentDefaults(UIDefaults defaults) + { + Object[] uiDefaults; + + Color highLight = new Color(249, 247, 246); + Color light = new Color(239, 235, 231); + Color shadow = new Color(139, 136, 134); + Color darkShadow = new Color(16, 16, 16); + + uiDefaults = new Object[] { + + "AbstractUndoableEdit.undoText", "Undo", + "AbstractUndoableEdit.redoText", "Redo", + "Button.background", new ColorUIResource(Color.LIGHT_GRAY), + "Button.border", + new UIDefaults.LazyValue() + { + public Object createValue(UIDefaults table) + { + return BasicBorders.getButtonBorder(); + } + }, + "Button.darkShadow", new ColorUIResource(Color.BLACK), + "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "Button.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "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.shadow", new ColorUIResource(Color.GRAY), + "Button.textIconGap", new Integer(4), + "Button.textShiftOffset", new Integer(0), + "CheckBox.background", new ColorUIResource(light), + "CheckBox.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "CheckBox.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "CheckBox.foreground", new ColorUIResource(darkShadow), + "CheckBox.icon", BasicIconFactory.getCheckBoxIcon(), + "CheckBox.margin",new InsetsUIResource(2, 2, 2, 2), + "CheckBox.textIconGap", new Integer(4), + "CheckBox.textShiftOffset", new Integer(0), + "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", + Font.PLAIN, 12), + "CheckBoxMenuItem.acceleratorForeground", + new ColorUIResource(darkShadow), + "CheckBoxMenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "CheckBoxMenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "CheckBoxMenuItem.background", new ColorUIResource(light), + "CheckBoxMenuItem.border", new BasicBorders.MarginBorder(), + "CheckBoxMenuItem.borderPainted", Boolean.FALSE, + "CheckBoxMenuItem.checkIcon", BasicIconFactory.getCheckBoxMenuItemIcon(), + "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "CheckBoxMenuItem.foreground", new ColorUIResource(darkShadow), + "CheckBoxMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), + "CheckBoxMenuItem.selectionBackground", new ColorUIResource(Color.black), + "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.white), + "ColorChooser.background", new ColorUIResource(light), + "ColorChooser.cancelText", "Cancel", + "ColorChooser.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ColorChooser.foreground", new ColorUIResource(darkShadow), + "ColorChooser.hsbBlueText", "B", + "ColorChooser.hsbBrightnessText", "B", + "ColorChooser.hsbGreenText", "G", + "ColorChooser.hsbHueText", "H", + "ColorChooser.hsbNameText", "HSB", + "ColorChooser.hsbRedText", "R", + "ColorChooser.hsbSaturationText", "S", + "ColorChooser.okText", "OK", + "ColorChooser.previewText", "Preview", + "ColorChooser.resetText", "Reset", + "ColorChooser.rgbBlueMnemonic", new Integer(66), + "ColorChooser.rgbBlueText", "Blue", + "ColorChooser.rgbGreenMnemonic", new Integer(71), + "ColorChooser.rgbGreenText", "Green", + "ColorChooser.rgbNameText", "RGB", + "ColorChooser.rgbRedMnemonic", new Integer(82), + "ColorChooser.rgbRedText", "Red", + "ColorChooser.sampleText", "Sample Text Sample Text", + "ColorChooser.swatchesDefaultRecentColor", new ColorUIResource(light), + "ColorChooser.swatchesNameText", "Swatches", + "ColorChooser.swatchesRecentSwatchSize", new Dimension(10, 10), + "ColorChooser.swatchesRecentText", "Recent:", + "ColorChooser.swatchesSwatchSize", new Dimension(10, 10), + "ComboBox.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "hidePopup", + "PAGE_UP", "pageUpPassThrough", + "PAGE_DOWN", "pageDownPassThrough", + "HOME", "homePassThrough", + "END", "endPassThrough" + }), + "ComboBox.background", new ColorUIResource(light), + "ComboBox.buttonBackground", new ColorUIResource(light), + "ComboBox.buttonDarkShadow", new ColorUIResource(shadow), + "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.selectionForeground", new ColorUIResource(Color.white), + "Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "KP_LEFT", "left", + "KP_RIGHT", "right", + "ctrl F5", "restore", + "LEFT", "left", + "ctrl alt F6", "selectNextFrame", + "UP", "up", + "ctrl F6", "selectNextFrame", + "RIGHT", "right", + "DOWN", "down", + "ctrl F7", "move", + "ctrl F8", "resize", + "ESCAPE", "escape", + "ctrl TAB", "selectNextFrame", + "ctrl F9", "minimize", + "KP_UP", "up", + "ctrl F4", "close", + "KP_DOWN", "down", + "ctrl F10", "maximize", + "ctrl alt shift F6","selectPreviousFrame" + }), + "Desktop.background", new ColorUIResource(0, 92, 92), + "DesktopIcon.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "EditorPane.background", new ColorUIResource(Color.white), + "EditorPane.border", new BasicBorders.MarginBorder(), + "EditorPane.caretBlinkRate", new Integer(500), + "EditorPane.caretForeground", new ColorUIResource(Color.black), + "EditorPane.font", new FontUIResource("Serif", Font.PLAIN, 12), + "EditorPane.foreground", new ColorUIResource(Color.black), + "EditorPane.inactiveForeground", new ColorUIResource(Color.gray), + "EditorPane.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "EditorPane.margin", new InsetsUIResource(3, 3, 3, 3), + "EditorPane.selectionBackground", new ColorUIResource(Color.black), + "EditorPane.selectionForeground", new ColorUIResource(Color.white), + "FileChooser.acceptAllFileFilterText", "All Files (*.*)", + "FileChooser.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "cancelSelection" + }), + "FileChooser.cancelButtonMnemonic", new Integer(67), + "FileChooser.cancelButtonText", "Cancel", + "FileChooser.cancelButtonToolTipText", "Abort file chooser dialog", + // XXX Don't use gif +// "FileChooser.detailsViewIcon", new IconUIResource(new ImageIcon("icons/DetailsView.gif")), + "FileChooser.directoryDescriptionText", "Directory", + "FileChooser.fileDescriptionText", "Generic File", + "FileChooser.helpButtonMnemonic", new Integer(72), + "FileChooser.helpButtonText", "Help", + "FileChooser.helpButtonToolTipText", "FileChooser help", + // XXX Don't use gif +// "FileChooser.homeFolderIcon", new IconUIResource(new ImageIcon("icons/HomeFolder.gif")), + // XXX Don't use gif +// "FileChooser.listViewIcon", new IconUIResource(new ImageIcon("icons/ListView.gif")), + "FileChooser.newFolderErrorSeparator", ":", + "FileChooser.newFolderErrorText", "Error creating new folder", + // XXX Don't use gif +// "FileChooser.newFolderIcon", new IconUIResource(new ImageIcon("icons/NewFolder.gif")), + "FileChooser.openButtonMnemonic", new Integer(79), + "FileChooser.openButtonText", "Open", + "FileChooser.openButtonToolTipText", "Open selected file", + "FileChooser.saveButtonMnemonic", new Integer(83), + "FileChooser.saveButtonText", "Save", + "FileChooser.saveButtonToolTipText", "Save selected file", + // XXX Don't use gif +// "FileChooser.upFolderIcon", new IconUIResource(new ImageIcon("icons/UpFolder.gif")), + "FileChooser.updateButtonMnemonic", new Integer(85), + "FileChooser.updateButtonText", "Update", + "FileChooser.updateButtonToolTipText", "Update directory listing", + // XXX Don't use gif +// "FileView.computerIcon", new IconUIResource(new ImageIcon("icons/Computer.gif")), + // XXX Don't use gif +// "FileView.directoryIcon", new IconUIResource(new ImageIcon("icons/Directory.gif")), + // XXX Don't use gif +// "FileView.fileIcon", new IconUIResource(new ImageIcon("icons/File.gif")), + // XXX Don't use gif +// "FileView.floppyDriveIcon", new IconUIResource(new ImageIcon("icons/Floppy.gif")), + // XXX Don't use gif +// "FileView.hardDriveIcon", new IconUIResource(new ImageIcon("icons/HardDrive.gif")), + "FocusManagerClassName", "TODO", + "FormattedTextField.background", new ColorUIResource(light), + "FormattedTextField.caretForeground", new ColorUIResource(Color.black), + "FormattedTextField.foreground", new ColorUIResource(Color.black), + "FormattedTextField.inactiveBackground", new ColorUIResource(light), + "FormattedTextField.inactiveForeground", new ColorUIResource(Color.gray), + "FormattedTextField.selectionBackground", + new ColorUIResource(Color.black), + "FormattedTextField.selectionForeground", + new ColorUIResource(Color.white), + "FormView.resetButtonText", "Reset", + "FormView.submitButtonText", "Submit Query", + "InternalFrame.activeTitleBackground", new ColorUIResource(0, 0, 128), + "InternalFrame.activeTitleForeground", new ColorUIResource(Color.white), + "InternalFrame.border", + new UIDefaults.LazyValue() + { + public Object createValue(UIDefaults table) + { + Color lineColor = new Color(238, 238, 238); + Border inner = BorderFactory.createLineBorder(lineColor, 1); + Color shadowInner = new Color(184, 207, 229); + Color shadowOuter = new Color(122, 138, 153); + Border outer = BorderFactory.createBevelBorder(BevelBorder.RAISED, + Color.WHITE, + Color.WHITE, + shadowOuter, + shadowInner); + Border border = new BorderUIResource.CompoundBorderUIResource(outer, + inner); + return border; + } + }, + "InternalFrame.borderColor", new ColorUIResource(light), + "InternalFrame.borderDarkShadow", new ColorUIResource(Color.BLACK), + "InternalFrame.borderHighlight", new ColorUIResource(Color.WHITE), + "InternalFrame.borderLight", new ColorUIResource(Color.LIGHT_GRAY), + "InternalFrame.borderShadow", new ColorUIResource(Color.GRAY), + "InternalFrame.closeIcon", BasicIconFactory.createEmptyFrameIcon(), + // XXX Don't use gif +// "InternalFrame.icon", new IconUIResource(new ImageIcon("icons/JavaCup.gif")), + "InternalFrame.iconifyIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.inactiveTitleBackground", new ColorUIResource(Color.gray), + "InternalFrame.inactiveTitleForeground", + new ColorUIResource(Color.lightGray), + "InternalFrame.maximizeIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.minimizeIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.titleFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "InternalFrame.windowBindings", new Object[] { + "shift ESCAPE", "showSystemMenu", + "ctrl SPACE", "showSystemMenu", + "ESCAPE", "showSystemMenu" + }, + "Label.background", new ColorUIResource(light), + "Label.disabledForeground", new ColorUIResource(Color.white), + "Label.disabledShadow", new ColorUIResource(shadow), + "Label.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Label.foreground", new ColorUIResource(darkShadow), + "List.background", new ColorUIResource(light), + "List.border", new BasicBorders.MarginBorder(), + "List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "scrollUp", + "ctrl \\", "clearSelection", + "PAGE_DOWN", "scrollDown", + "shift PAGE_DOWN","scrollDownExtendSelection", + "END", "selectLastRow", + "HOME", "selectFirstRow", + "shift END", "selectLastRowExtendSelection", + "shift HOME", "selectFirstRowExtendSelection", + "UP", "selectPreviousRow", + "ctrl /", "selectAll", + "ctrl A", "selectAll", + "DOWN", "selectNextRow", + "shift UP", "selectPreviousRowExtendSelection", + "ctrl SPACE", "selectNextRowExtendSelection", + "shift DOWN", "selectNextRowExtendSelection", + "KP_UP", "selectPreviousRow", + "shift PAGE_UP","scrollUpExtendSelection", + "KP_DOWN", "selectNextRow" + }), + "List.foreground", new ColorUIResource(darkShadow), + "List.selectionBackground", new ColorUIResource(Color.black), + "List.selectionForeground", new ColorUIResource(Color.white), + "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "Menu.acceleratorForeground", new ColorUIResource(darkShadow), + "Menu.acceleratorSelectionForeground", new ColorUIResource(Color.white), + "Menu.arrowIcon", BasicIconFactory.getMenuArrowIcon(), + "Menu.background", new ColorUIResource(light), + "Menu.border", new BasicBorders.MarginBorder(), + "Menu.borderPainted", Boolean.FALSE, + "Menu.checkIcon", BasicIconFactory.getMenuItemCheckIcon(), + "Menu.consumesTabs", Boolean.TRUE, + "Menu.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Menu.foreground", new ColorUIResource(darkShadow), + "Menu.margin", new InsetsUIResource(2, 2, 2, 2), + "Menu.selectedWindowInputMapBindings", new Object[] { + "ESCAPE", "cancel", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "UP", "selectPrevious", + "KP_UP", "selectPrevious", + "LEFT", "selectParent", + "KP_LEFT", "selectParent", + "RIGHT", "selectChild", + "KP_RIGHT", "selectChild", + "ENTER", "return", + "SPACE", "return" + }, + "Menu.selectionBackground", new ColorUIResource(Color.black), + "Menu.selectionForeground", new ColorUIResource(Color.white), + "MenuBar.background", new ColorUIResource(light), + "MenuBar.border", new BasicBorders.MenuBarBorder(null, null), + "MenuBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "MenuBar.foreground", new ColorUIResource(darkShadow), + "MenuBar.highlight", new ColorUIResource(highLight), + "MenuBar.shadow", new ColorUIResource(shadow), + "MenuBar.windowBindings", new Object[] { + "F10", "takeFocus" + }, + "MenuItem.acceleratorDelimiter", "-", + "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "MenuItem.acceleratorForeground", new ColorUIResource(darkShadow), + "MenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "MenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "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), + "MenuItem.selectionBackground", new ColorUIResource(Color.black), + "MenuItem.selectionForeground", new ColorUIResource(Color.white), + "OptionPane.background", new ColorUIResource(light), + "OptionPane.border", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.buttonAreaBorder", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.cancelButtonText", "Cancel", + // XXX Don't use gif +// "OptionPane.errorIcon", +// new IconUIResource(new ImageIcon("icons/Error.gif")), + "OptionPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "OptionPane.foreground", new ColorUIResource(darkShadow), + // XXX Don't use gif +// "OptionPane.informationIcon", +// new IconUIResource(new ImageIcon("icons/Inform.gif")), + "OptionPane.messageAreaBorder", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.messageForeground", new ColorUIResource(darkShadow), + "OptionPane.minimumSize", new DimensionUIResource(262, 90), + "OptionPane.noButtonText", "No", + "OptionPane.okButtonText", "OK", + // XXX Don't use gif +// "OptionPane.questionIcon", +// new IconUIResource(new ImageIcon("icons/Question.gif")), + // XXX Don't use gif +// "OptionPane.warningIcon", +// new IconUIResource(new ImageIcon("icons/Warn.gif")), + "OptionPane.windowBindings", new Object[] { + "ESCAPE", "close" + }, + "OptionPane.yesButtonText", "Yes", + "Panel.background", new ColorUIResource(light), + "Panel.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Panel.foreground", new ColorUIResource(Color.black), + "PasswordField.background", new ColorUIResource(light), + "PasswordField.border", new BasicBorders.FieldBorder(null, null, + null, null), + "PasswordField.caretBlinkRate", new Integer(500), + "PasswordField.caretForeground", new ColorUIResource(Color.black), + "PasswordField.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), + "PasswordField.foreground", new ColorUIResource(Color.black), + "PasswordField.inactiveBackground", new ColorUIResource(light), + "PasswordField.inactiveForeground", new ColorUIResource(Color.gray), + "PasswordField.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), + "notify-field-accept")}, + "PasswordField.margin", new InsetsUIResource(0, 0, 0, 0), + "PasswordField.selectionBackground", new ColorUIResource(Color.black), + "PasswordField.selectionForeground", new ColorUIResource(Color.white), + "PopupMenu.background", new ColorUIResource(light), + "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.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), + "RadioButton.background", new ColorUIResource(light), + "RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "RadioButton.darkShadow", new ColorUIResource(shadow), + "RadioButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "RadioButton.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButton.foreground", new ColorUIResource(darkShadow), + "RadioButton.highlight", new ColorUIResource(highLight), + "RadioButton.icon", BasicIconFactory.getRadioButtonIcon(), + "RadioButton.light", new ColorUIResource(highLight), + "RadioButton.margin", new InsetsUIResource(2, 2, 2, 2), + "RadioButton.shadow", new ColorUIResource(shadow), + "RadioButton.textIconGap", new Integer(4), + "RadioButton.textShiftOffset", new Integer(0), + "RadioButtonMenuItem.acceleratorFont", + new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButtonMenuItem.acceleratorForeground", + new ColorUIResource(darkShadow), + "RadioButtonMenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "RadioButtonMenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "RadioButtonMenuItem.background", new ColorUIResource(light), + "RadioButtonMenuItem.border", new BasicBorders.MarginBorder(), + "RadioButtonMenuItem.borderPainted", Boolean.FALSE, + "RadioButtonMenuItem.checkIcon", BasicIconFactory.getRadioButtonMenuItemIcon(), + "RadioButtonMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButtonMenuItem.foreground", new ColorUIResource(darkShadow), + "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), + "RadioButtonMenuItem.selectionBackground", + new ColorUIResource(Color.black), + "RadioButtonMenuItem.selectionForeground", + new ColorUIResource(Color.white), + "RootPane.defaultButtonWindowKeyBindings", new Object[] { + "ENTER", "press", + "released ENTER", "release", + "ctrl ENTER", "press", + "ctrl released ENTER", "release" + }, + "ScrollBar.background", new ColorUIResource(224, 224, 224), + "ScrollBar.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "negativeBlockIncrement", + "PAGE_DOWN", "positiveBlockIncrement", + "END", "maxScroll", + "HOME", "minScroll", + "LEFT", "positiveUnitIncrement", + "KP_UP", "negativeUnitIncrement", + "KP_DOWN", "positiveUnitIncrement", + "UP", "negativeUnitIncrement", + "RIGHT", "negativeUnitIncrement", + "KP_LEFT", "positiveUnitIncrement", + "DOWN", "positiveUnitIncrement", + "KP_RIGHT", "negativeUnitIncrement" + }), + "ScrollBar.foreground", new ColorUIResource(light), + "ScrollBar.maximumThumbSize", new DimensionUIResource(4096, 4096), + "ScrollBar.minimumThumbSize", new DimensionUIResource(8, 8), + "ScrollBar.thumb", new ColorUIResource(light), + "ScrollBar.thumbDarkShadow", new ColorUIResource(shadow), + "ScrollBar.thumbHighlight", new ColorUIResource(highLight), + "ScrollBar.thumbShadow", new ColorUIResource(shadow), + "ScrollBar.track", new ColorUIResource(light), + "ScrollBar.trackHighlight", new ColorUIResource(shadow), + "ScrollPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "scrollUp", + "KP_LEFT", "unitScrollLeft", + "ctrl PAGE_DOWN","scrollRight", + "PAGE_DOWN", "scrollDown", + "KP_RIGHT", "unitScrollRight", + "LEFT", "unitScrollLeft", + "ctrl END", "scrollEnd", + "UP", "unitScrollUp", + "RIGHT", "unitScrollRight", + "DOWN", "unitScrollDown", + "ctrl HOME", "scrollHome", + "ctrl PAGE_UP", "scrollLeft", + "KP_UP", "unitScrollUp", + "KP_DOWN", "unitScrollDown" + }), + "ScrollPane.background", new ColorUIResource(light), + "ScrollPane.border", new BorderUIResource.EtchedBorderUIResource(), + "ScrollPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ScrollPane.foreground", new ColorUIResource(darkShadow), + "Separator.background", new ColorUIResource(highLight), + "Separator.foreground", new ColorUIResource(shadow), + "Separator.highlight", new ColorUIResource(highLight), + "Separator.shadow", new ColorUIResource(shadow), + "Slider.background", new ColorUIResource(light), + "Slider.focus", new ColorUIResource(shadow), + "Slider.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "positiveBlockIncrement", + "PAGE_DOWN", "negativeBlockIncrement", + "END", "maxScroll", + "HOME", "minScroll", + "LEFT", "negativeUnitIncrement", + "KP_UP", "positiveUnitIncrement", + "KP_DOWN", "negativeUnitIncrement", + "UP", "positiveUnitIncrement", + "RIGHT", "positiveUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "DOWN", "negativeUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement" + }), + "Slider.focusInsets", new InsetsUIResource(2, 2, 2, 2), + "Slider.foreground", new ColorUIResource(light), + "Slider.highlight", new ColorUIResource(highLight), + "Slider.shadow", new ColorUIResource(shadow), + "Slider.thumbHeight", new Integer(20), + "Slider.thumbWidth", new Integer(10), + "Slider.tickHeight", new Integer(12), + "Spinner.background", new ColorUIResource(light), + "Spinner.foreground", new ColorUIResource(light), + "SplitPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "F6", "toggleFocus", + "F8", "startResize", + "END", "selectMax", + "HOME", "selectMin", + "LEFT", "negativeIncremnent", + "KP_UP", "negativeIncrement", + "KP_DOWN", "positiveIncrement", + "UP", "negativeIncrement", + "RIGHT", "positiveIncrement", + "KP_LEFT", "negativeIncrement", + "DOWN", "positiveIncrement", + "KP_RIGHT", "positiveIncrement" + }), + "SplitPane.background", new ColorUIResource(light), + "SplitPane.border", new BasicBorders.SplitPaneBorder(null, null), + "SplitPane.darkShadow", new ColorUIResource(shadow), + "SplitPane.dividerSize", new Integer(10), + "SplitPane.highlight", new ColorUIResource(highLight), + "SplitPane.shadow", new ColorUIResource(shadow), + "TabbedPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ctrl PAGE_DOWN","navigatePageDown", + "ctrl PAGE_UP", "navigatePageUp", + "ctrl UP", "requestFocus", + "ctrl KP_UP", "requestFocus" + }), + "TabbedPane.background", new ColorUIResource(light), + "TabbedPane.contentBorderInsets", new InsetsUIResource(2, 2, 3, 3), + "TabbedPane.darkShadow", new ColorUIResource(shadow), + "TabbedPane.focus", new ColorUIResource(darkShadow), + "TabbedPane.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "LEFT", "navigateLeft", + "KP_UP", "navigateUp", + "ctrl DOWN", "requestFocusForVisibleComponent", + "UP", "navigateUp", + "KP_DOWN", "navigateDown", + "RIGHT", "navigateRight", + "KP_LEFT", "navigateLeft", + "ctrl KP_DOWN", "requestFocusForVisibleComponent", + "KP_RIGHT", "navigateRight", + "DOWN", "navigateDown" + }), + "TabbedPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TabbedPane.foreground", new ColorUIResource(darkShadow), + "TabbedPane.highlight", new ColorUIResource(highLight), + "TabbedPane.light", new ColorUIResource(highLight), + "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1), + "TabbedPane.shadow", new ColorUIResource(shadow), + "TabbedPane.tabbedPaneTabAreaInsets", new InsetsUIResource(3, 2, 1, 2), + "TabbedPane.tabbedPaneTabInsets", new InsetsUIResource(1, 4, 1, 4), + "TabbedPane.tabbedPaneContentBorderInsets", new InsetsUIResource(3, 2, 1, 2), + "TabbedPane.tabbedPaneTabPadInsets", new InsetsUIResource(1, 1, 1, 1), + "TabbedPane.tabRunOverlay", new Integer(2), + "TabbedPane.textIconGap", new Integer(4), + "Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "shift PAGE_DOWN","scrollDownExtendSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "END", "selectLastColumn", + "shift END", "selectLastColumnExtendSelection", + "HOME", "selectFirstColumn", + "ctrl END", "selectLastRow", + "ctrl shift END","selectLastRowExtendSelection", + "LEFT", "selectPreviousColumn", + "shift HOME", "selectFirstColumnExtendSelection", + "UP", "selectPreviousRow", + "RIGHT", "selectNextColumn", + "ctrl HOME", "selectFirstRow", + "shift LEFT", "selectPreviousColumnExtendSelection", + "DOWN", "selectNextRow", + "ctrl shift HOME","selectFirstRowExtendSelection", + "shift UP", "selectPreviousRowExtendSelection", + "F2", "startEditing", + "shift RIGHT", "selectNextColumnExtendSelection", + "TAB", "selectNextColumnCell", + "shift DOWN", "selectNextRowExtendSelection", + "ENTER", "selectNextRowCell", + "KP_UP", "selectPreviousRow", + "KP_DOWN", "selectNextRow", + "KP_LEFT", "selectPreviousColumn", + "KP_RIGHT", "selectNextColumn", + "shift TAB", "selectPreviousColumnCell", + "ctrl A", "selectAll", + "shift ENTER", "selectPreviousRowCell", + "shift KP_DOWN", "selectNextRowExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ESCAPE", "cancel", + "ctrl shift PAGE_UP", "scrollRightExtendSelection", + "shift KP_RIGHT", " selectNextColumnExtendSelection", + "ctrl PAGE_UP", "scrollLeftChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_DOWN", "scrollLeftExtendSelection", + "ctrl PAGE_DOWN", "scrollRightChangeSelection", + "PAGE_UP", "scrollUpChangeSelection" + }), + "Table.background", new ColorUIResource(light), + "Table.focusCellBackground", new ColorUIResource(light), + "Table.focusCellForeground", new ColorUIResource(darkShadow), + "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.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0), + "Table.selectionBackground", new ColorUIResource(Color.black), + "Table.selectionForeground", new ColorUIResource(Color.white), + "TableHeader.background", new ColorUIResource(light), + "TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0), + "TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TableHeader.foreground", new ColorUIResource(darkShadow), + + "TextArea.background", new ColorUIResource(light), + "TextArea.border", new BasicBorders.MarginBorder(), + "TextArea.caretBlinkRate", new Integer(500), + "TextArea.caretForeground", new ColorUIResource(Color.black), + "TextArea.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), + "TextArea.foreground", new ColorUIResource(Color.black), + "TextArea.inactiveForeground", new ColorUIResource(Color.gray), + "TextArea.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "TextArea.margin", new InsetsUIResource(0, 0, 0, 0), + "TextArea.selectionBackground", new ColorUIResource(Color.black), + "TextArea.selectionForeground", new ColorUIResource(Color.white), + "TextField.background", new ColorUIResource(light), + "TextField.border", new BasicBorders.FieldBorder(null, null, null, null), + "TextField.caretBlinkRate", new Integer(500), + "TextField.caretForeground", new ColorUIResource(Color.black), + "TextField.darkShadow", new ColorUIResource(shadow), + "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.light", new ColorUIResource(highLight), + "TextField.highlight", new ColorUIResource(light), + "TextField.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), + "notify-field-accept"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, + InputEvent.SHIFT_DOWN_MASK), + "selection-backward"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, + InputEvent.SHIFT_DOWN_MASK), + "selection-forward"), + }, + "TextField.margin", new InsetsUIResource(0, 0, 0, 0), + "TextField.selectionBackground", new ColorUIResource(Color.black), + "TextField.selectionForeground", new ColorUIResource(Color.white), + "TextPane.background", new ColorUIResource(Color.white), + "TextPane.border", new BasicBorders.MarginBorder(), + "TextPane.caretBlinkRate", new Integer(500), + "TextPane.caretForeground", new ColorUIResource(Color.black), + "TextPane.font", new FontUIResource("Serif", Font.PLAIN, 12), + "TextPane.foreground", new ColorUIResource(Color.black), + "TextPane.inactiveForeground", new ColorUIResource(Color.gray), + "TextPane.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "TextPane.margin", new InsetsUIResource(3, 3, 3, 3), + "TextPane.selectionBackground", new ColorUIResource(Color.black), + "TextPane.selectionForeground", new ColorUIResource(Color.white), + "TitledBorder.border", new BorderUIResource.EtchedBorderUIResource(), + "TitledBorder.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TitledBorder.titleColor", new ColorUIResource(darkShadow), + "ToggleButton.background", new ColorUIResource(light), + "ToggleButton.border", + new BorderUIResource.CompoundBorderUIResource(null, null), + "ToggleButton.darkShadow", new ColorUIResource(shadow), + "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "ToggleButton.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ToggleButton.foreground", new ColorUIResource(darkShadow), + "ToggleButton.highlight", new ColorUIResource(highLight), + "ToggleButton.light", new ColorUIResource(light), + "ToggleButton.margin", new InsetsUIResource(2, 14, 2, 14), + "ToggleButton.shadow", new ColorUIResource(shadow), + "ToggleButton.textIconGap", new Integer(4), + "ToggleButton.textShiftOffset", new Integer(0), + "ToolBar.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight" + }), + "ToolBar.background", new ColorUIResource(light), + "ToolBar.border", new BorderUIResource.EtchedBorderUIResource(), + "ToolBar.darkShadow", new ColorUIResource(shadow), + "ToolBar.dockingBackground", new ColorUIResource(light), + "ToolBar.dockingForeground", new ColorUIResource(Color.red), + "ToolBar.floatingBackground", new ColorUIResource(light), + "ToolBar.floatingForeground", new ColorUIResource(Color.darkGray), + "ToolBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ToolBar.foreground", new ColorUIResource(darkShadow), + "ToolBar.highlight", new ColorUIResource(highLight), + "ToolBar.light", new ColorUIResource(highLight), + "ToolBar.separatorSize", new DimensionUIResource(20, 20), + "ToolBar.shadow", new ColorUIResource(shadow), + "ToolTip.background", new ColorUIResource(light), + "ToolTip.border", new BorderUIResource.LineBorderUIResource(Color.lightGray), + "ToolTip.font", new FontUIResource("SansSerif", Font.PLAIN, 12), + "ToolTip.foreground", new ColorUIResource(darkShadow), + "Tree.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "cancel" + }), + "Tree.background", new ColorUIResource(light), + "Tree.changeSelectionWithFocus", Boolean.TRUE, +// "Tree.closedIcon", new IconUIResource(new ImageIcon("icons/TreeClosed.png")), +// "Tree.collapsedIcon", new IconUIResource(new ImageIcon("icons/TreeCollapsed.png")), + "Tree.drawsFocusBorderAroundIcon", Boolean.FALSE, + "Tree.editorBorder", new BorderUIResource.LineBorderUIResource(Color.lightGray), + "Tree.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "shift PAGE_DOWN", "scrollDownExtendSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "END", "selectLast", + "ctrl KP_UP", "selectPreviousChangeLead", + "shift END", "selectLastExtendSelection", + "HOME", "selectFirst", + "ctrl END", "selectLastChangeLead", + "ctrl /", "selectAll", + "LEFT", "selectParent", + "shift HOME", "selectFirstExtendSelection", + "UP", "selectPrevious", + "ctrl KP_DOWN", "selectNextChangeLead", + "RIGHT", "selectChild", + "ctrl HOME", "selectFirstChangeLead", + "DOWN", "selectNext", + "ctrl KP_LEFT", "scrollLeft", + "shift UP", "selectPreviousExtendSelection", + "F2", "startEditing", + "ctrl LEFT", "scrollLeft", + "ctrl KP_RIGHT","scrollRight", + "ctrl UP", "selectPreviousChangeLead", + "shift DOWN", "selectNextExtendSelection", + "ENTER", "toggle", + "KP_UP", "selectPrevious", + "KP_DOWN", "selectNext", + "ctrl RIGHT", "scrollRight", + "KP_LEFT", "selectParent", + "KP_RIGHT", "selectChild", + "ctrl DOWN", "selectNextChangeLead", + "ctrl A", "selectAll", + "shift KP_UP", "selectPreviousExtendSelection", + "shift KP_DOWN","selectNextExtendSelection", + "ctrl SPACE", "toggleSelectionPreserveAnchor", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl \\", "clearSelection", + "shift SPACE", "extendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "shift PAGE_UP","scrollUpExtendSelection", + "SPACE", "toggleSelectionPreserveAnchor", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "PAGE_UP", "scrollUpChangeSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead" + }), + "Tree.font", new FontUIResource(new Font("Helvetica", 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.scrollsOnExpand", Boolean.TRUE, + "Tree.selectionBackground", new ColorUIResource(Color.black), + "Tree.nonSelectionBackground", new ColorUIResource(new Color(239, 235, 231)), + "Tree.selectionBorderColor", new ColorUIResource(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), + "Viewport.background", new ColorUIResource(light), + "Viewport.foreground", new ColorUIResource(Color.black), + "Viewport.font", new FontUIResource("Dialog", Font.PLAIN, 12) + }; + defaults.putDefaults(uiDefaults); + } +} // class BasicLookAndFeel diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java new file mode 100644 index 0000000..95f6b84 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -0,0 +1,304 @@ +/* BasicMenuBarUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JMenuBar; +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.MenuBarUI; + +/** + * UI Delegate for JMenuBar. + */ +public class BasicMenuBarUI extends MenuBarUI +{ + protected ChangeListener changeListener; + + /*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; + + /** + * Creates a new BasicMenuBarUI object. + */ + public BasicMenuBarUI() + { + changeListener = createChangeListener(); + containerListener = createContainerListener(); + propertyChangeListener = new PropertyChangeHandler(); + } + + /** + * Creates ChangeListener + * + * @return The ChangeListener + */ + protected ChangeListener createChangeListener() + { + return new ChangeHandler(); + } + + /** + * Creates ContainerListener() to listen for ContainerEvents + * fired by JMenuBar. + * + * @return The ContainerListener + */ + protected ContainerListener createContainerListener() + { + return new ContainerHandler(); + } + + /** + * Factory method to create a BasicMenuBarUI for the given {@link + * JComponent}, which should be a {@link JMenuBar}. + * + * @param x The {@link JComponent} a UI is being created for. + * + * @return A BasicMenuBarUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicMenuBarUI(); + } + + /** + * Returns maximum size for the specified menu bar + * + * @param c component for which to get maximum size + * + * @return Maximum size for the specified menu bar + */ + public Dimension getMaximumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Returns maximum allowed size of JMenuBar. + * + * @param c menuBar for which to return maximum size + * + * @return Maximum size of the give menu bar. + */ + public Dimension getMinimumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Returns preferred size of JMenuBar. + * + * @param c menuBar for which to return preferred size + * + * @return Preferred size of the give menu bar. + */ + public Dimension getPreferredSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + */ + 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")); + menuBar.setOpaque(true); + } + + /** + * This method installs the keyboard actions for the JMenuBar. + */ + protected void installKeyboardActions() + { + // FIXME: implement + } + + /** + * This method installs the listeners needed for this UI to function. + */ + protected void installListeners() + { + menuBar.addContainerListener(containerListener); + menuBar.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. + */ + public void installUI(JComponent c) + { + super.installUI(c); + menuBar = (JMenuBar) c; + menuBar.setLayout(new BoxLayout(menuBar, BoxLayout.X_AXIS)); + installDefaults(); + installListeners(); + installKeyboardActions(); + } + + /** + * This method uninstalls the defaults and nulls any objects created during + * install. + */ + protected void uninstallDefaults() + { + menuBar.setBackground(null); + menuBar.setBorder(null); + menuBar.setFont(null); + menuBar.setForeground(null); + } + + /** + * This method reverses the work done in installKeyboardActions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + menuBar.removeContainerListener(containerListener); + menuBar.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. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(); + uninstallListeners(); + uninstallKeyboardActions(); + menuBar = null; + } + + protected class ChangeHandler implements ChangeListener + { + public void stateChanged(ChangeEvent event) + { + } + } + + /** + * This class handles ContainerEvents fired by JMenuBar. It revalidates + * and repaints menu bar whenever menu is added or removed from it. + */ + protected class ContainerHandler implements ContainerListener + { + /** + * This method is called whenever menu is added to the menu bar + * + * @param e The ContainerEvent. + */ + public void componentAdded(ContainerEvent e) + { + menuBar.revalidate(); + menuBar.repaint(); + } + + /** + * This method is called whenever menu is removed from the menu bar. + * + * @param e The ContainerEvent. + */ + public void componentRemoved(ContainerEvent e) + { + menuBar.revalidate(); + menuBar.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired from the JMenuBar + */ + protected class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the properties of the MenuBar + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("borderPainted")) + menuBar.repaint(); + if (e.getPropertyName().equals("margin")) + menuBar.repaint(); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java new file mode 100644 index 0000000..a5bf082 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -0,0 +1,1006 @@ +/* BasicMenuItemUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +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.Icon; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; + +/** + * UI Delegate for JMenuItem. + */ +public class BasicMenuItemUI extends MenuItemUI +{ + /** + * Font to be used when displaying menu item's accelerator. + */ + protected Font acceleratorFont; + + /** + * Color to be used when displaying menu item's accelerator. + */ + protected Color acceleratorForeground; + + /** + * Color to be used when displaying menu item's accelerator when menu item is + * selected. + */ + protected Color acceleratorSelectionForeground; + + /** + * Icon that is displayed after the text to indicated that this menu contains + * submenu. + */ + protected Icon arrowIcon; + + /** + * Icon that is displayed before the text. This icon is only used in + * JCheckBoxMenuItem or JRadioBoxMenuItem. + */ + protected Icon checkIcon; + + /** + * Number of spaces between icon and text. + */ + protected int defaultTextIconGap = 4; + + /** + * Color of the text when menu item is disabled + */ + protected Color disabledForeground; + + /** + * The menu Drag mouse listener listening to the menu item. + */ + protected MenuDragMouseListener menuDragMouseListener; + + /** + * The menu item itself + */ + protected JMenuItem menuItem; + + /** + * Menu Key listener listening to the menu item. + */ + protected MenuKeyListener menuKeyListener; + + /** + * mouse input listener listening to menu item. + */ + protected MouseInputListener mouseInputListener; + + /** + * Indicates if border should be painted + */ + protected boolean oldBorderPainted; + + /** + * Color of text that is used when menu item is selected + */ + protected Color selectionBackground; + + /** + * Color of the text that is used when menu item is selected. + */ + protected Color selectionForeground; + + /** + * String that separates description of the modifiers and the key + */ + private String acceleratorDelimiter; + + /** + * PropertyChangeListener to listen for property changes in the menu item + */ + private PropertyChangeListener propertyChangeListener; + + /** + * Number of spaces between accelerator and menu item's label. + */ + private int defaultAcceleratorLabelGap = 4; + + /** + * Creates a new BasicMenuItemUI object. + */ + public BasicMenuItemUI() + { + mouseInputListener = createMouseInputListener(menuItem); + menuDragMouseListener = createMenuDragMouseListener(menuItem); + menuKeyListener = createMenuKeyListener(menuItem); + propertyChangeListener = new PropertyChangeHandler(); + } + + /** + * Create MenuDragMouseListener to listen for mouse dragged events. + * + * @param c menu item to listen to + * + * @return The MenuDragMouseListener + */ + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) + { + return new MenuDragMouseHandler(); + } + + /** + * 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) + { + return new MenuKeyHandler(); + } + + /** + * Handles mouse input events occuring for this menu item + * + * @param c menu item to listen to + * + * @return The MouseInputListener + */ + protected MouseInputListener createMouseInputListener(JComponent c) + { + return new MouseInputHandler(); + } + + /** + * 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. + * + * @return A BasicMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicMenuItemUI(); + } + + /** + * Programatically clicks menu item. + * + * @param msm MenuSelectionManager for the menu hierarchy + */ + protected void doClick(MenuSelectionManager msm) + { + menuItem.doClick(); + msm.clearSelectedPath(); + } + + /** + * Returns maximum size for the specified menu item + * + * @param c component for which to get maximum size + * + * @return Maximum size for the specified menu item. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * Returns minimum size for the specified menu item + * + * @param c component for which to get minimum size + * + * @return Minimum size for the specified menu item. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * Returns path to this menu item. + * + * @return $MenuElement[]$ Returns array of menu elements + * that constitute a path to this menu item. + */ + public MenuElement[] getPath() + { + ArrayList path = new ArrayList(); + + // Path to menu should also include its popup menu. + if (menuItem instanceof JMenu) + path.add(((JMenu) menuItem).getPopupMenu()); + + Component c = menuItem; + while (c instanceof MenuElement) + { + path.add(0, (MenuElement) c); + + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); + } + + MenuElement[] pathArray = new MenuElement[path.size()]; + path.toArray(pathArray); + return pathArray; + } + + /** + * Returns preferred size for the given menu item. + * + * @param c menu item for which to get preferred size + * @param checkIcon chech 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, + Icon arrowIcon, + int defaultTextIconGap) + { + 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(); + Rectangle rect; + + if (accelerator != null) + { + rect = getAcceleratorRect(accelerator, + m.getToolkit().getFontMetrics(acceleratorFont)); + + // add width of accelerator's text + d.width = d.width + rect.width + defaultAcceleratorLabelGap; + + // adjust the heigth of the preferred size if necessary + if (d.height < rect.height) + d.height = rect.height; + } + + if (checkIcon != null) + { + d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; + + if (checkIcon.getIconHeight() > d.height) + d.height = checkIcon.getIconHeight(); + } + + if (arrowIcon != null && (c instanceof JMenu)) + { + d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap; + + 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 + * + * @return $Dimension$ preferred size for the given component + */ + public Dimension getPreferredSize(JComponent c) + { + return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap); + } + + protected String getPropertyPrefix() + { + return null; + } + + /** + * This method installs the components for this {@link JMenuItem}. + * + * @param menuItem The {@link JMenuItem} to install components for. + */ + protected void installComponents(JMenuItem menuItem) + { + // FIXME: Need to implement + } + + /** + * 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"); + + menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); + menuItem.setHorizontalAlignment(SwingConstants.LEADING); + } + + /** + * This method installs the keyboard actions for this {@link JMenuItem}. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method installs the listeners for the {@link JMenuItem}. + */ + protected void installListeners() + { + menuItem.addMouseListener(mouseInputListener); + menuItem.addMouseMotionListener(mouseInputListener); + menuItem.addMenuDragMouseListener(menuDragMouseListener); + menuItem.addMenuKeyListener(menuKeyListener); + 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. + */ + public void installUI(JComponent c) + { + super.installUI(c); + menuItem = (JMenuItem) c; + installDefaults(); + installComponents(menuItem); + installListeners(); + } + + /** + * 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 + */ + public void paint(Graphics g, JComponent c) + { + paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(), + c.getForeground(), defaultTextIconGap); + } + + /** + * 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 + */ + protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) + { + Dimension size = getPreferredSize(menuItem); + Color foreground = g.getColor(); + g.setColor(bgColor); + g.drawRect(0, 0, size.width, size.height); + g.setColor(foreground); + } + + /** + * 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 + */ + protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, + Icon arrowIcon, Color background, + Color foreground, int defaultTextIconGap) + { + JMenuItem m = (JMenuItem) c; + Rectangle tr = new Rectangle(); // text rectangle + Rectangle ir = new Rectangle(); // icon rectangle + Rectangle vr = new Rectangle(); // view rectangle + Rectangle br = new Rectangle(); // border rectangle + Rectangle ar = new Rectangle(); // accelerator rectangle + Rectangle cr = new Rectangle(); // checkIcon rectangle + + int vertAlign = m.getVerticalAlignment(); + int horAlign = m.getHorizontalAlignment(); + int vertTextPos = m.getVerticalTextPosition(); + int horTextPos = m.getHorizontalTextPosition(); + + Font f = m.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + SwingUtilities.calculateInnerArea(m, br); + 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. */ + Insets insets = m.getInsets(); + br.x -= insets.left; + br.y -= insets.top; + br.width += insets.right + insets.left; + br.height += insets.top + insets.bottom; + + // Menu item is considered to be highlighted when it is selected. + if (m.isSelected() || m.getModel().isArmed() && + (m.getParent() instanceof MenuElement)) + { + 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 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); + 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; + } + + // 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); + } + } + + // 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); + if (i != null) + i.paintIcon(c, g, ir.x, ir.y); + + paintText(g, m, tr, m.getText()); + + // 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); + } + } + + /** + * 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 + */ + protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, + String text) + { + Font f = menuItem.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + + if (text != null && ! text.equals("")) + { + if (menuItem.isEnabled()) + { + // Menu item is considered to be highlighted when it is selected. + if (menuItem.isSelected() || menuItem.getModel().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. + + // FIXME: should there be different foreground colours for selected + // or deselected, when disabled? + g.setColor(Color.gray); + + 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()); + } + } + + /** + * This method uninstalls the components for this {@link JMenuItem}. + * + * @param menuItem The {@link JMenuItem} to uninstall components for. + */ + protected void uninstallComponents(JMenuItem menuItem) + { + // FIXME: need to implement + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + menuItem.setForeground(null); + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setMargin(null); + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setFont(null); + menuItem.setForeground(null); + menuItem.setMargin(null); + acceleratorFont = null; + acceleratorForeground = null; + acceleratorSelectionForeground = null; + arrowIcon = null; + selectionBackground = null; + selectionForeground = null; + acceleratorDelimiter = null; + } + + /** + * Uninstalls any keyboard actions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: need to implement + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + menuItem.removeMouseListener(mouseInputListener); + menuItem.removeMenuDragMouseListener(menuDragMouseListener); + menuItem.removeMenuKeyListener(menuKeyListener); + 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. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + uninstallComponents(menuItem); + menuItem = null; + } + + /** + * This method calls 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) + { + paint(g, c); + } + + /** + * Return text representation of the specified accelerator + * + * @param accelerator Accelerator for which to return string representation + * + * @return $String$ Text representation of the given accelerator + */ + private String getAcceleratorText(KeyStroke accelerator) + { + // convert keystroke into string format + String modifiersText = ""; + int modifiers = accelerator.getModifiers(); + char keyChar = accelerator.getKeyChar(); + int keyCode = accelerator.getKeyCode(); + + if (modifiers != 0) + modifiersText = KeyEvent.getKeyModifiersText(modifiers) + + acceleratorDelimiter; + + if (keyCode == KeyEvent.VK_UNDEFINED) + return modifiersText + keyChar; + else + return modifiersText + KeyEvent.getKeyText(keyCode); + } + + /** + * 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 + * + * @return $Rectangle$ reactangle which will be used to display accelerator + */ + private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm) + { + int width = fm.stringWidth(getAcceleratorText(accelerator)); + int height = fm.getHeight(); + return new Rectangle(0, 0, width, height); + } + + /** + * 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 + */ + private void paintAccelerator(Graphics g, JMenuItem menuItem, + Rectangle acceleratorRect, + String acceleratorText) + { + g.setFont(acceleratorFont); + FontMetrics fm = g.getFontMetrics(acceleratorFont); + + if (menuItem.isEnabled()) + g.setColor(acceleratorForeground); + else + // FIXME: should fix this to use 'disabledForeground', but its + // default value in BasicLookAndFeel is null. + g.setColor(Color.gray); + + BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x, + acceleratorRect.y + fm.getAscent()); + } + + /** + * 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 + { + /** + * Creates a new MouseInputHandler object. + */ + protected MouseInputHandler() + { + } + + /** + * 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) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * 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) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * 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); + } + } + + /** + * 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) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * 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) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse is pressed. This event is forwarded to + * MenuSelectionManager for further processing. + * + * @param e A {@link MouseEvent}. + */ + public void mousePressed(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * 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}. + */ + public void mouseReleased(MouseEvent e) + { + Rectangle size = menuItem.getBounds(); + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0 + && e.getY() < size.height) + { + manager.clearSelectedPath(); + menuItem.doClick(); + } + + else + manager.processMouseEvent(e); + } + } + + /** + * This class handles mouse dragged events. + */ + protected class MenuDragMouseHandler implements MenuDragMouseListener + { + /** + * Tbis method is invoked when mouse is dragged over the menu item. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseDragged(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * Tbis method is invoked when mouse enters the menu item while it is + * being dragged. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseEntered(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * Tbis method is invoked when mouse exits the menu item while + * it is being dragged + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseExited(MenuDragMouseEvent e) + { + } + + /** + * 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(); + + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + } + + /** + * This class handles key events occuring when menu item is visible on the + * screen. + */ + protected class MenuKeyHandler implements MenuKeyListener + { + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyPressed(MenuKeyEvent e) + { + } + + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyReleased(MenuKeyEvent e) + { + } + + /** + * 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) + { + } + } + + /** + * Helper class that listens for changes to the properties of the {@link + * JMenuItem}. + */ + protected class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when one of the menu item's properties change. + * + * @param evt A {@link PropertyChangeEvent}. + */ + public void propertyChange(PropertyChangeEvent evt) + { + menuItem.revalidate(); + menuItem.repaint(); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java new file mode 100644 index 0000000..6bd15ed --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java @@ -0,0 +1,541 @@ +/* BasicMenuUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JPopupMenu; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MenuListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegate for JMenu + */ +public class BasicMenuUI extends BasicMenuItemUI +{ + protected ChangeListener changeListener; + + /* MenuListener listens to MenuEvents fired by JMenu */ + protected MenuListener menuListener; + + /* PropertyChangeListner that listens to propertyChangeEvents occuring in JMenu*/ + protected PropertyChangeListener propertyChangeListener; + + /** + * Creates a new BasicMenuUI object. + */ + public BasicMenuUI() + { + mouseInputListener = createMouseInputListener((JMenu) menuItem); + menuListener = createMenuListener((JMenu) menuItem); + propertyChangeListener = createPropertyChangeListener((JMenu) menuItem); + } + + /** + * This method creates a new ChangeListener. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener(JComponent c) + { + return new ChangeHandler(); + } + + /** + * This method creates new MenuDragMouseListener to listen to mouse dragged events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MenuDrageMouseListener + */ + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) + { + return new MenuDragMouseHandler(); + } + + /** + * This method creates new MenuDragKeyListener to listen to key events + * + * @param c the menu to listen to + * + * @return The MenuKeyListener + */ + protected MenuKeyListener createMenuKeyListener(JComponent c) + { + return new MenuKeyHandler(); + } + + /** + * This method creates new MenuListener to listen to menu events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MenuListener + */ + protected MenuListener createMenuListener(JComponent c) + { + return new MenuHandler(); + } + + /** + * This method creates new MouseInputListener to listen to mouse input events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MouseInputListener + */ + protected MouseInputListener createMouseInputListener(JComponent c) + { + return new MouseInputHandler(); + } + + /** + * This method creates newPropertyChangeListener to listen to property changes + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The PropertyChangeListener + */ + protected PropertyChangeListener createPropertyChangeListener(JComponent c) + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new BasicMenuUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicMenuUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicMenuUI(); + } + + /** + * Get the component's maximum size. + * + * @param c The JComponent for which to get maximum size + * + * @return The maximum size of the component + */ + public Dimension getMaximumSize(JComponent c) + { + return c.getPreferredSize(); + } + + protected String getPropertyPrefix() + { + return null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + */ + 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"); + menuItem.setOpaque(true); + } + + /** + * Installs any keyboard actions. The list of keys that need to be bound are + * listed in Basic look and feel's defaults. + * + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * Creates and registers all the listeners for this UI delegate. + */ + protected void installListeners() + { + ((JMenu) menuItem).addMouseListener(mouseInputListener); + ((JMenu) menuItem).addMouseMotionListener(mouseInputListener); + ((JMenu) menuItem).addMenuListener(menuListener); + ((JMenu) menuItem).addMenuDragMouseListener(menuDragMouseListener); + } + + protected void setupPostTimer(JMenu menu) + { + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setFont(null); + menuItem.setForeground(null); + menuItem.setMargin(null); + acceleratorFont = null; + acceleratorForeground = null; + acceleratorSelectionForeground = null; + selectionBackground = null; + selectionForeground = null; + arrowIcon = null; + } + + /** + * Uninstalls any keyboard actions. The list of keys used are listed in + * Basic look and feel's defaults. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * Unregisters all the listeners that this UI delegate was using. In + * addition, it will also null any listeners that it was using. + */ + protected void uninstallListeners() + { + ((JMenu) menuItem).removeMouseListener(mouseInputListener); + ((JMenu) menuItem).removeMenuListener(menuListener); + ((JMenu) menuItem).removePropertyChangeListener(propertyChangeListener); + } + + /** + * This class is used by menus to handle mouse events occuring in the + * menu. + */ + protected class MouseInputHandler implements MouseInputListener + { + public void mouseClicked(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + public void mouseDragged(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + private boolean popupVisible() + { + JMenuBar mb = (JMenuBar) ((JMenu)menuItem).getParent(); + // check if mb.isSelected because if no menus are selected + // we don't have to look through the list for popup menus + if (!mb.isSelected()) + return false; + for (int i=0;i maxll) + { + Box tmp = new Box(BoxLayout.Y_AXIS); + burstStringInto(tmp, msg.toString(), maxll); + addMessageComponents(container, cons, tmp, maxll, true); + } + else + addMessageComponents(container, cons, new JLabel(msg.toString()), + maxll, true); + } + } + + /** + * This method creates instances of d (recursively if necessary based on + * maxll) and adds to c. + * + * @param c The container to add to. + * @param d The string to burst. + * @param maxll The max line length. + */ + protected void burstStringInto(Container c, String d, int maxll) + { + // FIXME: Verify that this is the correct behaviour. + // One interpretation of the spec is that this method + // should recursively call itself to create (and add) + // JLabels to the container if the length of the String d + // is greater than maxll. + // but in practice, even with a really long string, this is + // all that happens. + if (d == null || c == null) + return; + JLabel label = new JLabel(d); + c.add(label); + } + + /** + * This method returns true if the given JOptionPane contains custom + * components. + * + * @param op The JOptionPane to check. + * + * @return True if the JOptionPane contains custom components. + */ + public boolean containsCustomComponents(JOptionPane op) + { + return hasCustomComponents; + } + + /** + * This method creates a button action listener for the given button index. + * + * @param buttonIndex The index of the button in components. + * + * @return A new ButtonActionListener. + */ + protected ActionListener createButtonActionListener(int buttonIndex) + { + return new ButtonActionListener(buttonIndex); + } + + /** + * This method creates the button area. + * + * @return A new Button Area. + */ + protected Container createButtonArea() + { + JPanel buttonPanel = new JPanel(); + + buttonPanel.setLayout(createLayoutManager()); + addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex()); + + return buttonPanel; + } + + /** + * This method creates a new LayoutManager for the button area. + * + * @return A new LayoutManager for the button area. + */ + protected LayoutManager createLayoutManager() + { + return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6); + } + + /** + * This method creates the message area. + * + * @return A new message area. + */ + protected Container createMessageArea() + { + JPanel messageArea = new JPanel(); + messageArea.setLayout(new BorderLayout()); + addIcon(messageArea); + + JPanel rightSide = new JPanel(); + rightSide.setBorder(BorderFactory.createEmptyBorder(0, 11, 17, 0)); + rightSide.setLayout(new GridBagLayout()); + GridBagConstraints con = createConstraints(); + + addMessageComponents(rightSide, con, getMessage(), + getMaxCharactersPerLineCount(), false); + + if (optionPane.getWantsInput()) + { + Object[] selection = optionPane.getSelectionValues(); + + if (selection == null) + inputComponent = new JTextField(15); + else if (selection.length < 20) + inputComponent = new JComboBox(selection); + else + inputComponent = new JList(selection); + if (inputComponent != null) + { + addMessageComponents(rightSide, con, inputComponent, + getMaxCharactersPerLineCount(), false); + resetSelectedValue(); + selectInitialValue(optionPane); + } + } + + messageArea.add(rightSide, BorderLayout.EAST); + + return messageArea; + } + + /** + * This method creates a new PropertyChangeListener for listening to the + * JOptionPane. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a Container that will separate the message and button + * areas. + * + * @return A Container that will separate the message and button areas. + */ + protected Container createSeparator() + { + return (Container) Box.createVerticalStrut(17); + } + + /** + * This method creates a new BasicOptionPaneUI for the given component. + * + * @param x The component to create a UI for. + * + * @return A new BasicOptionPaneUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicOptionPaneUI(); + } + + /** + * This method returns the buttons for the JOptionPane. If no options are + * set, a set of options will be created based upon the optionType. + * + * @return The buttons that will be added. + */ + protected Object[] getButtons() + { + if (optionPane.getOptions() != null) + return optionPane.getOptions(); + switch (optionPane.getOptionType()) + { + case JOptionPane.YES_NO_OPTION: + return new Object[] { YES_STRING, NO_STRING }; + case JOptionPane.YES_NO_CANCEL_OPTION: + return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING }; + case JOptionPane.OK_CANCEL_OPTION: + case JOptionPane.DEFAULT_OPTION: + return new Object[] { OK_STRING, CANCEL_STRING }; + } + return null; + } + + /** + * This method will return the icon the user has set or the icon that will + * be used based on message type. + * + * @return The icon to use in the JOptionPane. + */ + protected Icon getIcon() + { + if (optionPane.getIcon() != null) + return optionPane.getIcon(); + else + return getIconForType(optionPane.getMessageType()); + } + + /** + * This method returns the icon for the given messageType. + * + * @param messageType The type of message. + * + * @return The icon for the given messageType. + */ + protected Icon getIconForType(int messageType) + { + Icon tmp = null; + switch (messageType) + { + case JOptionPane.ERROR_MESSAGE: + tmp = errorIcon; + break; + case JOptionPane.INFORMATION_MESSAGE: + tmp = infoIcon; + break; + case JOptionPane.WARNING_MESSAGE: + tmp = warningIcon; + break; + case JOptionPane.QUESTION_MESSAGE: + tmp = questionIcon; + break; + } + return tmp; + // FIXME: Don't cast till the default icons are in. + // return new IconUIResource(tmp); + } + + /** + * This method returns the index of the initialValue in the options array. + * + * @return The index of the initalValue. + */ + protected int getInitialValueIndex() + { + Object[] buttons = getButtons(); + + if (buttons == null) + return -1; + + Object select = optionPane.getInitialValue(); + + for (int i = 0; i < buttons.length; i++) + { + if (select == buttons[i]) + return i; + } + return 0; + } + + /** + * This method returns the maximum number of characters that should be + * placed on a line. + * + * @return The maximum number of characteres that should be placed on a + * line. + */ + protected int getMaxCharactersPerLineCount() + { + return optionPane.getMaxCharactersPerLineCount(); + } + + /** + * This method returns the maximum size. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the message of the JOptionPane. + * + * @return The message. + */ + protected Object getMessage() + { + return optionPane.getMessage(); + } + + /** + * This method returns the minimum size of the JOptionPane. + * + * @return The minimum size. + */ + public Dimension getMinimumOptionPaneSize() + { + return minimumSize; + } + + /** + * This method returns the minimum size. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the JOptionPane. The preferred + * size is the maximum of the size desired by the layout and the minimum + * size. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane); + Dimension d2 = getMinimumOptionPaneSize(); + + int w = Math.max(d.width, d2.width); + int h = Math.max(d.height, d2.height); + return new Dimension(w, h); + } + + /** + * This method returns whether all buttons should have the same width. + * + * @return Whether all buttons should have the same width. + */ + protected boolean getSizeButtonsToSameWidth() + { + return true; + } + + /** + * This method installs components for the JOptionPane. + */ + protected void installComponents() + { + // reset it. + hasCustomComponents = false; + Container msg = createMessageArea(); + if (msg != null) + { + ((JComponent) msg).setBorder(messageBorder); + msg.setForeground(messageForeground); + messageAreaContainer = msg; + optionPane.add(msg); + } + + Container sep = createSeparator(); + if (sep != null) + optionPane.add(sep); + + Container button = createButtonArea(); + if (button != null) + { + ((JComponent) button).setBorder(buttonBorder); + buttonContainer = button; + optionPane.add(button); + } + + optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11)); + optionPane.invalidate(); + } + + /** + * This method installs defaults for the JOptionPane. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + optionPane.setFont(defaults.getFont("OptionPane.font")); + optionPane.setBackground(defaults.getColor("OptionPane.background")); + optionPane.setForeground(defaults.getColor("OptionPane.foreground")); + optionPane.setBorder(defaults.getBorder("OptionPane.border")); + optionPane.setOpaque(true); + + messageBorder = defaults.getBorder("OptionPane.messageAreaBorder"); + messageForeground = defaults.getColor("OptionPane.messageForeground"); + buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder"); + + minimumSize = defaults.getDimension("OptionPane.minimumSize"); + minimumWidth = minimumSize.width; + minimumHeight = minimumSize.height; + + // FIXME: Image icons don't seem to work properly right now. + // Once they do, replace the synthetic icons with these ones. + + /* + warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon"); + infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon"); + errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon"); + questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon"); + */ + } + + /** + * This method installs keyboard actions for the JOptionpane. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs listeners for the JOptionPane. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + + optionPane.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method installs the UI for the JOptionPane. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JOptionPane) + { + optionPane = (JOptionPane) c; + + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * Changes the inputValue property in the JOptionPane based on the current + * value of the inputComponent. + */ + protected void resetInputValue() + { + if (optionPane.getWantsInput() && inputComponent != null) + { + Object output = null; + if (inputComponent instanceof JTextField) + output = ((JTextField) inputComponent).getText(); + else if (inputComponent instanceof JComboBox) + output = ((JComboBox) inputComponent).getSelectedItem(); + else if (inputComponent instanceof JList) + output = ((JList) inputComponent).getSelectedValue(); + + if (output != null) + optionPane.setInputValue(output); + } + } + + /** + * This method requests focus to the inputComponent (if one is present) and + * the initialFocusComponent otherwise. + * + * @param op The JOptionPane. + */ + public void selectInitialValue(JOptionPane op) + { + if (inputComponent != null) + { + inputComponent.requestFocus(); + return; + } + if (initialFocusComponent != null) + initialFocusComponent.requestFocus(); + } + + /** + * This method resets the value in the inputComponent to the + * initialSelectionValue property. + * This is package-private to avoid an accessor method. + */ + void resetSelectedValue() + { + if (inputComponent != null) + { + Object init = optionPane.getInitialSelectionValue(); + if (init == null) + return; + if (inputComponent instanceof JTextField) + ((JTextField) inputComponent).setText((String) init); + else if (inputComponent instanceof JComboBox) + ((JComboBox) inputComponent).setSelectedItem(init); + else if (inputComponent instanceof JList) + { + // ((JList) inputComponent).setSelectedValue(init, true); + } + } + } + + /** + * This method uninstalls all the components in the JOptionPane. + */ + protected void uninstallComponents() + { + optionPane.removeAll(); + buttonContainer = null; + messageAreaContainer = null; + } + + /** + * This method uninstalls the defaults for the JOptionPane. + */ + protected void uninstallDefaults() + { + optionPane.setFont(null); + optionPane.setForeground(null); + optionPane.setBackground(null); + + minimumSize = null; + + messageBorder = null; + buttonBorder = null; + messageForeground = null; + + // FIXME: ImageIcons don't seem to work properly + + /* + warningIcon = null; + errorIcon = null; + questionIcon = null; + infoIcon = null; + */ + } + + /** + * This method uninstalls keyboard actions for the JOptionPane. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls listeners for the JOptionPane. + */ + protected void uninstallListeners() + { + optionPane.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + + optionPane = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java new file mode 100644 index 0000000..0896721 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java @@ -0,0 +1,67 @@ +/* BasicPanelUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PanelUI; + +public class BasicPanelUI extends PanelUI +{ + public static ComponentUI createUI(JComponent x) + { + return new BasicPanelUI(); + } + + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JPanel) + { + JPanel p = (JPanel) c; + installDefaults(p); + } + } + + public void installDefaults(JPanel p) + { + p.setOpaque(true); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java new file mode 100644 index 0000000..044027b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -0,0 +1,67 @@ +/* BasicPasswordFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PasswordView; +import javax.swing.text.View; + +public class BasicPasswordFieldUI extends BasicTextFieldUI +{ + public BasicPasswordFieldUI() + { + } + + public View create(Element elem) + { + return new PasswordView(elem); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicPasswordFieldUI(); + } + + protected String getPropertyPrefix() + { + return "PasswordField"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java new file mode 100644 index 0000000..b629477 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java @@ -0,0 +1,114 @@ +/* BasicPopupMenuSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.plaf.ComponentUI; + +/** + * The Basic Look and Feel UI delegate for JPopupMenu.Separator. + */ +public class BasicPopupMenuSeparatorUI extends BasicSeparatorUI +{ + /** + * Creates a new BasicPopupMenuSeparatorUI object. + */ + public BasicPopupMenuSeparatorUI() + { + super(); + } + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicPopupMenuSeparatorUI + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicPopupMenuSeparatorUI(); + } + + /** + * The Popup Menu Separator has two lines. The top line will be + * painted using highlight color and the bottom using shadow color. + * + * @param g The Graphics object to paint with + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (! (c instanceof JPopupMenu.Separator)) + return; + + Rectangle r = new Rectangle(); + SwingUtilities.calculateInnerArea(c, r); + Color saved = g.getColor(); + + int midAB = r.width / 2 + r.x; + int midAD = r.height / 2 + r.y; + + 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); + } + + /** + * This method returns the preferred size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return super.getPreferredSize(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java new file mode 100644 index 0000000..247117b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -0,0 +1,674 @@ +/* BasicPopupMenuUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +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; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PopupMenuUI; + + +/** + * UI Delegate for JPopupMenu + */ +public class BasicPopupMenuUI extends PopupMenuUI +{ + /* popupMenu for which this UI delegate is for*/ + protected JPopupMenu popupMenu; + + /* MouseInputListener listens to mouse events. Package private for inner classes. */ + static transient MouseInputListener mouseInputListener; + + /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/ + private transient PopupMenuListener popupMenuListener; + + /* ComponentListener listening to popupMenu's invoker. + * This is package-private to avoid an accessor method. */ + TopWindowListener topWindowListener; + + /** + * Creates a new BasicPopupMenuUI object. + */ + public BasicPopupMenuUI() + { + popupMenuListener = new PopupMenuHandler(); + topWindowListener = new TopWindowListener(); + } + + /** + * Factory method to create a BasicPopupMenuUI for the given {@link + * JComponent}, which should be a {@link JMenuItem}. + * + * @param x The {@link JComponent} a UI is being created for. + * + * @return A BasicPopupMenuUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicPopupMenuUI(); + } + + /** + * 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) + { + super.installUI(c); + popupMenu = (JPopupMenu) c; + popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS)); + popupMenu.setBorderPainted(true); + JPopupMenu.setDefaultLightWeightPopupEnabled(true); + + installDefaults(); + installListeners(); + } + + /** + * This method installs the defaults that are defined in the Basic look + * and feel for this {@link JPopupMenu}. + */ + 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")); + popupMenu.setOpaque(true); + } + + /** + * This method installs the listeners for the {@link JMenuItem}. + */ + protected void installListeners() + { + popupMenu.addPopupMenuListener(popupMenuListener); + } + + /** + * This method installs the keyboard actions for this {@link JPopupMenu}. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * 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. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + popupMenu = null; + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + popupMenu.setBackground(null); + popupMenu.setBorder(null); + popupMenu.setFont(null); + popupMenu.setForeground(null); + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + popupMenu.removePopupMenuListener(popupMenuListener); + } + + /** + * Uninstalls any keyboard actions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method returns the minimum size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * This method returns the preferred size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return null; + } + + /** + * This method returns the minimum size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * Return true if given mouse event is a platform popup trigger, and false + * otherwise + * + * @param e MouseEvent that is to be checked for popup trigger event + * + * @return true if given mouse event is a platform popup trigger, and false + * otherwise + */ + public boolean isPopupTrigger(MouseEvent e) + { + return false; + } + + /** + * This listener handles PopupMenuEvents fired by JPopupMenu + */ + private class PopupMenuHandler implements PopupMenuListener + { + /** + * This method is invoked when JPopupMenu is cancelled. + * + * @param event the PopupMenuEvent + */ + public void popupMenuCanceled(PopupMenuEvent event) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when JPopupMenu becomes invisible + * + * @param event the PopupMenuEvent + */ + public void popupMenuWillBecomeInvisible(PopupMenuEvent event) + { + // remove listener that listens to component events fired + // by the top - level window that this popup belongs to. + Component invoker = popupMenu.getInvoker(); + + 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)) + { + // set glass pane not to interrupt mouse events and remove + // mouseInputListener + Container glassPane = (Container) rootContainer.getGlassPane(); + glassPane.setVisible(false); + glassPane.removeMouseListener(mouseInputListener); + mouseInputListener = null; + } + } + + /** + * This method is invoked when JPopupMenu becomes visible + * + * @param event the PopupMenuEvent + */ + public void popupMenuWillBecomeVisible(PopupMenuEvent event) + { + // Adds topWindowListener to top-level window to listener to + // ComponentEvents fired by it. We need to cancel this popup menu + // if topWindow to which this popup belongs was resized or moved. + Component invoker = popupMenu.getInvoker(); + RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities + .getRoot(invoker); + ((Container) rootContainer).addComponentListener(topWindowListener); + + // Set the glass pane to interrupt all mouse events originating in root + // container + if (mouseInputListener == null) + { + Container glassPane = (Container) rootContainer.getGlassPane(); + glassPane.setVisible(true); + mouseInputListener = new MouseInputHandler(rootContainer); + glassPane.addMouseListener(mouseInputListener); + glassPane.addMouseMotionListener(mouseInputListener); + } + + // if this popup menu is a free floating popup menu, + // then by default its first element should be always selected when + // this popup menu becomes visible. + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + + if (manager.getSelectedPath().length == 0) + { + // Set selected path to point to the first item in the popup menu + MenuElement[] path = new MenuElement[2]; + path[0] = popupMenu; + Component[] comps = popupMenu.getComponents(); + if (comps.length != 0 && comps[0] instanceof MenuElement) + { + path[1] = (MenuElement) comps[0]; + manager.setSelectedPath(path); + } + } + } + } + + /** + * ComponentListener that listens to Component Events fired by the top - + * level window to which popup menu belongs. If top-level window was + * resized, moved or hidded then popup menu will be hidded and selected + * path of current menu hierarchy will be set to null. + */ + private class TopWindowListener implements ComponentListener + { + /** + * This method is invoked when top-level window is resized. This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentResized(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is moved. This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentMoved(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is shown This method + * does nothing by default. + * + * @param e The ComponentEvent + */ + public void componentShown(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is hidden This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentHidden(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + } + + /** + * MouseInputHandler listens to all mouse events originated in the root + * container. This class is responsible for closing menu hierarchy when the + * user presses mouse over any component that do not belong to the current + * menu hierarchy. This is acomplished by interrupting all mouse event in + * the glass pane and checking if other component was pressed while menu + * was open, before redestributing events further to intended components + */ + private class MouseInputHandler implements MouseInputListener + { + private JLayeredPane layeredPane; + private Container glassPane; + private Cursor nativeCursor; + private transient Component mouseEventTarget; + private transient Component pressedComponent; + private transient Component lastComponentEntered; + private transient Component tempComponent; + private transient int pressCount; + + /** + * Creates a new MouseInputHandler object. + * + * @param c the top most root container + */ + public MouseInputHandler(RootPaneContainer c) + { + layeredPane = c.getLayeredPane(); + glassPane = (Container) c.getGlassPane(); + } + + /** + * Handles mouse clicked event + * + * @param e Mouse event + */ + public void mouseClicked(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseDragged event + * + * @param e MouseEvent + */ + public void mouseDragged(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseEntered event + * + * @param e MouseEvent + */ + public void mouseEntered(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseExited event + * + * @param e MouseEvent + */ + public void mouseExited(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse moved event + * + * @param e MouseEvent + */ + public void mouseMoved(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse pressed event + * + * @param e MouseEvent + */ + public void mousePressed(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse released event + * + * @param e MouseEvent + */ + public void mouseReleased(MouseEvent e) + { + handleEvent(e); + } + + /* + * This method determines component that was intended to received mouse + * event, before it was interrupted within the glass pane. This method + * also redispatches mouse entered and mouse exited events to the + * appropriate components. This code is slightly modified code from + * Container.LightweightDispatcher class, which is private inside + * Container class and cannot be used here. + */ + public void acquireComponentForMouseEvent(MouseEvent me) + { + int x = me.getX(); + int y = me.getY(); + + // Find the candidate which should receive this event. + Component parent = layeredPane; + Component candidate = null; + Point p = me.getPoint(); + while ((candidate == null) && (parent != null)) + { + p = SwingUtilities.convertPoint(glassPane, p.x, p.y, parent); + 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 + // children here. + if (candidate == layeredPane) + candidate = null; + + // If our candidate is new, inform the old target we're leaving. + if ((lastComponentEntered != null) && lastComponentEntered.isShowing() + && (lastComponentEntered != candidate)) + { + // Old candidate could have been removed from + // the layeredPane so we check first. + if (SwingUtilities.isDescendingFrom(lastComponentEntered, layeredPane)) + { + Point tp = SwingUtilities.convertPoint(layeredPane, x, y, + lastComponentEntered); + MouseEvent exited = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_EXITED, + me.getWhen(), + me.getModifiersEx(), tp.x, + tp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + + tempComponent = lastComponentEntered; + lastComponentEntered = null; + tempComponent.dispatchEvent(exited); + } + + lastComponentEntered = null; + } + + // If we have a candidate, maybe enter it. + if (candidate != null) + { + mouseEventTarget = candidate; + + if (candidate.isLightweight() && candidate.isShowing() + && (candidate != layeredPane) + && (candidate != lastComponentEntered)) + { + lastComponentEntered = mouseEventTarget; + + Point cp = SwingUtilities.convertPoint(layeredPane, x, y, + lastComponentEntered); + MouseEvent entered = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_ENTERED, + me.getWhen(), + me.getModifiersEx(), cp.x, + cp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + lastComponentEntered.dispatchEvent(entered); + } + } + + if ((me.getID() == MouseEvent.MOUSE_RELEASED) + || ((me.getID() == MouseEvent.MOUSE_PRESSED) && (pressCount > 0)) + || (me.getID() == MouseEvent.MOUSE_DRAGGED)) + { + // If any of the following events occur while a button is held down, + // they should be dispatched to the same component to which the + // original MOUSE_PRESSED event was dispatched: + // - MOUSE_RELEASED + // - MOUSE_PRESSED: another button pressed while the first is held down + // - MOUSE_DRAGGED + if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane)) + 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; + } + } + } + + /* + * This method handles mouse events interrupted by glassPane. It + * redispatches the mouse events appropriately to the intended components. + * The code in this method is also taken from + * Container.LightweightDispatcher class. The code is slightly modified + * to handle the case when mouse is released over non-menu component. In + * this case this method closes current menu hierarchy before + * redispatching the event further. + */ + public void handleEvent(AWTEvent e) + { + if (e instanceof MouseEvent) + { + MouseEvent me = (MouseEvent) e; + + acquireComponentForMouseEvent(me); + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget != null && mouseEventTarget.isShowing() + && (e.getID() != MouseEvent.MOUSE_ENTERED) + && (e.getID() != MouseEvent.MOUSE_EXITED)) + { + MouseEvent newEvt = SwingUtilities.convertMouseEvent(glassPane, + me, + mouseEventTarget); + + mouseEventTarget.dispatchEvent(newEvt); + + // If mouse was clicked over the component that is not part + // of menu hierarchy,then must close the menu hierarchy */ + if (e.getID() == MouseEvent.MOUSE_RELEASED) + { + boolean partOfMenuHierarchy = false; + MenuSelectionManager manager = MenuSelectionManager + .defaultManager(); + + partOfMenuHierarchy = manager.isComponentPartOfCurrentMenu(mouseEventTarget); + + if (! partOfMenuHierarchy) + manager.clearSelectedPath(); + } + + 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; + } + } + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java new file mode 100644 index 0000000..d00628f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -0,0 +1,827 @@ +/* BasicProgressBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +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.Point; +import java.awt.Rectangle; +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.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JProgressBar; +import javax.swing.SwingConstants; +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; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ProgressBarUI; + +/** + * The Basic Look and Feel UI delegate for the + * JProgressBar. + */ +public class BasicProgressBarUI extends ProgressBarUI +{ + /** + * A helper class that listens for ChangeEvents + * from the progressBar's model. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ChangeHandler implements ChangeListener + { + /** + * Called every time the state of the model changes. + * + * @param e The ChangeEvent given by the model. + */ + public void stateChanged(ChangeEvent e) + { + // Nothing to do but repaint. + progressBar.repaint(); + } + } + + /** + * This helper class is used to listen for + * PropertyChangeEvents from the progressBar. + */ + private class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called every time the properties of the + * progressBar change. + * + * @param e The PropertyChangeEvent given by the progressBar. + */ + public void propertyChange(PropertyChangeEvent e) + { + // 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(); + } + } + + /** + * This helper class is used to listen for + * the animationTimer's intervals. On every interval, + * the bouncing box should move. + */ + private class Animator implements ActionListener + { + /** + * Called every time the animationTimer reaches + * its interval. + * + * @param e The ActionEvent given by the timer. + */ + public void actionPerformed(ActionEvent e) + { + // Incrementing the animation index will cause + // a repaint. + incrementAnimationIndex(); + } + } + + /** The timer used to move the bouncing box. */ + private transient Timer animationTimer; + + // The total number of frames must be an even number. + // The total number of frames is calculated from + // the cycleTime and repaintInterval given by + // the basic Look and Feel defaults. + // + // +-----------------------------------------------+ + // | frame0 | frame1 | frame2 | frame 3 | frame 4 | + // | | frame7 | frame6 | frame 5 | | + // +-----------------------------------------------+ + + /** The current animation index. */ + private transient int animationIndex; + + /** The total number of frames.*/ + private transient int numFrames; + + /** The helper that moves the bouncing box. */ + private transient Animator animation; + + /** The helper that listens for property change events. */ + private transient PropertyChangeHandler propertyListener; + + /** The Listener for the model. */ + protected ChangeListener changeListener; + + /** The progressBar for this UI. */ + protected JProgressBar progressBar; + + /** The length of the cell. The cell is the painted part. */ + private transient int cellLength; + + /** The gap between cells. */ + private transient int cellSpacing; + + /** The color of the text when the bar is not over it.*/ + private transient Color selectionBackground; + + /** The color of the text when the bar is over it. */ + private transient Color selectionForeground; + + /** + * Creates a new BasicProgressBarUI object. + */ + public BasicProgressBarUI() + { + super(); + } + + /** + * Creates a new BasicProgressBarUI for the component. + * + * @param x The JComponent to create the UI for. + * + * @return A new BasicProgressBarUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicProgressBarUI(); + } + + /** + * This method returns the length of the bar (from the minimum) + * in pixels (or units that the Graphics object draws in) based + * on the progressBar's getPercentComplete() value. + * + * @param b The insets of the progressBar. + * @param width The width of the progressBar. + * @param height The height of the progressBar. + * + * @return The length of the bar that should be painted in pixels. + */ + protected int getAmountFull(Insets b, int width, int height) + { + double percentDone = progressBar.getPercentComplete(); + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + return (int) (percentDone * (width - b.left - b.right)); + else + return (int) (percentDone * (height - b.top - b.bottom)); + } + + /** + * The current animation index. + * + * @return The current animation index. + */ + protected int getAnimationIndex() + { + return animationIndex; + } + + /** + * This method returns the size and position of the bouncing box + * for the current animation index. It stores the values in the + * given rectangle and returns it. It returns null if no box should + * be drawn. + * + * @param r The bouncing box rectangle. + * + * @return The bouncing box rectangle. + */ + protected Rectangle getBox(Rectangle r) + { + if (!progressBar.isIndeterminate()) + return null; + //numFrames has to be an even number as defined by spec. + int iterations = numFrames / 2 + 1; + + double boxDependent; + double boxIndependent; + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + Dimension dims = getPreferredInnerHorizontal(); + boxDependent = (double) dims.width / iterations; + boxIndependent = dims.height; + } + else + { + Dimension dims = getPreferredInnerVertical(); + boxDependent = (double) dims.height / iterations; + boxIndependent = dims.width; + } + + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(progressBar, vr); + + int index = getAnimationIndex(); + if (animationIndex > (numFrames + 1) / 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; + } + else + { + index++; + r.x = vr.x; + r.y = vr.height - (int) (index * boxDependent) + vr.y; + r.width = (int) boxIndependent; + r.height = (int) boxDependent; + } + + return r; + } + + /** + * This method returns the length of the cells. + * + * @return The cell length. + */ + protected int getCellLength() + { + return cellLength; + } + + /** + * This method returns the spacing between cells. + * + * @return The cell gap. + */ + protected int getCellSpacing() + { + return cellSpacing; + } + + /** + * This method returns the maximum size of the JComponent. + * If it returns null, it is up to the LayoutManager + * to give it a size. + * + * @param c The component to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the JComponent. + * If it returns null, it is up to the LayoutManager to + * give it a size. + * + * @param c The component to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the inner + * rectangle (the bounds without the insets) if the + * progressBar is horizontal. + * + * @return The preferred size of the progressBar minus + * insets if it's horizontal. + */ + protected Dimension getPreferredInnerHorizontal() + { + Rectangle vr = new Rectangle(); + + SwingUtilities.calculateInnerArea(progressBar, vr); + + return new Dimension(vr.width, vr.height); + } + + /** + * This method returns the preferred size of the inner + * rectangle (the bounds without insets) if the + * progressBar is vertical. + * + * @return The preferred size of the progressBar minus + * insets if it's vertical. + */ + protected Dimension getPreferredInnerVertical() + { + Rectangle vr = new Rectangle(); + + SwingUtilities.calculateInnerArea(progressBar, vr); + + return new Dimension(vr.width, vr.height); + } + + /** + * This method returns the preferred size of the + * given JComponent. If it returns null, then it + * is up to the LayoutManager to give it a size. + * + * @param c The component to find the preferred size for. + * + * @return The preferred size of the component. + */ + 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; + } + 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); + } + + /** + * This method returns the Color that the text is shown in when the bar is + * not over the text. + * + * @return The color of the text when the bar is not over it. + */ + protected Color getSelectionBackground() + { + return selectionBackground; + } + + /** + * This method returns the Color that the text is shown in when the bar is + * over the text. + * + * @return The color of the text when the bar is over it. + */ + protected Color getSelectionForeground() + { + return selectionForeground; + } + + /** + * This method returns the point (the top left of the bounding box) + * where the text should be painted. + * + * @param g The Graphics object to measure FontMetrics with. + * @param progressString The string to paint. + * @param x The x coordinate of the overall bounds box. + * @param y The y coordinate of the overall bounds box. + * @param width The width of the overall bounds box. + * @param height The height of the overall bounds box. + * + * @return The top left of the bounding box where text should be painted. + */ + protected Point getStringPlacement(Graphics g, String progressString, int x, + int y, int width, int height) + { + Rectangle tr = new Rectangle(); + Rectangle vr = new Rectangle(x, y, width, height); + Rectangle ir = new Rectangle(); + + Font f = g.getFont(); + FontMetrics fm = g.getFontMetrics(f); + + SwingUtilities.layoutCompoundLabel(progressBar, fm, progressString, null, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, vr, ir, tr, 0); + return new Point(tr.x, tr.y); + } + + /** + * This method increments the animation index. + */ + protected void incrementAnimationIndex() + { + animationIndex++; + //numFrames is like string length, it should be named numFrames or something + if (animationIndex >= numFrames) + animationIndex = 0; + progressBar.repaint(); + } + + /** + * This method paints the progressBar. It delegates its responsibilities + * to paintDeterminate and paintIndeterminate. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (! progressBar.isIndeterminate()) + paintDeterminate(g, c); + else + paintIndeterminate(g, c); + } + + /** + * This method is called if the painting to be done is + * for a determinate progressBar. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + protected void paintDeterminate(Graphics g, JComponent c) + { + Color saved = g.getColor(); + int space = getCellSpacing(); + int len = getCellLength(); + int max = progressBar.getMaximum(); + int min = progressBar.getMinimum(); + int value = progressBar.getValue(); + + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(c, vr); + + Rectangle or = c.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; + } + } + } + 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); + } + } + } + } + + if (progressBar.isStringPainted() && !progressBar.getString().equals("")) + paintString(g, 0, 0, or.width, or.height, amountFull, insets); + g.setColor(saved); + } + + /** + * This method is called if the painting to be done is for + * an indeterminate progressBar. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + protected void paintIndeterminate(Graphics g, JComponent c) + { + //need to paint the box at it's current position. no text is painted since + //all we're doing is bouncing back and forth + Color saved = g.getColor(); + Insets insets = c.getInsets(); + + Rectangle or = c.getBounds(); + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(c, vr); + + g.setColor(c.getBackground()); + g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); + + Rectangle box = new Rectangle(); + getBox(box); + + g.setColor(c.getForeground()); + g.fill3DRect(box.x, box.y, box.width, box.height, true); + + if (progressBar.isStringPainted() && !progressBar.getString().equals("")) + paintString(g, 0, 0, or.width, or.height, + getAmountFull(insets, or.width, or.height), insets); + + g.setColor(saved); + } + + /** + * This method paints the string for the progressBar. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate of the progressBar. + * @param y The y coordinate of the progressBar. + * @param width The width of the progressBar. + * @param height The height of the progressBar. + * @param amountFull The amount of the progressBar that has its bar filled. + * @param b The insets of the progressBar. + */ + protected void paintString(Graphics g, int x, int y, int width, int height, + int amountFull, Insets b) + { + // 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); + + FontMetrics fm = g.getFontMetrics(progressBar.getFont()); + + g.drawString(progressBar.getString(), placement.x, + placement.y + fm.getAscent()); + + g.setColor(saved); + } + + /** + * This method sets the current animation index. If the index + * is greater than the number of frames, it resets to 0. + * + * @param newValue The new animation index. + */ + protected void setAnimationIndex(int newValue) + { + animationIndex = (newValue <= numFrames) ? newValue : 0; + progressBar.repaint(); + } + + /** + * This method sets the cell length. + * + * @param cellLen The cell length. + */ + protected void setCellLength(int cellLen) + { + cellLength = cellLen; + } + + /** + * This method sets the cell spacing. + * + * @param cellSpace The cell spacing. + */ + protected void setCellSpacing(int cellSpace) + { + cellSpacing = cellSpace; + } + + /** + * This method starts the animation timer. It is called + * when the propertyChangeListener detects that the progressBar + * has changed to indeterminate mode. + * + * @since 1.4 + */ + protected void startAnimationTimer() + { + if (animationTimer != null) + animationTimer.start(); + } + + /** + * This method stops the animation timer. It is called when + * the propertyChangeListener detects that the progressBar + * has changed to determinate mode. + * + * @since 1.4 + */ + protected void stopAnimationTimer() + { + if (animationTimer != null) + animationTimer.stop(); + setAnimationIndex(0); + } + + /** + * This method changes the settings for the progressBar to + * the defaults provided by the current Look and Feel. + */ + 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")); + progressBar.setOpaque(true); + + selectionForeground = defaults.getColor("ProgressBar.selectionForeground"); + selectionBackground = defaults.getColor("ProgressBar.selectionBackground"); + cellLength = defaults.getInt("ProgressBar.cellLength"); + cellSpacing = defaults.getInt("ProgressBar.cellSpacing"); + + int repaintInterval = defaults.getInt("ProgressBar.repaintInterval"); + int cycleTime = defaults.getInt("ProgressBar.cycleTime"); + + if (cycleTime % repaintInterval != 0 + && (cycleTime / repaintInterval) % 2 != 0) + { + int div = (cycleTime / repaintInterval) + 2; + div /= 2; + div *= 2; + cycleTime = div * repaintInterval; + } + setAnimationIndex(0); + numFrames = cycleTime / repaintInterval; + animationTimer.setDelay(repaintInterval); + } + + /** + * The method uninstalls any defaults that were + * set by the current Look and Feel. + */ + protected void uninstallDefaults() + { + progressBar.setFont(null); + progressBar.setForeground(null); + progressBar.setBackground(null); + + selectionForeground = null; + selectionBackground = null; + } + + /** + * This method registers listeners to all the + * components that this UI delegate needs to listen to. + */ + protected void installListeners() + { + changeListener = new ChangeHandler(); + propertyListener = new PropertyChangeHandler(); + animation = new Animator(); + + progressBar.addChangeListener(changeListener); + progressBar.addPropertyChangeListener(propertyListener); + animationTimer.addActionListener(animation); + } + + /** + * This method unregisters listeners to all the + * components that were listened to. + */ + protected void uninstallListeners() + { + progressBar.removeChangeListener(changeListener); + progressBar.removePropertyChangeListener(propertyListener); + animationTimer.removeActionListener(animation); + + changeListener = null; + propertyListener = null; + animation = null; + } + + /** + * This method installs the UI for the given JComponent. + * This includes setting up defaults and listeners as + * well as initializing any values or objects that + * the UI may need. + * + * @param c The JComponent that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JProgressBar) + { + progressBar = (JProgressBar) c; + + animationTimer = new Timer(200, null); + animationTimer.setRepeats(true); + + installDefaults(); + installListeners(); + } + } + + /** + * This method removes the UI for the given JComponent. + * This includes removing any listeners or defaults + * that the installUI may have set up. + * + * @param c The JComponent that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + uninstallListeners(); + uninstallDefaults(); + + animationTimer = null; + progressBar = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java new file mode 100644 index 0000000..d5cd7f4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -0,0 +1,102 @@ +/* BasicRadioButtonMenuItemUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegator for JRadioButtonMenuItem + */ +public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI +{ + /** + * Creates a new BasicRadioButtonMenuItemUI object. + */ + public BasicRadioButtonMenuItemUI() + { + super(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon"); + } + + /** + * Factory method to create a BasicRadioButtonMenuItemUI for the given {@link + * JComponent}, which should be a JRadioButtonMenuItem. + * + * @param b The {@link JComponent} a UI is being created for. + * + * @return A BasicRadioButtonMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicRadioButtonMenuItemUI(); + } + + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ + protected String getPropertyPrefix() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(JMenuItem item, MouseEvent e, + MenuElement[] path, + MenuSelectionManager manager) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java new file mode 100644 index 0000000..38e117b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java @@ -0,0 +1,87 @@ +/* BasicRadioButtonUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +public class BasicRadioButtonUI extends BasicToggleButtonUI +{ + + protected Icon icon; + + public static ComponentUI createUI(final JComponent c) { + return new BasicRadioButtonUI(); + } + + public BasicRadioButtonUI() + { + icon = getDefaultIcon(); + } + + public void installUI(final JComponent c) { + super.installUI(c); + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + b.setIcon(icon); + } + } + + public Icon getDefaultIcon() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + return defaults.getIcon("RadioButton.icon"); + } + +} + + + + + + + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java new file mode 100644 index 0000000..d97f7ba --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -0,0 +1,66 @@ +/* BasicPanelUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.RootPaneUI; + +public class BasicRootPaneUI extends RootPaneUI + implements PropertyChangeListener +{ + public static ComponentUI createUI(JComponent x) + { + return new BasicRootPaneUI(); + } + + public void installUI(JComponent c) + { + c.setBackground(UIManager.getColor("control")); + super.installUI(c); + } + + public void propertyChange(PropertyChangeEvent event) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java new file mode 100644 index 0000000..892db2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -0,0 +1,1271 @@ +/* BasicScrollBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoundedRangeModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.SwingConstants; +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; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollBarUI; + +/** + * The Basic Look and Feel UI delegate for JScrollBar. + */ +public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, + SwingConstants +{ + /** + * A helper class that listens to the two JButtons on each end of the + * JScrollBar. + */ + 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. + * + * @param e The MouseEvent fired by the JButton. + */ + public void mousePressed(MouseEvent e) + { + scrollTimer.stop(); + scrollListener.setScrollByBlock(false); + if (e.getSource() == incrButton) + scrollListener.setDirection(POSITIVE_SCROLL); + else + scrollListener.setDirection(NEGATIVE_SCROLL); + scrollTimer.start(); + } + + /** + * Stops the thumb when the JButton is released. + * + * @param e The MouseEvent fired by the JButton. + */ + public void mouseReleased(MouseEvent e) + { + scrollTimer.stop(); + } + } + + /** + * A helper class that listens to the ScrollBar's model for ChangeEvents. + */ + protected class ModelListener implements ChangeListener + { + /** + * Called when the model changes. + * + * @param e The ChangeEvent fired by the model. + */ + public void stateChanged(ChangeEvent e) + { + // System.err.println(this + ".stateChanged()"); + calculatePreferredSize(); + getThumbBounds(); + scrollbar.repaint(); + } + } + + /** + * A helper class that listens to the ScrollBar's properties. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when one of the ScrollBar's properties change. + * + * @param e The PropertyChangeEvent fired by the ScrollBar. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("model")) + { + ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); + scrollbar.getModel().addChangeListener(modelListener); + getThumbBounds(); + } + 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(); + } + scrollbar.repaint(); + } + } + + /** + * A helper class that listens for events from the timer that is used to + * move the thumb. + */ + protected class ScrollListener implements ActionListener + { + /** The direction the thumb moves in. */ + private transient int direction; + + /** Whether movement will be in blocks. */ + private transient boolean block; + + /** + * Creates a new ScrollListener object. The default is scrolling + * positively with block movement. + */ + public ScrollListener() + { + direction = POSITIVE_SCROLL; + block = true; + } + + /** + * Creates a new ScrollListener object using the given direction and + * block. + * + * @param dir The direction to move in. + * @param block Whether movement will be in blocks. + */ + public ScrollListener(int dir, boolean block) + { + direction = dir; + this.block = block; + } + + /** + * Sets the direction to scroll in. + * + * @param direction The direction to scroll in. + */ + public void setDirection(int direction) + { + this.direction = direction; + } + + /** + * Sets whether scrolling will be done in blocks. + * + * @param block Whether scrolling will be in blocks. + */ + public void setScrollByBlock(boolean block) + { + this.block = block; + } + + /** + * Called every time the timer reaches its interval. + * + * @param e The ActionEvent fired by the timer. + */ + public void actionPerformed(ActionEvent e) + { + 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); + } + else + scrollByUnit(direction); + } + } + + /** + * Helper class that listens for movement on the track. + */ + protected class TrackListener extends MouseAdapter + implements MouseMotionListener + { + /** The current X coordinate of the mouse. */ + protected int currentMouseX; + + /** The current Y coordinate of the mouse. */ + protected int currentMouseY; + + /** + * The offset between the current mouse cursor and the current value of + * the scrollbar. + */ + protected int offset; + + /** + * This method is called when the mouse is being dragged. + * + * @param e The MouseEvent given. + */ + public void mouseDragged(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + if (scrollbar.getValueIsAdjusting()) + { + int value; + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + value = valueForXPosition(currentMouseX) - offset; + else + value = valueForYPosition(currentMouseY) - offset; + + scrollbar.setValue(value); + } + } + + /** + * This method is called when the mouse is moved. + * + * @param e The MouseEvent given. + */ + public void mouseMoved(MouseEvent e) + { + // Not interested in where the mouse + // is unless it is being dragged. + } + + /** + * This method is called when the mouse is pressed. When it is pressed, + * the thumb should move in blocks towards the cursor. + * + * @param e The MouseEvent given. + */ + public void mousePressed(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + int value; + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (value == scrollbar.getValue()) + return; + + if (! thumbRect.contains(e.getPoint())) + { + scrollTimer.stop(); + scrollListener.setScrollByBlock(true); + if (value > scrollbar.getValue()) + { + trackHighlight = INCREASE_HIGHLIGHT; + scrollListener.setDirection(POSITIVE_SCROLL); + } + else + { + trackHighlight = DECREASE_HIGHLIGHT; + scrollListener.setDirection(NEGATIVE_SCROLL); + } + scrollTimer.start(); + } + else + { + // We'd like to keep track of where the cursor + // is inside the thumb. + // This works because the scrollbar's value represents + // "lower" edge of the thumb. The value at which + // the cursor is at must be greater or equal + // to that value. + scrollbar.setValueIsAdjusting(true); + offset = value - scrollbar.getValue(); + } + scrollbar.repaint(); + } + + /** + * This method is called when the mouse is released. It should stop + * movement on the thumb + * + * @param e The MouseEvent given. + */ + public void mouseReleased(MouseEvent e) + { + trackHighlight = NO_HIGHLIGHT; + scrollTimer.stop(); + + if (scrollbar.getValueIsAdjusting()) + scrollbar.setValueIsAdjusting(false); + scrollbar.repaint(); + } + + /** + * A helper method that decides whether we should keep scrolling in the + * given direction. + * + * @param direction The direction to check for. + * + * @return Whether the thumb should keep scrolling. + */ + public boolean shouldScroll(int direction) + { + int value; + if (scrollbar.getOrientation() == HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (direction == POSITIVE_SCROLL) + return (value > scrollbar.getValue()); + else + return (value < scrollbar.getValue()); + } + } + + /** The listener that listens to the JButtons. */ + protected ArrowButtonListener buttonListener; + + /** The listener that listens to the model. */ + protected ModelListener modelListener; + + /** The listener that listens to the scrollbar for property changes. */ + protected PropertyChangeListener propertyChangeListener; + + /** The listener that listens to the timer. */ + protected ScrollListener scrollListener; + + /** The listener that listens for MouseEvents on the track. */ + protected TrackListener trackListener; + + /** The JButton that decrements the scrollbar's value. */ + protected JButton decrButton; + + /** The JButton that increments the scrollbar's value. */ + protected JButton incrButton; + + /** The dimensions of the maximum thumb size. */ + protected Dimension maximumThumbSize; + + /** The dimensions of the minimum thumb size. */ + protected Dimension minimumThumbSize; + + /** The color of the thumb. */ + protected Color thumbColor; + + /** The outer shadow of the thumb. */ + protected Color thumbDarkShadowColor; + + /** The top and left edge color for the thumb. */ + protected Color thumbHighlightColor; + + /** The outer light shadow for the thumb. */ + protected Color thumbLightShadowColor; + + /** The color that is used when the mouse press occurs in the track. */ + protected Color trackHighlightColor; + + /** The color of the track. */ + protected Color trackColor; + + /** The size and position of the track. */ + protected Rectangle trackRect; + + /** The size and position of the thumb. */ + protected Rectangle thumbRect; + + /** Indicates that the decrease highlight should be painted. */ + protected static final int DECREASE_HIGHLIGHT = 1; + + /** Indicates that the increase highlight should be painted. */ + protected static final int INCREASE_HIGHLIGHT = 2; + + /** Indicates that no highlight should be painted. */ + protected static final int NO_HIGHLIGHT = 0; + + /** Indicates that the scrolling direction is positive. */ + private static final int POSITIVE_SCROLL = 1; + + /** Indicates that the scrolling direction is negative. */ + private static final int NEGATIVE_SCROLL = -1; + + /** The cached preferred size for the scrollbar. */ + private transient Dimension preferredSize; + + /** The current highlight status. */ + protected int trackHighlight; + + /** FIXME: Use this for something (presumably mouseDragged) */ + protected boolean isDragging; + + /** The timer used to move the thumb when the mouse is held. */ + protected Timer scrollTimer; + + /** The scrollbar this UI is acting for. */ + protected JScrollBar scrollbar; + + /** + * This method adds a component to the layout. + * + * @param name The name to associate with the component that is added. + * @param child The Component to add. + */ + public void addLayoutComponent(String name, Component child) + { + // You should not be adding stuff to this component. + // The contents are fixed. + } + + /** + * This method configures the scrollbar's colors. This can be done by + * looking up the standard colors from the Look and Feel defaults. + */ + protected void configureScrollBarColors() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + trackColor = defaults.getColor("ScrollBar.track"); + trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight"); + thumbColor = defaults.getColor("ScrollBar.thumb"); + thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight"); + thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow"); + thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow"); + } + + /** + * This method creates an ArrowButtonListener. + * + * @return A new ArrowButtonListener. + */ + protected ArrowButtonListener createArrowButtonListener() + { + return new ArrowButtonListener(); + } + + /** + * This method creates a new JButton with the appropriate icon for the + * orientation. + * + * @param orientation The orientation this JButton uses. + * + * @return The increase JButton. + */ + protected JButton createIncreaseButton(int orientation) + { + if (incrButton == null) + incrButton = new BasicArrowButton(orientation); + else + ((BasicArrowButton) incrButton).setDirection(orientation); + return incrButton; + } + + /** + * This method creates a new JButton with the appropriate icon for the + * orientation. + * + * @param orientation The orientation this JButton uses. + * + * @return The decrease JButton. + */ + protected JButton createDecreaseButton(int orientation) + { + if (decrButton == null) + decrButton = new BasicArrowButton(orientation); + else + ((BasicArrowButton) decrButton).setDirection(orientation); + return decrButton; + } + + /** + * This method creates a new ModelListener. + * + * @return A new ModelListener. + */ + protected ModelListener createModelListener() + { + return new ModelListener(); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new ScrollListener. + * + * @return A new ScrollListener. + */ + protected ScrollListener createScrollListener() + { + return new ScrollListener(); + } + + /** + * This method creates a new TrackListener. + * + * @return A new TrackListener. + */ + protected TrackListener createTrackListener() + { + return new TrackListener(); + } + + /** + * This method returns a new BasicScrollBarUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicScrollBarUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicScrollBarUI(); + } + + /** + * This method returns the maximum size for this JComponent. + * + * @param c The JComponent to measure the maximum size for. + * + * @return The maximum size for the component. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum thumb size. + * + * @return The maximum thumb size. + */ + protected Dimension getMaximumThumbSize() + { + return maximumThumbSize; + } + + /** + * This method returns the minimum size for this JComponent. + * + * @param c The JComponent to measure the minimum size for. + * + * @return The minimum size for the component. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum thumb size. + * + * @return The minimum thumb size. + */ + protected Dimension getMinimumThumbSize() + { + return minimumThumbSize; + } + + /** + * This method calculates the preferred size since calling + * getPreferredSize() returns a cached value. + * This is package-private to avoid an accessor method. + */ + void calculatePreferredSize() + { + // System.err.println(this + ".calculatePreferredSize()"); + int height; + int width; + height = width = 0; + + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + { + width += incrButton.getPreferredSize().getWidth(); + width += decrButton.getPreferredSize().getWidth(); + + width += (scrollbar.getMaximum() - scrollbar.getMinimum()); + + height = Math.max(incrButton.getPreferredSize().height, + decrButton.getPreferredSize().height); + height = Math.max(getMinimumThumbSize().height, height); + height = Math.max(20, height); + height = Math.min(getMaximumThumbSize().height, height); + } + else + { + height += incrButton.getPreferredSize().getHeight(); + height += decrButton.getPreferredSize().getHeight(); + + height += (scrollbar.getMaximum() - scrollbar.getMinimum()); + + width = Math.max(incrButton.getPreferredSize().width, + decrButton.getPreferredSize().width); + width = Math.max(getMinimumThumbSize().width, width); + width = Math.max(20, width); + width = Math.min(getMaximumThumbSize().width, width); + } + + Insets insets = scrollbar.getInsets(); + + height += insets.top + insets.bottom; + width += insets.left + insets.right; + + preferredSize = new Dimension(width, height); + } + + /** + * This method returns a cached value of the preferredSize. The only + * restrictions are: If the scrollbar is horizontal, the height should be + * the maximum of the height of the JButtons and the minimum width of the + * thumb. For vertical scrollbars, the calculation is similar (swap width + * for height and vice versa). + * + * @param c The JComponent to measure. + * + * @return The preferredSize. + */ + public Dimension getPreferredSize(JComponent c) + { + calculatePreferredSize(); + return preferredSize; + } + + /** + * This method returns the thumb's bounds based on the current value of the + * scrollbar. This method updates the cached value and returns that. + * + * @return The thumb bounds. + */ + 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; + } + + /** + * This method calculates the bounds of the track. This method updates the + * cached value and returns it. + * + * @return The track's bounds. + */ + 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; + } + + /** + * This method installs any addition Components that are a part of or + * related to this scrollbar. + */ + protected void installComponents() + { + int orientation = scrollbar.getOrientation(); + switch (orientation) + { + case (JScrollBar.HORIZONTAL): + incrButton = createIncreaseButton(EAST); + decrButton = createDecreaseButton(WEST); + break; + default: + incrButton = createIncreaseButton(SOUTH); + 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")); + 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"); + + maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize"); + minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize"); + } + + /** + * This method installs the keyboard actions for the scrollbar. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs any listeners for the scrollbar. This method also + * installs listeners for things such as the JButtons and the timer. + */ + protected void installListeners() + { + scrollListener = createScrollListener(); + trackListener = createTrackListener(); + buttonListener = createArrowButtonListener(); + modelListener = createModelListener(); + propertyChangeListener = createPropertyChangeListener(); + + scrollbar.addMouseMotionListener(trackListener); + scrollbar.addMouseListener(trackListener); + + incrButton.addMouseListener(buttonListener); + decrButton.addMouseListener(buttonListener); + + scrollbar.addPropertyChangeListener(propertyChangeListener); + scrollbar.getModel().addChangeListener(modelListener); + + scrollTimer.addActionListener(scrollListener); + } + + /** + * This method installs the UI for the component. This can include setting + * up listeners, defaults, and components. This also includes initializing + * any data objects. + * + * @param c The JComponent to install. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JScrollBar) + { + scrollbar = (JScrollBar) c; + + trackRect = new Rectangle(); + thumbRect = new Rectangle(); + + scrollTimer = new Timer(200, null); + scrollTimer.setRepeats(true); + + installComponents(); + installDefaults(); + configureScrollBarColors(); + installListeners(); + + calculatePreferredSize(); + } + } + + /** + * This method lays out the scrollbar. + * + * @param scrollbarContainer The Container to layout. + */ + public void layoutContainer(Container scrollbarContainer) + { + if (scrollbarContainer instanceof JScrollBar) + { + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + layoutHScrollbar((JScrollBar) scrollbarContainer); + else + layoutVScrollbar((JScrollBar) scrollbarContainer); + } + } + + /** + * This method lays out the scrollbar horizontally. + * + * @param sb The JScrollBar to layout. + */ + 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(); + + decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height); + incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width, + trackRect.height); + } + + /** + * This method lays out the scrollbar vertically. + * + * @param sb The JScrollBar to layout. + */ + protected void layoutVScrollbar(JScrollBar sb) + { + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(scrollbar, vr); + + // Update rectangles + getTrackBounds(); + getThumbBounds(); + + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height); + incrButton.setBounds(vr.x, trackRect.y + trackRect.height, + trackRect.width, incrDims.height); + } + + /** + * This method returns the minimum size required for the layout. + * + * @param scrollbarContainer The Container that is laid out. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container scrollbarContainer) + { + return preferredLayoutSize(scrollbarContainer); + } + + /** + * This method is called when the component is painted. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + paintTrack(g, c, getTrackBounds()); + paintThumb(g, c, getThumbBounds()); + + if (trackHighlight == INCREASE_HIGHLIGHT) + paintIncreaseHighlight(g); + else if (trackHighlight == DECREASE_HIGHLIGHT) + paintDecreaseHighlight(g); + } + + /** + * This method is called when repainting and the mouse is pressed in the + * track. It paints the track below the thumb with the trackHighlight + * color. + * + * @param g The Graphics object to paint with. + */ + protected void paintDecreaseHighlight(Graphics g) + { + Color saved = g.getColor(); + + g.setColor(trackHighlightColor); + if (scrollbar.getOrientation() == HORIZONTAL) + g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x, + trackRect.height); + else + g.fillRect(trackRect.x, trackRect.y, trackRect.width, + thumbRect.y - trackRect.y); + g.setColor(saved); + } + + /** + * This method is called when repainting and the mouse is pressed in the + * track. It paints the track above the thumb with the trackHighlight + * color. + * + * @param g The Graphics objet to paint with. + */ + protected void paintIncreaseHighlight(Graphics g) + { + Color saved = g.getColor(); + + g.setColor(trackHighlightColor); + if (scrollbar.getOrientation() == HORIZONTAL) + g.fillRect(thumbRect.x + thumbRect.width, trackRect.y, + trackRect.x + trackRect.width - thumbRect.x - thumbRect.width, + trackRect.height); + else + g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width, + trackRect.y + trackRect.height - thumbRect.y + - thumbRect.height); + g.setColor(saved); + } + + /** + * This method paints the thumb. + * + * @param g The Graphics object to paint with. + * @param c The Component that is being painted. + * @param thumbBounds The thumb bounds. + */ + protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) + { + g.setColor(thumbColor); + g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, + thumbBounds.height); + + BasicGraphicsUtils.drawBezel(g, thumbBounds.x, thumbBounds.y, + thumbBounds.width, thumbBounds.height, + false, false, thumbDarkShadowColor, + thumbDarkShadowColor, thumbHighlightColor, + thumbHighlightColor); + } + + /** + * This method paints the track. + * + * @param g The Graphics object to paint with. + * @param c The JComponent being painted. + * @param trackBounds The track's bounds. + */ + protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) + { + Color saved = g.getColor(); + g.setColor(trackColor); + g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width, + trackBounds.height, false); + g.setColor(saved); + } + + /** + * This method returns the preferred size for the layout. + * + * @param scrollbarContainer The Container to find a size for. + * + * @return The preferred size for the layout. + */ + public Dimension preferredLayoutSize(Container scrollbarContainer) + { + if (scrollbarContainer instanceof JComponent) + return getPreferredSize((JComponent) scrollbarContainer); + else + return null; + } + + /** + * This method removes a child component from the layout. + * + * @param child The child to remove. + */ + public void removeLayoutComponent(Component child) + { + // You should not be removing stuff from this component. + } + + /** + * The method scrolls the thumb by a block in the direction specified. + * + * @param direction The direction to scroll. + */ + protected void scrollByBlock(int direction) + { + scrollbar.setValue(scrollbar.getValue() + + scrollbar.getBlockIncrement(direction)); + } + + /** + * The method scrolls the thumb by a unit in the direction specified. + * + * @param direction The direction to scroll. + */ + protected void scrollByUnit(int direction) + { + scrollbar.setValue(scrollbar.getValue() + + scrollbar.getUnitIncrement(direction)); + } + + /** + * This method sets the thumb's bounds. + * + * @param x The X position of the thumb. + * @param y The Y position of the thumb. + * @param width The width of the thumb. + * @param height The height of the thumb. + */ + protected void setThumbBounds(int x, int y, int width, int height) + { + thumbRect.x = x; + thumbRect.y = y; + thumbRect.width = width; + thumbRect.height = height; + } + + /** + * This method uninstalls any components that are a part of or related to + * this scrollbar. + */ + protected void uninstallComponents() + { + scrollbar.remove(incrButton); + scrollbar.remove(decrButton); + incrButton = null; + decrButton = null; + } + + /** + * This method uninstalls any defaults that this scrollbar acquired from the + * Basic Look and Feel defaults. + */ + protected void uninstallDefaults() + { + scrollbar.setForeground(null); + scrollbar.setBackground(null); + scrollbar.setBorder(null); + } + + /** + * This method uninstalls any keyboard actions this scrollbar acquired + * during install. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls any listeners that were registered during install. + */ + protected void uninstallListeners() + { + scrollTimer.removeActionListener(scrollListener); + + scrollbar.getModel().removeChangeListener(modelListener); + scrollbar.removePropertyChangeListener(propertyChangeListener); + + decrButton.removeMouseListener(buttonListener); + incrButton.removeMouseListener(buttonListener); + + scrollbar.removeMouseListener(trackListener); + scrollbar.removeMouseMotionListener(trackListener); + + propertyChangeListener = null; + modelListener = null; + buttonListener = null; + trackListener = null; + scrollListener = null; + } + + /** + * This method uninstalls the UI. This includes removing any defaults, + * listeners, and components that this UI may have initialized. It also + * nulls any instance data. + * + * @param c The Component to uninstall for. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(); + uninstallListeners(); + uninstallComponents(); + + scrollTimer = null; + + thumbRect = null; + trackRect = null; + + trackColor = null; + trackHighlightColor = null; + thumbColor = null; + thumbHighlightColor = null; + thumbDarkShadowColor = null; + thumbLightShadowColor = null; + + scrollbar = null; + } + + /** + * This method returns the value in the scrollbar's range given the y + * coordinate. If the value is out of range, it will return the closest + * legal value. + * This is package-private to avoid an accessor method. + * + * @param yPos The y coordinate to calculate a value for. + * + * @return The value for the y coordinate. + */ + int valueForYPosition(int yPos) + { + int min = scrollbar.getMinimum(); + int max = scrollbar.getMaximum(); + int len = trackRect.height; + + int value; + + // If the length is 0, you shouldn't be able to even see where the thumb is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + value = ((yPos - trackRect.y) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method returns the value in the scrollbar's range given the x + * coordinate. If the value is out of range, it will return the closest + * legal value. + * This is package-private to avoid an accessor method. + * + * @param xPos The x coordinate to calculate a value for. + * + * @return The value for the x coordinate. + */ + int valueForXPosition(int xPos) + { + int min = scrollbar.getMinimum(); + int max = scrollbar.getMaximum(); + int len = trackRect.width; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + value = ((xPos - trackRect.x) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java new file mode 100644 index 0000000..7bb7acf --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -0,0 +1,130 @@ +/* BasicScrollPaneUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.ScrollPaneLayout; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollPaneUI; + +public class BasicScrollPaneUI extends ScrollPaneUI + implements ScrollPaneConstants +{ + + /** The Scrollpane for which the UI is provided by this class. */ + protected JScrollPane scrollpane; + + public static ComponentUI createUI(final JComponent c) + { + return new BasicScrollPaneUI(); + } + + 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")); + p.setOpaque(true); + } + + protected void uninstallDefaults(JScrollPane p) + { + p.setForeground(null); + p.setBackground(null); + p.setFont(null); + p.setBorder(null); + scrollpane = null; + } + + public void installUI(final JComponent c) + { + super.installUI(c); + this.installDefaults((JScrollPane)c); + } + + public void uninstallUI(final JComponent c) + { + super.uninstallUI(c); + this.uninstallDefaults((JScrollPane)c); + } + + + public Dimension getMinimumSize(JComponent c) + { + JScrollPane p = (JScrollPane ) c; + ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout(); + return sl.minimumLayoutSize(c); + } + + public Dimension getPreferredSize(JComponent c) + { + JScrollPane p = (JScrollPane ) c; + ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout(); + return sl.preferredLayoutSize(c); + } + + + public void paint(Graphics g, JComponent c) + { + // do nothing; the normal painting-of-children algorithm, along with + // ScrollPaneLayout, does all the relevant work. + } +} + + + + + + + + + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java new file mode 100644 index 0000000..38c9c7a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java @@ -0,0 +1,269 @@ +/* BasicSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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; + +/** + * The Basic Look and Feel UI delegate for JSeparator. + */ +public class BasicSeparatorUI extends SeparatorUI +{ + /** The shadow color. */ + protected Color shadow; + + /** The highlight color. */ + protected Color highlight; + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicSeparatorUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicSeparatorUI(); + } + + /** + * This method installs the UI for the given JComponent. + * This can include installing defaults, listeners, and + * initializing any instance data. + * + * @param c The JComponent that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JSeparator) + { + JSeparator s = (JSeparator) c; + + installDefaults(s); + installListeners(s); + } + } + + /** + * Uninstalls the UI for the given JComponent. This + * method reverses what was done when installing + * the UI on the JComponent. + * + * @param c The JComponent that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + if (c instanceof JSeparator) + { + JSeparator s = (JSeparator) c; + + uninstallListeners(s); + uninstallDefaults(s); + } + } + + /** + * This method installs the defaults that are given by + * the Basic Look and Feel. + * + * @param s The JSeparator that is being installed. + */ + protected void installDefaults(JSeparator s) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + shadow = defaults.getColor("Separator.shadow"); + highlight = defaults.getColor("Separator.highlight"); + s.setOpaque(false); + } + + /** + * This method removes the defaults that were given + * by the Basic Look and Feel. + * + * @param s The JSeparator that is being uninstalled. + */ + protected void uninstallDefaults(JSeparator s) + { + shadow = null; + highlight = null; + } + + /** + * This method installs any listeners that need + * to be attached to the JSeparator or any of its + * components. + * + * @param s The JSeparator that is being installed. + */ + protected void installListeners(JSeparator s) + { + // Separators don't receive events. + } + + /** + * This method uninstalls any listeners that + * were installed during the install UI process. + * + * @param s The JSeparator that is being uninstalled. + */ + protected void uninstallListeners(JSeparator s) + { + // Separators don't receive events. + } + + /** + * 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 + * 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(); + + int midAB = r.width / 2 + r.x; + int midAD = r.height / 2 + r.y; + + JSeparator s; + if (c instanceof JSeparator) + s = (JSeparator) c; + else + 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); + } + } + + /** + * This method returns the preferred size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + Dimension dims = new Dimension(0, 0); + Insets insets = c.getInsets(); + + 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; + } + } + dims.width += insets.left + insets.right; + dims.height += insets.top + insets.bottom; + + return dims; + } + + /** + * This method returns the minimum size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java new file mode 100644 index 0000000..0a72a62 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java @@ -0,0 +1,2239 @@ +/* BasicSliderUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Polygon; +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.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Dictionary; +import java.util.Enumeration; + +import javax.swing.BoundedRangeModel; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JSlider; +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; +import javax.swing.event.MouseInputAdapter; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SliderUI; + +/** + *

+ * BasicSliderUI.java This is the UI delegate in the Basic look and feel that + * paints JSliders. + *

+ * + *

+ * The UI delegate keeps track of 6 rectangles that place the various parts of + * the JSlider inside the component. + *

+ * + *

+ * The rectangles are organized as follows: + *

+ *
+ *     +-------------------------------------------------------+ <-- focusRect
+ *     |                                                       |
+ *     |  +==+-------------------+==+--------------------+==+<------ contentRect
+ *     |  |  |                   |  |<---thumbRect       |  |  |
+ *     |  |  |    TRACK          |  |                    |<--------- trackRect
+ *     |  |  +-------------------+==+--------------------+  |  |
+ *     |  |  |                                           |  |  |
+ *     |  |  |          TICKS GO HERE                    |<-------- tickRect
+ *     |  |  |                                           |  |  |
+ *     |  +==+-------------------------------------------+==+  |
+ *     |  |  |                                           |  |  |
+ *     |  |  |                                           |  |<----- labelRect
+ *     |  |  |                 LABELS GO HERE            |  |  |
+ *     |  |  |                                           |  |  |
+ *     |  |  |                                           |  |  |
+ *     |  |  |                                           |  |  |
+ *     |  |  |                                           |  |  |
+ *     |  |                                              |  |  |
+ * 
+ * + *

+ * The space between the contentRect and the focusRect are the FocusInsets. + *

+ * + *

+ * The space between the focusRect and the component bounds is the insetCache + * which are the component's insets. + *

+ * + *

+ * The top of the thumb is the top of the contentRect. The trackRect has to be + * as tall as the thumb. + *

+ * + *

+ * The trackRect and tickRect do not start from the left edge of the + * focusRect. They are trackBuffer away from each side of the focusRect. This + * is so that the thumb has room to move. + *

+ * + *

+ * The labelRect does start right against the contentRect's left and right + * edges and it gets all remaining space. + *

+ */ +public class BasicSliderUI extends SliderUI +{ + /** + * Helper class that listens to the {@link JSlider}'s model for changes. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ChangeHandler implements ChangeListener + { + /** + * Called when the slider's model has been altered. The UI delegate should + * recalculate any rectangles that are dependent on the model for their + * positions and repaint. + * + * @param e A static {@link ChangeEvent} passed from the model. + */ + public void stateChanged(ChangeEvent e) + { + // Maximum, minimum, and extent values will be taken + // care of automatically when the slider is repainted. + // Only thing that needs recalculation is the thumb. + calculateThumbLocation(); + slider.repaint(); + } + } + + /** + * Helper class that listens for resize events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ComponentHandler extends ComponentAdapter + { + /** + * Called when the size of the component changes. The UI delegate should + * recalculate any rectangles that are dependent on the model for their + * positions and repaint. + * + * @param e A {@link ComponentEvent}. + */ + public void componentResized(ComponentEvent e) + { + calculateGeometry(); + + slider.revalidate(); + slider.repaint(); + } + } + + /** + * Helper class that listens for focus events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler implements FocusListener + { + /** + * Called when the {@link JSlider} has gained focus. It should repaint + * the slider with the focus drawn. + * + * @param e A {@link FocusEvent}. + */ + public void focusGained(FocusEvent e) + { + // FIXME: implement. + } + + /** + * Called when the {@link JSlider} has lost focus. It should repaint the + * slider without the focus drawn. + * + * @param e A {@link FocusEvent}. + */ + public void focusLost(FocusEvent e) + { + // FIXME: implement. + } + } + + /** + * Helper class that listens for changes to the properties of the {@link + * JSlider}. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when one of the properties change. The UI should recalculate any + * rectangles if necessary and repaint. + * + * @param e A {@link PropertyChangeEvent}. + */ + public void propertyChange(PropertyChangeEvent e) + { + // Check for orientation changes. + if (e.getPropertyName().equals("orientation")) + recalculateIfOrientationChanged(); + else if (e.getPropertyName().equals("model")) + { + BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue(); + oldModel.removeChangeListener(changeListener); + slider.getModel().addChangeListener(changeListener); + calculateThumbLocation(); + } + + // elif the componentOrientation changes (this is a bound property, + // just undocumented) we change leftToRightCache. In Sun's + // implementation, the LTR cache changes on a repaint. This is strange + // since there is no need to do so. We could events here and + // update the cache. + // elif the border/insets change, we recalculateInsets. + slider.repaint(); + } + } + + /** + * Helper class that listens to our swing timer. This class is responsible + * for listening to the timer and moving the thumb in the proper direction + * every interval. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ScrollListener implements ActionListener + { + /** Indicates which direction the thumb should scroll. */ + private transient int direction; + + /** Indicates whether we should scroll in blocks or in units. */ + private transient boolean block; + + /** + * Creates a new ScrollListener object. + */ + public ScrollListener() + { + direction = POSITIVE_SCROLL; + block = false; + } + + /** + * Creates a new ScrollListener object. + * + * @param dir The direction to scroll in. + * @param block If movement will be in blocks. + */ + public ScrollListener(int dir, boolean block) + { + direction = dir; + this.block = block; + } + + /** + * Called every time the swing timer reaches its interval. If the thumb + * needs to move, then this method will move the thumb one block or unit + * in the direction desired. Otherwise, the timer can be stopped. + * + * @param e An {@link ActionEvent}. + */ + public void actionPerformed(ActionEvent e) + { + if (! trackListener.shouldScroll(direction)) + { + scrollTimer.stop(); + return; + } + + if (block) + scrollByBlock(direction); + else + scrollByUnit(direction); + } + + /** + * Sets the direction to scroll in. + * + * @param direction The direction to scroll in. + */ + public void setDirection(int direction) + { + this.direction = direction; + } + + /** + * Sets whether movement will be in blocks. + * + * @param block If movement will be in blocks. + */ + public void setScrollByBlock(boolean block) + { + this.block = block; + } + } + + /** + * Helper class that listens for mouse events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TrackListener extends MouseInputAdapter + { + /** The current X position of the mouse. */ + protected int currentMouseX; + + /** The current Y position of the mouse. */ + protected int currentMouseY; + + /** + * The offset between the current slider value and the cursor's position. + */ + protected int offset; + + /** + * Called when the mouse has been dragged. This should find the mouse's + * current position and adjust the value of the {@link JSlider} + * accordingly. + * + * @param e A {@link MouseEvent} + */ + public void mouseDragged(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + if (slider.getValueIsAdjusting()) + { + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX) - offset; + else + value = valueForYPosition(currentMouseY) - offset; + + slider.setValue(value); + } + } + + /** + * Called when the mouse has moved over a component but no buttons have + * been pressed yet. + * + * @param e A {@link MouseEvent} + */ + public void mouseMoved(MouseEvent e) + { + // Don't care that we're moved unless we're dragging. + } + + /** + * Called when the mouse is pressed. When the press occurs on the thumb + * itself, the {@link JSlider} should have its value set to where the + * mouse was pressed. If the press occurs on the track, then the thumb + * should move one block towards the direction of the mouse. + * + * @param e A {@link MouseEvent} + */ + public void mousePressed(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (slider.getSnapToTicks()) + value = findClosestTick(value); + + // If the thumb is hit, then we don't need to set the timers to move it. + if (! thumbRect.contains(e.getPoint())) + { + // The mouse has hit some other part of the slider. + // The value moves no matter where in the slider you hit. + if (value > slider.getValue()) + scrollDueToClickInTrack(POSITIVE_SCROLL); + else + scrollDueToClickInTrack(NEGATIVE_SCROLL); + } + else + { + slider.setValueIsAdjusting(true); + offset = value - slider.getValue(); + } + } + + /** + * Called when the mouse is released. This should stop the timer that + * scrolls the thumb. + * + * @param e A {@link MouseEvent} + */ + public void mouseReleased(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + if (slider.getValueIsAdjusting()) + { + slider.setValueIsAdjusting(false); + if (slider.getSnapToTicks()) + slider.setValue(findClosestTick(slider.getValue())); + } + if (scrollTimer != null) + scrollTimer.stop(); + } + + /** + * Indicates whether the thumb should scroll in the given direction. + * + * @param direction The direction to check. + * + * @return True if the thumb should move in that direction. + */ + public boolean shouldScroll(int direction) + { + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (direction == POSITIVE_SCROLL) + return (value > slider.getValue()); + else + return (value < slider.getValue()); + } + } + + /** The preferred height of the thumb. */ + private transient int thumbHeight; + + /** The preferred width of the thumb. */ + private transient int thumbWidth; + + /** The preferred height of the tick rectangle. */ + private transient int tickHeight; + + /** Listener for changes from the model. */ + protected ChangeListener changeListener; + + /** Listener for changes to the {@link JSlider}. */ + protected PropertyChangeListener propertyChangeListener; + + /** Listener for the scrollTimer. */ + protected ScrollListener scrollListener; + + /** Listener for component resizing. */ + protected ComponentListener componentListener; + + /** Listener for focus handling. */ + protected FocusListener focusListener; + + /** Listener for mouse events. */ + protected TrackListener trackListener; + + /** The insets between the FocusRectangle and the ContentRectangle. */ + protected Insets focusInsets; + + /** The {@link JSlider}'s insets. */ + protected Insets insetCache; + + /** Rectangle describing content bounds. See diagram above. */ + protected Rectangle contentRect; + + /** Rectangle describing focus bounds. See diagram above. */ + protected Rectangle focusRect; + + /** Rectangle describing the thumb's bounds. See diagram above. */ + protected Rectangle thumbRect; + + /** Rectangle describing the tick bounds. See diagram above. */ + protected Rectangle tickRect; + + /** Rectangle describing the label bounds. See diagram above. */ + protected Rectangle labelRect; + + /** Rectangle describing the track bounds. See diagram above. */ + protected Rectangle trackRect; + + /** FIXME: use this somewhere. */ + public static final int MAX_SCROLL = 2; + + /** FIXME: use this somewhere. */ + public static final int MIN_SCROLL = -2; + + /** A constant describing scrolling towards the minimum. */ + public static final int NEGATIVE_SCROLL = -1; + + /** A constant describing scrolling towards the maximum. */ + public static final int POSITIVE_SCROLL = 1; + + /** The gap between the edges of the contentRect and trackRect. */ + protected int trackBuffer; + + /** Whether this slider is actually drawn left to right. */ + protected boolean leftToRightCache; + + /** A timer that periodically moves the thumb. */ + protected Timer scrollTimer; + + /** A reference to the {@link JSlider} that this UI was created for. */ + protected JSlider slider; + + /** The shadow color. */ + private transient Color shadowColor; + + /** The highlight color. */ + private transient Color highlightColor; + + /** The focus color. */ + private transient Color focusColor; + + /** + * Creates a new Basic look and feel Slider UI. + * + * @param b The {@link JSlider} that this UI was created for. + */ + public BasicSliderUI(JSlider b) + { + super(); + } + + /** + * Gets the shadow color to be used for this slider. The shadow color is the + * color used for drawing the top and left edges of the track. + * + * @return The shadow color. + */ + protected Color getShadowColor() + { + return shadowColor; + } + + /** + * Gets the highlight color to be used for this slider. The highlight color + * is the color used for drawing the bottom and right edges of the track. + * + * @return The highlight color. + */ + protected Color getHighlightColor() + { + return highlightColor; + } + + /** + * Gets the focus color to be used for this slider. The focus color is the + * color used for drawing the focus rectangle when the component gains + * focus. + * + * @return The focus color. + */ + protected Color getFocusColor() + { + return focusColor; + } + + /** + * Factory method to create a BasicSliderUI for the given {@link + * JComponent}, which should be a {@link JSlider}. + * + * @param b The {@link JComponent} a UI is being created for. + * + * @return A BasicSliderUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicSliderUI((JSlider) b); + } + + /** + * 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) + { + super.installUI(c); + if (c instanceof JSlider) + { + slider = (JSlider) c; + + focusRect = new Rectangle(); + contentRect = new Rectangle(); + thumbRect = new Rectangle(); + trackRect = new Rectangle(); + tickRect = new Rectangle(); + labelRect = new Rectangle(); + + insetCache = slider.getInsets(); + leftToRightCache = ! slider.getInverted(); + + scrollTimer = new Timer(200, null); + scrollTimer.setRepeats(true); + + installDefaults(slider); + installListeners(slider); + installKeyboardActions(slider); + + calculateFocusRect(); + + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + } + + /** + * 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. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + + uninstallKeyboardActions(slider); + uninstallListeners(slider); + + scrollTimer = null; + + focusRect = null; + contentRect = null; + thumbRect = null; + trackRect = null; + tickRect = null; + labelRect = null; + + focusInsets = null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + * + * @param slider The {@link JSlider} that is having this UI installed. + */ + 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")); + slider.setOpaque(true); + + thumbHeight = defaults.getInt("Slider.thumbHeight"); + thumbWidth = defaults.getInt("Slider.thumbWidth"); + tickHeight = defaults.getInt("Slider.tickHeight"); + + focusInsets = defaults.getInsets("Slider.focusInsets"); + } + + /** + * Creates a new {@link TrackListener}. + * + * @param slider The {@link JSlider} that this {@link TrackListener} is + * created for. + * + * @return A new {@link TrackListener}. + */ + protected TrackListener createTrackListener(JSlider slider) + { + return new TrackListener(); + } + + /** + * Creates a new {@link ChangeListener}. + * + * @param slider The {@link JSlider} that this {@link ChangeListener} is + * created for. + * + * @return A new {@link ChangeListener}. + */ + protected ChangeListener createChangeListener(JSlider slider) + { + return new ChangeHandler(); + } + + /** + * Creates a new {@link ComponentListener}. + * + * @param slider The {@link JSlider} that this {@link ComponentListener} is + * created for. + * + * @return A new {@link ComponentListener}. + */ + protected ComponentListener createComponentListener(JSlider slider) + { + return new ComponentHandler(); + } + + /** + * Creates a new {@link FocusListener}. + * + * @param slider The {@link JSlider} that this {@link FocusListener} is + * created for. + * + * @return A new {@link FocusListener}. + */ + protected FocusListener createFocusListener(JSlider slider) + { + return new FocusHandler(); + } + + /** + * Creates a new {@link ScrollListener}. + * + * @param slider The {@link JSlider} that this {@link ScrollListener} is + * created for. + * + * @return A new {@link ScrollListener}. + */ + protected ScrollListener createScrollListener(JSlider slider) + { + return new ScrollListener(); + } + + /** + * Creates a new {@link PropertyChangeListener}. + * + * @param slider The {@link JSlider} that this {@link + * PropertyChangeListener} is created for. + * + * @return A new {@link PropertyChangeListener}. + */ + protected PropertyChangeListener createPropertyChangeListener(JSlider slider) + { + return new PropertyChangeHandler(); + } + + /** + * Creates and registers all the listeners for this UI delegate. This + * includes creating the ScrollListener and registering it to the timer. + * + * @param slider The {@link JSlider} is having listeners installed. + */ + protected void installListeners(JSlider slider) + { + propertyChangeListener = createPropertyChangeListener(slider); + componentListener = createComponentListener(slider); + trackListener = createTrackListener(slider); + focusListener = createFocusListener(slider); + changeListener = createChangeListener(slider); + scrollListener = createScrollListener(slider); + + slider.addPropertyChangeListener(propertyChangeListener); + slider.addComponentListener(componentListener); + slider.addMouseListener(trackListener); + slider.addMouseMotionListener(trackListener); + slider.addFocusListener(focusListener); + slider.getModel().addChangeListener(changeListener); + + scrollTimer.addActionListener(scrollListener); + } + + /** + * Unregisters all the listeners that this UI delegate was using. In + * addition, it will also null any listeners that it was using. + * + * @param slider The {@link JSlider} that is having listeners removed. + */ + protected void uninstallListeners(JSlider slider) + { + slider.removePropertyChangeListener(propertyChangeListener); + slider.removeComponentListener(componentListener); + slider.removeMouseListener(trackListener); + slider.removeMouseMotionListener(trackListener); + slider.removeFocusListener(focusListener); + slider.getModel().removeChangeListener(changeListener); + + scrollTimer.removeActionListener(scrollListener); + + propertyChangeListener = null; + componentListener = null; + trackListener = null; + focusListener = null; + changeListener = null; + scrollListener = null; + } + + /** + * Installs any keyboard actions. The list of keys that need to be bound are + * listed in Basic look and feel's defaults. + * + * @param slider The {@link JSlider} that is having keyboard actions + * installed. + */ + protected void installKeyboardActions(JSlider slider) + { + // FIXME: implement. + } + + /** + * Uninstalls any keyboard actions. The list of keys used are listed in + * Basic look and feel's defaults. + * + * @param slider The {@link JSlider} that is having keyboard actions + * uninstalled. + */ + protected void uninstallKeyboardActions(JSlider slider) + { + // FIXME: implement. + } + + /* XXX: This is all after experimentation with SUN's implementation. + + PreferredHorizontalSize seems to be 200x21. + PreferredVerticalSize seems to be 21x200. + + MinimumHorizontalSize seems to be 36x21. + MinimumVerticalSize seems to be 21x36. + + PreferredSize seems to be 200x63. Or Components.getBounds? + + MinimumSize seems to be 36x63. + + MaximumSize seems to be 32767x63. + */ + + /** + * This method returns the preferred size when the slider is horizontally + * oriented. + * + * @return The dimensions of the preferred horizontal size. + */ + public Dimension getPreferredHorizontalSize() + { + Insets insets = slider.getInsets(); + + // The width should cover all the labels (which are usually the + // deciding factor of the width) + int width = getWidthOfWidestLabel() * (slider.getLabelTable() == null ? 0 + : slider.getLabelTable() + .size()); + + // If there are not enough labels. + // This number is pretty much arbitrary, but it looks nice. + if (width < 200) + width = 200; + + // We can only draw inside of the focusRectangle, so we have to + // pad it with insets. + width += insets.left + insets.right + focusInsets.left + focusInsets.right; + + // Height is determined by the thumb, the ticks and the labels. + int height = thumbHeight; + + if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 + || slider.getMinorTickSpacing() > 0) + height += tickHeight; + + if (slider.getPaintLabels()) + height += getHeightOfTallestLabel(); + + height += insets.top + insets.bottom + focusInsets.top + + focusInsets.bottom; + + return new Dimension(width, height); + } + + /** + * This method returns the preferred size when the slider is vertically + * oriented. + * + * @return The dimensions of the preferred vertical size. + */ + public Dimension getPreferredVerticalSize() + { + Insets insets = slider.getInsets(); + + int height = getHeightOfTallestLabel() * (slider.getLabelTable() == null + ? 0 : slider.getLabelTable() + .size()); + + if (height < 200) + height = 200; + + height += insets.top + insets.bottom + focusInsets.top + + focusInsets.bottom; + + int width = thumbHeight; + + if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 + || slider.getMinorTickSpacing() > 0) + width += tickHeight; + + if (slider.getPaintLabels()) + width += getWidthOfWidestLabel(); + + width += insets.left + insets.right + focusInsets.left + focusInsets.right; + + return new Dimension(width, height); + } + + /** + * This method returns the minimum size when the slider is horizontally + * oriented. + * + * @return The dimensions of the minimum horizontal size. + */ + public Dimension getMinimumHorizontalSize() + { + return getPreferredHorizontalSize(); + } + + /** + * This method returns the minimum size of the slider when it is vertically + * oriented. + * + * @return The dimensions of the minimum vertical size. + */ + public Dimension getMinimumVerticalSize() + { + return getPreferredVerticalSize(); + } + + /** + * This method returns the preferred size of the component. If it returns + * null, then it is up to the Layout Manager to give the {@link JComponent} + * a size. + * + * @param c The {@link JComponent} to find the preferred size for. + * + * @return The dimensions of the preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method returns the minimum size for this {@link JSlider} for this + * look and feel. If it returns null, then it is up to the Layout Manager + * to give the {@link JComponent} a size. + * + * @param c The {@link JComponent} to find the minimum size for. + * + * @return The dimensions of the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method returns the maximum size for this {@link JSlider} for this + * look and feel. If it returns null, then it is up to the Layout Manager + * to give the {@link JComponent} a size. + * + * @param c The {@link JComponent} to find a maximum size for. + * + * @return The dimensions of the maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method calculates all the sizes of the rectangles by delegating to + * the helper methods calculateXXXRect. + */ + protected void calculateGeometry() + { + calculateFocusRect(); + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateTickRect(); + calculateLabelRect(); + calculateThumbLocation(); + } + + /** + * This method calculates the size and position of the focusRect. This + * method does not need to be called if the orientation changes. + */ + protected void calculateFocusRect() + { + insetCache = slider.getInsets(); + focusRect = SwingUtilities.calculateInnerArea(slider, focusRect); + + if (focusRect.width < 0) + focusRect.width = 0; + if (focusRect.height < 0) + focusRect.height = 0; + } + + /** + * This method calculates the size but not the position of the thumbRect. It + * must take into account the orientation of the slider. + */ + protected void calculateThumbSize() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + if (thumbWidth > contentRect.width) + thumbRect.width = contentRect.width / 4; + else + thumbRect.width = thumbWidth; + if (thumbHeight > contentRect.height) + thumbRect.height = contentRect.height; + else + thumbRect.height = thumbHeight; + } + else + { + // The thumb gets flipped when inverted, so thumbWidth + // actually is the height and vice versa. + if (thumbWidth > contentRect.height) + thumbRect.height = contentRect.height / 4; + else + thumbRect.height = thumbWidth; + if (thumbHeight > contentRect.width) + thumbRect.width = contentRect.width; + else + thumbRect.width = thumbHeight; + } + } + + /** + * This method calculates the size and position of the contentRect. This + * method does not need to be called if the orientation changes. + */ + protected void calculateContentRect() + { + contentRect.x = focusRect.x + focusInsets.left; + contentRect.y = focusRect.y + focusInsets.top; + contentRect.width = focusRect.width - focusInsets.left - focusInsets.right; + contentRect.height = focusRect.height - focusInsets.top + - focusInsets.bottom; + + if (contentRect.width < 0) + contentRect.width = 0; + if (contentRect.height < 0) + contentRect.height = 0; + } + + /** + * Calculates the position of the thumbRect based on the current value of + * the slider. It must take into account the orientation of the slider. + */ + protected void calculateThumbLocation() + { + int value = slider.getValue(); + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + thumbRect.x = xPositionForValue(value) - thumbRect.width / 2; + thumbRect.y = contentRect.y; + } + else + { + thumbRect.x = contentRect.x; + thumbRect.y = yPositionForValue(value) - thumbRect.height / 2; + } + } + + /** + * Calculates the gap size between the left edge of the contentRect and the + * left edge of the trackRect. + */ + protected void calculateTrackBuffer() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + trackBuffer = thumbRect.width; + else + trackBuffer = thumbRect.height; + } + + /** + * This method returns the size of the thumbRect. + * + * @return The dimensions of the thumb. + */ + protected Dimension getThumbSize() + { + // This is really just the bounds box for the thumb. + // The thumb will actually be pointed (like a rectangle + triangle at bottom) + return thumbRect.getSize(); + } + + /** + * Calculates the size and position of the trackRect. It must take into + * account the orientation of the slider. + */ + protected void calculateTrackRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + trackRect.x = contentRect.x + trackBuffer; + trackRect.y = contentRect.y; + trackRect.width = contentRect.width - 2 * trackBuffer; + trackRect.height = thumbRect.height; + } + else + { + trackRect.x = contentRect.x; + trackRect.y = contentRect.y + trackBuffer; + trackRect.width = thumbRect.width; + trackRect.height = contentRect.height - 2 * trackBuffer; + } + } + + /** + * This method returns the height of the tick area box if the slider is + * horizontal and the width of the tick area box is the slider is vertical. + * It not necessarily how long the ticks will be. If a gap between the edge + * of tick box and the actual tick is desired, then that will need to be + * handled in the tick painting methods. + * + * @return The height (or width if the slider is vertical) of the tick + * rectangle. + */ + protected int getTickLength() + { + return tickHeight; + } + + /** + * This method calculates the size and position of the tickRect. It must + * take into account the orientation of the slider. + */ + protected void calculateTickRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + tickRect.x = trackRect.x; + tickRect.y = trackRect.y + trackRect.height; + tickRect.width = trackRect.width; + tickRect.height = getTickLength(); + + if (tickRect.y + tickRect.height > contentRect.y + contentRect.height) + tickRect.height = contentRect.y + contentRect.height - tickRect.y; + } + else + { + tickRect.x = trackRect.x + trackRect.width; + tickRect.y = trackRect.y; + tickRect.width = getTickLength(); + tickRect.height = trackRect.height; + + if (tickRect.x + tickRect.width > contentRect.x + contentRect.width) + tickRect.width = contentRect.x + contentRect.width - tickRect.x; + } + } + + /** + * This method calculates the size and position of the labelRect. It must + * take into account the orientation of the slider. + */ + protected void calculateLabelRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + labelRect.x = contentRect.x; + labelRect.y = tickRect.y + tickRect.height; + labelRect.width = contentRect.width; + labelRect.height = contentRect.height - labelRect.y; + } + else + { + labelRect.x = tickRect.x + tickRect.width; + labelRect.y = contentRect.y; + labelRect.width = contentRect.width - labelRect.x; + labelRect.height = contentRect.height; + } + } + + /** + * This method returns the width of the widest label in the slider's label + * table. + * + * @return The width of the widest label or 0 if no label table exists. + */ + protected int getWidthOfWidestLabel() + { + int widest = 0; + Component label; + + if (slider.getLabelTable() == null) + return 0; + + Dimension pref; + for (Enumeration list = slider.getLabelTable().elements(); + list.hasMoreElements();) + { + Object comp = list.nextElement(); + if (! (comp instanceof Component)) + continue; + label = (Component) comp; + pref = label.getPreferredSize(); + if (pref != null && pref.width > widest) + widest = pref.width; + } + return widest; + } + + /** + * This method returns the height of the tallest label in the slider's label + * table. + * + * @return The height of the tallest label or 0 if no label table exists. + */ + protected int getHeightOfTallestLabel() + { + int tallest = 0; + Component label; + + if (slider.getLabelTable() == null) + return 0; + Dimension pref; + for (Enumeration list = slider.getLabelTable().elements(); + list.hasMoreElements();) + { + Object comp = list.nextElement(); + if (! (comp instanceof Component)) + continue; + label = (Component) comp; + pref = label.getPreferredSize(); + if (pref != null && pref.height > tallest) + tallest = pref.height; + } + return tallest; + } + + /** + * This method returns the width of the label whose key has the highest + * value. + * + * @return The width of the high value label or 0 if no label table exists. + */ + protected int getWidthOfHighValueLabel() + { + Component highValueLabel = getHighestValueLabel(); + if (highValueLabel != null) + return highValueLabel.getWidth(); + else + return 0; + } + + /** + * This method returns the width of the label whose key has the lowest + * value. + * + * @return The width of the low value label or 0 if no label table exists. + */ + protected int getWidthOfLowValueLabel() + { + Component lowValueLabel = getLowestValueLabel(); + if (lowValueLabel != null) + return lowValueLabel.getWidth(); + else + return 0; + } + + /** + * This method returns the height of the label whose key has the highest + * value. + * + * @return The height of the high value label or 0 if no label table exists. + */ + protected int getHeightOfHighValueLabel() + { + Component highValueLabel = getHighestValueLabel(); + if (highValueLabel != null) + return highValueLabel.getHeight(); + else + return 0; + } + + /** + * This method returns the height of the label whose key has the lowest + * value. + * + * @return The height of the low value label or 0 if no label table exists. + */ + protected int getHeightOfLowValueLabel() + { + Component lowValueLabel = getLowestValueLabel(); + if (lowValueLabel != null) + return lowValueLabel.getHeight(); + else + return 0; + } + + /** + * This method returns whether the slider is to be drawn inverted. + * + * @return True is the slider is to be drawn inverted. + */ + protected boolean drawInverted() + { + return ! (slider.getInverted() ^ leftToRightCache); + } + + /** + * This method returns the label whose key has the lowest value. + * + * @return The low value label or null if no label table exists. + */ + protected Component getLowestValueLabel() + { + Integer key = new Integer(Integer.MAX_VALUE); + Integer tmpKey; + Dictionary labelTable = slider.getLabelTable(); + + if (labelTable == null) + return null; + + for (Enumeration list = labelTable.keys(); list.hasMoreElements();) + { + Object value = list.nextElement(); + if (! (value instanceof Integer)) + continue; + tmpKey = (Integer) value; + if (tmpKey.intValue() < key.intValue()) + key = tmpKey; + } + Object comp = labelTable.get(key); + if (! (comp instanceof Component)) + return null; + return (Component) comp; + } + + /** + * This method returns the label whose key has the highest value. + * + * @return The high value label or null if no label table exists. + */ + protected Component getHighestValueLabel() + { + Integer key = new Integer(Integer.MIN_VALUE); + Integer tmpKey; + Dictionary labelTable = slider.getLabelTable(); + + if (labelTable == null) + return null; + + for (Enumeration list = labelTable.keys(); list.hasMoreElements();) + { + Object value = list.nextElement(); + if (! (value instanceof Integer)) + continue; + tmpKey = (Integer) value; + if (tmpKey.intValue() > key.intValue()) + key = tmpKey; + } + Object comp = labelTable.get(key); + if (! (comp instanceof Component)) + return null; + return (Component) comp; + } + + /** + * This method is used to paint the {@link JSlider}. It delegates all its + * duties to the various paint methods like paintTicks(), paintTrack(), + * paintThumb(), etc. + * + * @param g The {@link Graphics} object to paint with. + * @param c The {@link JComponent} that is being painted. + */ + public void paint(Graphics g, JComponent c) + { + // 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(); + + if (slider.getPaintTrack()) + paintTrack(g); + if (slider.getPaintTicks()) + paintTicks(g); + if (slider.getPaintLabels()) + paintLabels(g); + + //FIXME: Paint focus. + paintThumb(g); + } + + /** + * This method recalculates any rectangles that need to be recalculated + * after the insets of the component have changed. + */ + protected void recalculateIfInsetsChanged() + { + // Examining a test program shows that either Sun calls private + // methods that we don't know about, or these don't do anything. + calculateFocusRect(); + + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + + /** + * This method recalculates any rectangles that need to be recalculated + * after the orientation of the slider changes. + */ + protected void recalculateIfOrientationChanged() + { + // Examining a test program shows that either Sun calls private + // methods that we don't know about, or these don't do anything. + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + + /** + * This method is called during a repaint if the slider has focus. It draws + * an outline of the focusRect using the color returned by + * getFocusColor(). + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintFocus(Graphics g) + { + Color saved_color = g.getColor(); + + g.setColor(getFocusColor()); + + g.drawRect(focusRect.x, focusRect.y, focusRect.width, focusRect.height); + + g.setColor(saved_color); + } + + /** + *

+ * This method is called during a repaint if the track is to be drawn. It + * draws a 3D rectangle to represent the track. The track is not the size + * of the trackRect. The top and left edges of the track should be outlined + * with the shadow color. The bottom and right edges should be outlined + * with the highlight color. + *

+ *
+   *    a---d   
+   *    |   |   
+   *    |   |   a------------------------d
+   *    |   |   |                        |
+   *    |   |   b------------------------c
+   *    |   |
+   *    |   |   
+   *    b---c
+   * 
+ * + *

+ * The b-a-d path needs to be drawn with the shadow color and the b-c-d path + * needs to be drawn with the highlight color. + *

+ * + * @param g The {@link Graphics} object to draw with. + */ + public void paintTrack(Graphics g) + { + Color saved_color = g.getColor(); + int width; + int height; + + Point a = new Point(trackRect.x, trackRect.y); + Point b = new Point(a); + Point c = new Point(a); + Point d = new Point(a); + + Polygon high; + Polygon shadow; + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + width = trackRect.width; + height = (thumbRect.height / 4 == 0) ? 1 : thumbRect.height / 4; + + a.translate(0, (trackRect.height / 2) - (height / 2)); + b.translate(0, (trackRect.height / 2) + (height / 2)); + c.translate(trackRect.width, (trackRect.height / 2) + (height / 2)); + d.translate(trackRect.width, (trackRect.height / 2) - (height / 2)); + } + else + { + width = (thumbRect.width / 4 == 0) ? 1 : thumbRect.width / 4; + height = trackRect.height; + + a.translate((trackRect.width / 2) - (width / 2), 0); + b.translate((trackRect.width / 2) - (width / 2), trackRect.height); + c.translate((trackRect.width / 2) + (width / 2), trackRect.height); + d.translate((trackRect.width / 2) + (width / 2), 0); + } + g.setColor(Color.GRAY); + g.fillRect(a.x, a.y, width, height); + + g.setColor(getHighlightColor()); + g.drawLine(b.x, b.y, c.x, c.y); + g.drawLine(c.x, c.y, d.x, d.y); + + g.setColor(getShadowColor()); + g.drawLine(b.x, b.y, a.x, a.y); + g.drawLine(a.x, a.y, d.x, d.y); + + g.setColor(saved_color); + } + + /** + * This method is called during a repaint if the ticks are to be drawn. This + * method must still verify that the majorTickSpacing and minorTickSpacing + * are greater than zero before drawing the ticks. + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintTicks(Graphics g) + { + int max = slider.getMaximum(); + int min = slider.getMinimum(); + int majorSpace = slider.getMajorTickSpacing(); + int minorSpace = slider.getMinorTickSpacing(); + + if (majorSpace > 0) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + double loc = tickRect.x; + double increment = (max == min) ? 0 + : majorSpace * (double) tickRect.width / (max + - min); + if (drawInverted()) + { + loc += tickRect.width; + increment *= -1; + } + for (int i = min; i <= max; i += majorSpace) + { + paintMajorTickForHorizSlider(g, tickRect, (int) loc); + loc += increment; + } + } + else + { + double loc = tickRect.height + tickRect.y; + double increment = (max == min) ? 0 + : -majorSpace * (double) tickRect.height / (max + - min); + if (drawInverted()) + { + loc = tickRect.y; + increment *= -1; + } + for (int i = min; i <= max; i += majorSpace) + { + paintMajorTickForVertSlider(g, tickRect, (int) loc); + loc += increment; + } + } + } + if (minorSpace > 0) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + double loc = tickRect.x; + double increment = (max == min) ? 0 + : minorSpace * (double) tickRect.width / (max + - min); + if (drawInverted()) + { + loc += tickRect.width; + increment *= -1; + } + for (int i = min; i <= max; i += minorSpace) + { + paintMinorTickForHorizSlider(g, tickRect, (int) loc); + loc += increment; + } + } + else + { + double loc = tickRect.height + tickRect.y; + double increment = (max == min) ? 0 + : -minorSpace * (double) tickRect.height / (max + - min); + if (drawInverted()) + { + loc = tickRect.y; + increment *= -1; + } + for (int i = min; i <= max; i += minorSpace) + { + paintMinorTickForVertSlider(g, tickRect, (int) loc); + loc += increment; + } + } + } + } + + /* Minor ticks start at 1/4 of the height (or width) of the tickRect and extend + to 1/2 of the tickRect. + + Major ticks start at 1/4 of the height and extend to 3/4. + */ + + /** + * This method paints a minor tick for a horizontal slider at the given x + * value. x represents the x coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param x The x coordinate to draw the tick at. + */ + protected void paintMinorTickForHorizSlider(Graphics g, + Rectangle tickBounds, int x) + { + int y = tickRect.y + tickRect.height / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x, y + tickRect.height / 4); + g.setColor(saved); + } + + /** + * This method paints a major tick for a horizontal slider at the given x + * value. x represents the x coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param x The x coordinate to draw the tick at. + */ + protected void paintMajorTickForHorizSlider(Graphics g, + Rectangle tickBounds, int x) + { + int y = tickRect.y + tickRect.height / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x, y + tickRect.height / 2); + g.setColor(saved); + } + + /** + * This method paints a minor tick for a vertical slider at the given y + * value. y represents the y coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param y The y coordinate to draw the tick at. + */ + protected void paintMinorTickForVertSlider(Graphics g, Rectangle tickBounds, + int y) + { + int x = tickRect.x + tickRect.width / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x + tickRect.width / 4, y); + g.setColor(saved); + } + + /** + * This method paints a major tick for a vertical slider at the given y + * value. y represents the y coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param y The y coordinate to draw the tick at. + */ + protected void paintMajorTickForVertSlider(Graphics g, Rectangle tickBounds, + int y) + { + int x = tickRect.x + tickRect.width / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x + tickRect.width / 2, y); + g.setColor(saved); + } + + /** + * This method paints all the labels from the slider's label table. This + * method must make sure that the label table is not null before painting + * the labels. Each entry in the label table is a (integer, component) + * pair. Every label is painted at the value of the integer. + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintLabels(Graphics g) + { + if (slider.getLabelTable() != null) + { + Dictionary table = slider.getLabelTable(); + Integer tmpKey; + Object key; + Object element; + Component label; + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + for (Enumeration list = table.keys(); list.hasMoreElements();) + { + key = list.nextElement(); + if (! (key instanceof Integer)) + continue; + tmpKey = (Integer) key; + element = table.get(tmpKey); + // We won't paint them if they're not + // JLabels so continue anyway + if (! (element instanceof JLabel)) + continue; + label = (Component) element; + paintHorizontalLabel(g, tmpKey.intValue(), label); + } + } + else + { + for (Enumeration list = table.keys(); list.hasMoreElements();) + { + key = list.nextElement(); + if (! (key instanceof Integer)) + continue; + tmpKey = (Integer) key; + element = table.get(tmpKey); + // We won't paint them if they're not + // JLabels so continue anyway + if (! (element instanceof JLabel)) + continue; + label = (Component) element; + paintVerticalLabel(g, tmpKey.intValue(), label); + } + } + } + } + + /** + * This method paints the label on the horizontal slider at the value + * specified. The value is not a coordinate. It is a value within the range + * of the slider. If the value is not within the range of the slider, this + * method will do nothing. This method should not paint outside the + * boundaries of the labelRect. + * + * @param g The {@link Graphics} object to draw with. + * @param value The value to paint at. + * @param label The label to paint. + */ + protected void paintHorizontalLabel(Graphics g, int value, Component label) + { + // This relies on clipping working properly or we'll end up + // painting all over the place. If our preferred size is ignored, then + // the labels may not fit inside the slider's bounds. Rather than mucking + // with font sizes and possible icon sizes, we'll set the bounds for + // the label and let it get clipped. + Dimension dim = label.getPreferredSize(); + int w = (int) dim.getWidth(); + int h = (int) dim.getHeight(); + + int max = slider.getMaximum(); + int min = slider.getMinimum(); + + if (value > max || value < min) + return; + + // value + // | + // ------------ + // | | + // | | + // | | + // The label must move w/2 to the right to fit directly under the value. + int xpos = xPositionForValue(value) - w / 2; + int ypos = labelRect.y; + + // We want to center the label around the xPositionForValue + // So we use xpos - w / 2. However, if value is min and the label + // is large, we run the risk of going out of bounds. So we bring it back + // to 0 if it becomes negative. + if (xpos < 0) + xpos = 0; + + // If the label + starting x position is greater than + // the x space in the label rectangle, we reset it to the largest + // amount possible in the rectangle. This means ugliness. + if (xpos + w > labelRect.x + labelRect.width) + w = labelRect.x + labelRect.width - xpos; + + // If the label is too tall. We reset it to the height of the label + // rectangle. + if (h > labelRect.height) + h = labelRect.height; + + label.setBounds(xpos, ypos, w, h); + javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds()); + } + + /** + * This method paints the label on the vertical slider at the value + * specified. The value is not a coordinate. It is a value within the range + * of the slider. If the value is not within the range of the slider, this + * method will do nothing. This method should not paint outside the + * boundaries of the labelRect. + * + * @param g The {@link Graphics} object to draw with. + * @param value The value to paint at. + * @param label The label to paint. + */ + protected void paintVerticalLabel(Graphics g, int value, Component label) + { + Dimension dim = label.getPreferredSize(); + int w = (int) dim.getWidth(); + int h = (int) dim.getHeight(); + + int max = slider.getMaximum(); + int min = slider.getMinimum(); + + if (value > max || value < min) + return; + + int xpos = labelRect.x; + int ypos = yPositionForValue(value) - h / 2; + + if (ypos < 0) + ypos = 0; + + if (ypos + h > labelRect.y + labelRect.height) + h = labelRect.y + labelRect.height - ypos; + + if (w > labelRect.width) + w = labelRect.width; + + label.setBounds(xpos, ypos, w, h); + javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds()); + } + + /** + *

+ * This method paints a thumb. There are two types of thumb: + *

+ *
+   *   Vertical         Horizontal
+   *    a---b            a-----b
+   *    |   |            |      \
+   *    e   c            |       c
+   *     \ /             |      /
+   *      d              e-----d
+   *  
+ * + *

+ * In the case of vertical thumbs, we highlight the path b-a-e-d and shadow + * the path b-c-d. In the case of horizontal thumbs, we highlight the path + * c-b-a-e and shadow the path c-d-e. In both cases we fill the path + * a-b-c-d-e before shadows and highlights are drawn. + *

+ * + * @param g The graphics object to paint with + */ + public void paintThumb(Graphics g) + { + Color saved_color = g.getColor(); + + Polygon thumb = new Polygon(); + + Point a = new Point(thumbRect.x, thumbRect.y); + Point b = new Point(a); + Point c = new Point(a); + Point d = new Point(a); + Point e = new Point(a); + + Polygon bright; + Polygon dark; + Polygon all; + + // This will be in X-dimension if the slider is inverted and y if it isn't. + int turnPoint; + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + turnPoint = thumbRect.height * 3 / 4; + + b.translate(thumbRect.width, 0); + c.translate(thumbRect.width, turnPoint); + d.translate(thumbRect.width / 2, thumbRect.height); + e.translate(0, turnPoint); + + bright = new Polygon(new int[] { b.x, a.x, e.x, d.x }, + new int[] { b.y, a.y, e.y, d.y }, 4); + + dark = new Polygon(new int[] { b.x, c.x, d.x }, + new int[] { b.y, c.y, d.y }, 3); + all = new Polygon(new int[] { a.x + 1, b.x, c.x, d.x, e.x + 1 }, + new int[] { a.y + 1, b.y + 1, c.y, d.y + 1, e.y }, 5); + } + else + { + turnPoint = thumbRect.width * 3 / 4; + + b.translate(turnPoint, 0); + c.translate(thumbRect.width, thumbRect.height / 2); + d.translate(turnPoint, thumbRect.height); + e.translate(0, thumbRect.height); + + bright = new Polygon(new int[] { c.x, b.x, a.x, e.x }, + new int[] { c.y, b.y, a.y, e.y }, 4); + + dark = new Polygon(new int[] { c.x, d.x, e.x + 1 }, + new int[] { c.y, d.y, e.y }, 3); + + all = new Polygon(new int[] { a.x + 1, b.x, c.x - 1, d.x, e.x + 1 }, + new int[] { a.y + 1, b.y + 1, c.y, d.y, e.y }, 5); + } + + g.setColor(Color.WHITE); + g.drawPolyline(bright.xpoints, bright.ypoints, bright.npoints); + + g.setColor(Color.BLACK); + g.drawPolyline(dark.xpoints, dark.ypoints, dark.npoints); + + g.setColor(Color.GRAY); + g.fillPolygon(all); + + g.setColor(saved_color); + } + + /** + * This method sets the position of the thumbRect. + * + * @param x The new x position. + * @param y The new y position. + */ + public void setThumbLocation(int x, int y) + { + thumbRect.x = x; + thumbRect.y = y; + } + + /** + * This method is used to move the thumb one block in the direction + * specified. If the slider snaps to ticks, this method is responsible for + * snapping it to a tick after the thumb has been moved. + * + * @param direction The direction to move in. + */ + public void scrollByBlock(int direction) + { + // The direction is -1 for backwards and 1 for forwards. + int unit = direction * (slider.getMaximum() - slider.getMinimum()) / 10; + + int moveTo = slider.getValue() + unit; + + if (slider.getSnapToTicks()) + moveTo = findClosestTick(moveTo); + + slider.setValue(moveTo); + } + + /** + * This method is used to move the thumb one unit in the direction + * specified. If the slider snaps to ticks, this method is responsible for + * snapping it to a tick after the thumb has been moved. + * + * @param direction The direction to move in. + */ + public void scrollByUnit(int direction) + { + // The direction is -1 for backwards and 1 for forwards. + int moveTo = slider.getValue() + direction; + + if (slider.getSnapToTicks()) + moveTo = findClosestTick(moveTo); + + slider.setValue(moveTo); + } + + /** + * This method is called when there has been a click in the track and the + * thumb needs to be scrolled on regular intervals. This method is only + * responsible for starting the timer and not for stopping it. + * + * @param dir The direction to move in. + */ + protected void scrollDueToClickInTrack(int dir) + { + scrollTimer.stop(); + + scrollListener.setDirection(dir); + scrollListener.setScrollByBlock(true); + + scrollTimer.start(); + } + + /** + * This method returns the X coordinate for the value passed in. + * + * @param value The value to calculate an x coordinate for. + * + * @return The x coordinate for the value. + */ + protected int xPositionForValue(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int extent = slider.getExtent(); + int len = trackRect.width; + + int xPos = (max == min) ? 0 : (value - min) * len / (max - min); + + if (! drawInverted()) + xPos += trackRect.x; + else + { + xPos = trackRect.width - xPos; + xPos += trackRect.x; + } + return xPos; + } + + /** + * This method returns the y coordinate for the value passed in. + * + * @param value The value to calculate a y coordinate for. + * + * @return The y coordinate for the value. + */ + protected int yPositionForValue(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int extent = slider.getExtent(); + int len = trackRect.height; + + int yPos = (max == min) ? 0 : (value - min) * len / (max - min); + + if (! drawInverted()) + { + yPos = trackRect.height - yPos; + yPos += trackRect.y; + } + else + yPos += trackRect.y; + return yPos; + } + + /** + * This method returns the value in the slider's range given the y + * coordinate. If the value is out of range, it will return the closest + * legal value. + * + * @param yPos The y coordinate to calculate a value for. + * + * @return The value for the y coordinate. + */ + public int valueForYPosition(int yPos) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int len = trackRect.height; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + if (! drawInverted()) + value = ((len - (yPos - trackRect.y)) * (max - min) / len + min); + else + value = ((yPos - trackRect.y) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method returns the value in the slider's range given the x + * coordinate. If the value is out of range, it will return the closest + * legal value. + * + * @param xPos The x coordinate to calculate a value for. + * + * @return The value for the x coordinate. + */ + public int valueForXPosition(int xPos) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int len = trackRect.width; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + if (! drawInverted()) + value = ((xPos - trackRect.x) * (max - min) / len + min); + else + value = ((len - (xPos - trackRect.x)) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method finds the closest value that has a tick associated with it. + * This is package-private to avoid an accessor method. + * + * @param value The value to search from. + * + * @return The closest value that has a tick associated with it. + */ + int findClosestTick(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int majorSpace = slider.getMajorTickSpacing(); + int minorSpace = slider.getMinorTickSpacing(); + + // The default value to return is value + minor or + // value + major. + // Initializing at min - value leaves us with a default + // return value of min, which always has tick marks + // (if ticks are painted). + int minor = min - value; + int major = min - value; + + // If there are no major tick marks or minor tick marks + // e.g. snap is set to true but no ticks are set, then + // we can just return the value. + if (majorSpace <= 0 && minorSpace <= 0) + return value; + + // First check the major ticks. + if (majorSpace > 0) + { + int lowerBound = (value - min) / majorSpace; + int majLower = majorSpace * lowerBound + min; + int majHigher = majorSpace * (lowerBound + 1) + min; + + if (majHigher <= max && majHigher - value <= value - majLower) + major = majHigher - value; + else + major = majLower - value; + } + + if (minorSpace > 0) + { + int lowerBound = value / minorSpace; + int minLower = minorSpace * lowerBound; + int minHigher = minorSpace * (lowerBound + 1); + + if (minHigher <= max && minHigher - value <= value - minLower) + minor = minHigher - value; + else + minor = minLower - value; + } + + // Give preference to minor ticks + if (Math.abs(minor) > Math.abs(major)) + return value + major; + else + return value + minor; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java new file mode 100644 index 0000000..97ab97b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -0,0 +1,574 @@ +/* SpinnerUI.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JSpinner; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SpinnerUI; + +/** + * DOCUMENT ME! + * + * @author Ka-Hing Cheung + * + * @see javax.swing.JSpinner + * @since 1.4 + */ +public class BasicSpinnerUI extends SpinnerUI +{ + /** + * Creates a new ComponentUI for the specified + * JComponent + * + * @param c DOCUMENT ME! + * + * @return a ComponentUI + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicSpinnerUI(); + } + + /** + * Creates an editor component. Really, it just returns + * JSpinner.getEditor() + * + * @return a JComponent as an editor + * + * @see javax.swing.JSpinner#getEditor + */ + protected JComponent createEditor() + { + return spinner.getEditor(); + } + + /** + * Creates a LayoutManager that layouts the sub components. The + * subcomponents are identifies by the constraint "Next", "Previous" and + * "Editor" + * + * @return a LayoutManager + * + * @see java.awt.LayoutManager + */ + protected LayoutManager createLayout() + { + return new DefaultLayoutManager(); + } + + /** + * Creates the "Next" button + * + * @return the next button component + */ + protected Component createNextButton() + { + JButton button = new BasicArrowButton(BasicArrowButton.NORTH); + return button; + } + + /** + * Creates the "Previous" button + * + * @return the previous button component + */ + protected Component createPreviousButton() + { + JButton button = new BasicArrowButton(BasicArrowButton.SOUTH); + return button; + } + + /** + * Creates the PropertyChangeListener that will be attached by + * installListeners. It should watch for the "editor" + * property, when it's changed, replace the old editor with the new one, + * probably by calling replaceEditor + * + * @return a PropertyChangeListener + * + * @see #replaceEditor + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + // FIXME: Add check for enabled property change. Need to + // disable the buttons. + if ("editor".equals(evt.getPropertyName())) + BasicSpinnerUI.this.replaceEditor((JComponent) evt.getOldValue(), + (JComponent) evt.getNewValue()); + } + }; + } + + /** + * Called by installUI. This should set various defaults + * obtained from UIManager.getLookAndFeelDefaults, as well as + * set the layout obtained from createLayout + * + * @see javax.swing.UIManager#getLookAndFeelDefaults + * @see #createLayout + * @see #installUI + */ + 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")); + */ + spinner.setLayout(createLayout()); + spinner.setOpaque(true); + } + + /* + * Called by installUI, which basically adds the + * PropertyChangeListener created by + * createPropertyChangeListener + * + * @see #createPropertyChangeListener + * @see #installUI + */ + protected void installListeners() + { + spinner.addPropertyChangeListener(listener); + } + + /* + * Install listeners to the next button so that it increments the model + */ + protected void installNextButtonListeners(Component c) + { + c.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent evt) + { + if (! spinner.isEnabled()) + return; + increment(); + timer.setInitialDelay(500); + timer.start(); + } + + public void mouseReleased(MouseEvent evt) + { + timer.stop(); + } + + void increment() + { + Object next = BasicSpinnerUI.this.spinner.getNextValue(); + if (next != null) + BasicSpinnerUI.this.spinner.getModel().setValue(next); + } + + volatile boolean mouseDown = false; + Timer timer = new Timer(50, + new ActionListener() + { + public void actionPerformed(ActionEvent event) + { + increment(); + } + }); + }); + } + + /* + * Install listeners to the previous button so that it decrements the model + */ + protected void installPreviousButtonListeners(Component c) + { + c.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent evt) + { + if (! spinner.isEnabled()) + return; + decrement(); + timer.setInitialDelay(500); + timer.start(); + } + + public void mouseReleased(MouseEvent evt) + { + timer.stop(); + } + + void decrement() + { + Object prev = BasicSpinnerUI.this.spinner.getPreviousValue(); + if (prev != null) + BasicSpinnerUI.this.spinner.getModel().setValue(prev); + } + + volatile boolean mouseDown = false; + Timer timer = new Timer(50, + new ActionListener() + { + public void actionPerformed(ActionEvent event) + { + decrement(); + } + }); + }); + } + + /** + * Install this UI to the JComponent, which in reality, is a + * JSpinner. Calls installDefaults, + * installListeners, and also adds the buttons and editor. + * + * @param c DOCUMENT ME! + * + * @see #installDefaults + * @see #installListeners + * @see #createNextButton + * @see #createPreviousButton + * @see #createEditor + */ + public void installUI(JComponent c) + { + super.installUI(c); + + spinner = (JSpinner) c; + + installDefaults(); + installListeners(); + + Component next = createNextButton(); + Component previous = createPreviousButton(); + + installNextButtonListeners(next); + installPreviousButtonListeners(previous); + + c.add(createEditor(), "Editor"); + c.add(next, "Next"); + c.add(previous, "Previous"); + } + + /** + * Replace the old editor with the new one + * + * @param oldEditor the old editor + * @param newEditor the new one to replace with + */ + protected void replaceEditor(JComponent oldEditor, JComponent newEditor) + { + spinner.remove(oldEditor); + spinner.add(newEditor); + } + + /** + * The reverse of installDefaults. Called by + * uninstallUI + */ + protected void uninstallDefaults() + { + spinner.setLayout(null); + } + + /** + * The reverse of installListeners, called by + * uninstallUI + */ + protected void uninstallListeners() + { + spinner.removePropertyChangeListener(listener); + } + + /** + * Called when the current L&F is replaced with another one, should call + * uninstallDefaults and uninstallListeners as + * well as remove the next/previous buttons and the editor + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + + uninstallDefaults(); + uninstallListeners(); + c.removeAll(); + } + + /** The spinner for this UI */ + protected JSpinner spinner; + + /** DOCUMENT ME! */ + private PropertyChangeListener listener = createPropertyChangeListener(); + + /** + * DOCUMENT ME! + */ + private class DefaultLayoutManager implements LayoutManager + { + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + */ + public void layoutContainer(Container parent) + { + synchronized (parent.getTreeLock()) + { + Insets i = parent.getInsets(); + boolean l2r = parent.getComponentOrientation().isLeftToRight(); + /* + -------------- -------------- + | | n | | n | | + | e | - | or | - | e | + | | p | | p | | + -------------- -------------- + */ + Dimension e = minSize(editor); + Dimension n = minSize(next); + Dimension p = minSize(previous); + Dimension s = spinner.getPreferredSize(); + + int x = l2r ? i.left : i.right; + int y = i.top; + int w = Math.max(p.width, n.width); + int h = Math.max(p.height, n.height); + h = Math.max(h, e.height / 2); + int e_width = s.width - w; + + if (l2r) + { + setBounds(editor, x, y + (s.height - e.height) / 2, e_width, + e.height); + x += e_width; + + setBounds(next, x, y, w, h); + y += h; + + setBounds(previous, x, y, w, h); + } + else + { + setBounds(next, x, y + (s.height - e.height) / 2, w, h); + y += h; + + setBounds(previous, x, y, w, h); + x += w; + y -= h; + + setBounds(editor, x, y, e_width, e.height); + } + } + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension minimumLayoutSize(Container parent) + { + Dimension d = new Dimension(); + + if (editor != null) + { + Dimension tmp = editor.getMinimumSize(); + d.width += tmp.width; + d.height = tmp.height; + } + + int nextWidth = 0; + int previousWidth = 0; + int otherHeight = 0; + + if (next != null) + { + Dimension tmp = next.getMinimumSize(); + nextWidth = tmp.width; + otherHeight += tmp.height; + } + if (previous != null) + { + Dimension tmp = previous.getMinimumSize(); + previousWidth = tmp.width; + otherHeight += tmp.height; + } + + d.height = Math.max(d.height, otherHeight); + d.width += Math.max(nextWidth, previousWidth); + + return d; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension preferredLayoutSize(Container parent) + { + Dimension d = new Dimension(); + + if (editor != null) + { + Dimension tmp = editor.getPreferredSize(); + d.width += Math.max(tmp.width, 40); + d.height = tmp.height; + } + + int nextWidth = 0; + int previousWidth = 0; + int otherHeight = 0; + + if (next != null) + { + Dimension tmp = next.getPreferredSize(); + nextWidth = tmp.width; + otherHeight += tmp.height; + } + if (previous != null) + { + Dimension tmp = previous.getPreferredSize(); + previousWidth = tmp.width; + otherHeight += tmp.height; + } + + d.height = Math.max(d.height, otherHeight); + d.width += Math.max(nextWidth, previousWidth); + + return d; + } + + /** + * DOCUMENT ME! + * + * @param child DOCUMENT ME! + */ + public void removeLayoutComponent(Component child) + { + if (child == editor) + editor = null; + else if (child == next) + next = null; + else if (previous == child) + previous = null; + } + + /** + * DOCUMENT ME! + * + * @param name DOCUMENT ME! + * @param child DOCUMENT ME! + */ + public void addLayoutComponent(String name, Component child) + { + if ("Editor".equals(name)) + editor = child; + else if ("Next".equals(name)) + next = child; + else if ("Previous".equals(name)) + previous = child; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private Dimension minSize(Component c) + { + if (c == null) + return new Dimension(); + else + return c.getMinimumSize(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param w DOCUMENT ME! + * @param h DOCUMENT ME! + */ + private void setBounds(Component c, int x, int y, int w, int h) + { + if (c != null) + c.setBounds(x, y, w, h); + } + + /** DOCUMENT ME! */ + private Component editor; + + /** DOCUMENT ME! */ + private Component next; + + /** DOCUMENT ME! */ + private Component previous; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java new file mode 100644 index 0000000..b8674ed --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -0,0 +1,912 @@ +/* BasicSplitPaneDivider.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JButton; +import javax.swing.JSplitPane; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +/** + * The divider that separates the two parts of a JSplitPane in the Basic look + * and feel. + * + *

+ * Implementation status: We do not have a real implementation yet. Currently, + * it is mostly a stub to allow compiling other parts of the + * javax.swing.plaf.basic package, although some parts are already + * functional. + *

+ * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ +public class BasicSplitPaneDivider extends Container + implements PropertyChangeListener +{ + /** + * Determined using the serialver tool of Apple/Sun JDK 1.3.1 + * on MacOS X 10.1.5. + */ + static final long serialVersionUID = 1463404307042803342L; + + /** + * The width and height of the little buttons for showing and hiding parts + * of a JSplitPane in a single mouse click. + */ + protected static final int ONE_TOUCH_SIZE = 6; + + /** The distance the one touch buttons will sit from the divider's edges. */ + protected static final int ONE_TOUCH_OFFSET = 2; + + /** + * An object that performs the tasks associated with an ongoing drag + * operation, or null if the user is currently not dragging + * the divider. + */ + protected DragController dragger; + + /** + * The delegate object that is responsible for the UI of the + * JSplitPane that contains this divider. + */ + protected BasicSplitPaneUI splitPaneUI; + + /** The thickness of the divider in pixels. */ + protected int dividerSize; + + /** A divider that is used for layout purposes. */ + protected Component hiddenDivider; + + /** The JSplitPane containing this divider. */ + protected JSplitPane splitPane; + + /** + * The listener for handling mouse events from both the divider and the + * containing JSplitPane. + * + *

+ * The reason for also handling MouseEvents from the containing + * JSplitPane is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + *

+ */ + protected MouseHandler mouseHandler = new MouseHandler(); + + /** + * The current orientation of the containing JSplitPane, which + * is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or {@link + * javax.swing.JSplitPane#VERTICAL_SPLIT}. + */ + protected int orientation; + + /** + * The button for showing and hiding the left (or top) component of the + * JSplitPane. + */ + protected JButton leftButton; + + /** + * The button for showing and hiding the right (or bottom) component of the + * JSplitPane. + */ + protected JButton rightButton; + + /** + * The border of this divider. Typically, this will be an instance of {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. + * + * @see #getBorder() + * @see #setBorder(javax.swing.border.Border) + */ + private Border border; + + // This is not a pixel count. + // This int should be able to take 3 values. + // left (top), middle, right(bottom) + // 0 1 2 + + /** + * Keeps track of where the divider should be placed when using one touch + * expand buttons. + * This is package-private to avoid an accessor method. + */ + transient int currentDividerLocation = 1; + + /** DOCUMENT ME! */ + private transient Border tmpBorder = new Border() + { + public Insets getBorderInsets(Component c) + { + return new Insets(2, 2, 2, 2); + } + + public boolean isBorderOpaque() + { + return false; + } + + public void paintBorder(Component c, Graphics g, int x, int y, + int width, int height) + { + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawRect(x + 2, y + 2, width - 4, height - 4); + + g.setColor(saved); + } + }; + + /** + * Constructs a new divider. + * + * @param ui the UI delegate of the enclosing JSplitPane. + */ + public BasicSplitPaneDivider(BasicSplitPaneUI ui) + { + setLayout(new DividerLayout()); + setBasicSplitPaneUI(ui); + setDividerSize(splitPane.getDividerSize()); + setBorder(tmpBorder); + } + + /** + * Sets the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. + * + * @param newUI the UI delegate, or null to release the + * connection to the current delegate. + */ + public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) + { + /* Remove the connection to the existing JSplitPane. */ + if (splitPane != null) + { + splitPane.removePropertyChangeListener(this); + splitPane.removeMouseListener(mouseHandler); + splitPane.removeMouseMotionListener(mouseHandler); + removeMouseListener(mouseHandler); + removeMouseMotionListener(mouseHandler); + splitPane = null; + hiddenDivider = null; + } + + /* Establish the connection to the new JSplitPane. */ + splitPaneUI = newUI; + if (splitPaneUI != null) + splitPane = newUI.getSplitPane(); + if (splitPane != null) + { + splitPane.addPropertyChangeListener(this); + splitPane.addMouseListener(mouseHandler); + splitPane.addMouseMotionListener(mouseHandler); + addMouseListener(mouseHandler); + addMouseMotionListener(mouseHandler); + hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider(); + orientation = splitPane.getOrientation(); + oneTouchExpandableChanged(); + } + } + + /** + * Returns the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. + * + * @return The UI for the JSplitPane. + */ + public BasicSplitPaneUI getBasicSplitPaneUI() + { + return splitPaneUI; + } + + /** + * Sets the thickness of the divider. + * + * @param newSize the new width or height in pixels. + */ + public void setDividerSize(int newSize) + { + this.dividerSize = newSize; + } + + /** + * Retrieves the thickness of the divider. + * + * @return The thickness of the divider. + */ + public int getDividerSize() + { + return dividerSize; + } + + /** + * Sets the border of this divider. + * + * @param border the new border. Typically, this will be an instance of + * {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneBorder}. + * + * @since 1.3 + */ + public void setBorder(Border border) + { + if (border != this.border) + { + Border oldValue = this.border; + this.border = border; + firePropertyChange("border", oldValue, border); + } + } + + /** + * Retrieves the border of this divider. + * + * @return the current border, or null if no border has been + * set. + * + * @since 1.3 + */ + public Border getBorder() + { + return border; + } + + /** + * Retrieves the insets of the divider. If a border has been installed on + * the divider, the result of calling its getBorderInsets + * method is returned. Otherwise, the inherited implementation will be + * invoked. + * + * @see javax.swing.border.Border#getBorderInsets(java.awt.Component) + */ + public Insets getInsets() + { + if (border != null) + return border.getBorderInsets(this); + else + return super.getInsets(); + } + + /** + * Returns the preferred size of this divider, which is + * dividerSize by dividerSize pixels. + * + * @return The preferred size of the divider. + */ + public Dimension getPreferredSize() + { + return getLayout().preferredLayoutSize(this); + } + + /** + * Returns the minimal size of this divider, which is + * dividerSize by dividerSize pixels. + * + * @return The minimal size of the divider. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * Processes events from the JSplitPane that contains this + * divider. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JSplitPane.ONE_TOUCH_EXPANDABLE_PROPERTY)) + oneTouchExpandableChanged(); + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + orientation = splitPane.getOrientation(); + if (splitPane.isOneTouchExpandable()) + { + layout(); + repaint(); + } + } + else if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + dividerSize = splitPane.getDividerSize(); + } + + /** + * Paints the divider by painting its border. + * + * @param g The Graphics Object to paint with. + */ + public void paint(Graphics g) + { + Dimension dividerSize; + + super.paint(g); + if (border != null) + { + dividerSize = getSize(); + border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height); + } + } + + /** + * Reacts to changes of the oneToughExpandable property of the + * containing JSplitPane. + */ + protected void oneTouchExpandableChanged() + { + if (splitPane.isOneTouchExpandable()) + { + leftButton = createLeftOneTouchButton(); + rightButton = createRightOneTouchButton(); + add(leftButton); + add(rightButton); + + leftButton.addMouseListener(mouseHandler); + rightButton.addMouseListener(mouseHandler); + + // Set it to 1. + currentDividerLocation = 1; + } + else + { + if (leftButton != null && rightButton != null) + { + leftButton.removeMouseListener(mouseHandler); + rightButton.removeMouseListener(mouseHandler); + + remove(leftButton); + remove(rightButton); + leftButton = null; + rightButton = null; + } + } + layout(); + repaint(); + } + + /** + * Creates a button for showing and hiding the left (or top) part of a + * JSplitPane. + * + * @return The left one touch button. + */ + protected JButton createLeftOneTouchButton() + { + int dir = SwingConstants.WEST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.NORTH; + JButton button = new BasicArrowButton(dir); + button.setBorder(null); + + return button; + } + + /** + * Creates a button for showing and hiding the right (or bottom) part of a + * JSplitPane. + * + * @return The right one touch button. + */ + protected JButton createRightOneTouchButton() + { + int dir = SwingConstants.EAST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.SOUTH; + JButton button = new BasicArrowButton(dir); + button.setBorder(null); + return button; + } + + /** + * Prepares the divider for dragging by calling the + * startDragging method of the UI delegate of the enclosing + * JSplitPane. + * + * @see BasicSplitPaneUI#startDragging() + */ + protected void prepareForDragging() + { + if (splitPaneUI != null) + splitPaneUI.startDragging(); + } + + /** + * Drags the divider to a given location by calling the + * dragDividerTo method of the UI delegate of the enclosing + * JSplitPane. + * + * @param location the new location of the divider. + * + * @see BasicSplitPaneUI#dragDividerTo(int location) + */ + protected void dragDividerTo(int location) + { + if (splitPaneUI != null) + splitPaneUI.dragDividerTo(location); + } + + /** + * Finishes a dragging gesture by calling the finishDraggingTo + * method of the UI delegate of the enclosing JSplitPane. + * + * @param location the new, final location of the divider. + * + * @see BasicSplitPaneUI#finishDraggingTo(int location) + */ + protected void finishDraggingTo(int location) + { + if (splitPaneUI != null) + splitPaneUI.finishDraggingTo(location); + } + + /** + * This helper method moves the divider to one of the three locations when + * using one touch expand buttons. Location 0 is the left (or top) most + * location. Location 1 is the middle. Location 2 is the right (or bottom) + * most location. + * This is package-private to avoid an accessor method. + * + * @param locationIndex The location to move to. + */ + void moveDividerTo(int locationIndex) + { + Insets insets = splitPane.getInsets(); + switch (locationIndex) + { + case 1: + splitPane.setDividerLocation(splitPane.getLastDividerLocation()); + break; + case 0: + int top = (orientation == JSplitPane.HORIZONTAL_SPLIT) ? insets.left + : insets.top; + splitPane.setDividerLocation(top); + break; + case 2: + int bottom; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + bottom = splitPane.getBounds().width - insets.right - dividerSize; + else + bottom = splitPane.getBounds().height - insets.bottom - dividerSize; + splitPane.setDividerLocation(bottom); + break; + } + } + + /** + * The listener for handling mouse events from both the divider and the + * containing JSplitPane. + * + *

+ * The reason for also handling MouseEvents from the containing + * JSplitPane is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + *

+ * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ + protected class MouseHandler extends MouseAdapter + implements MouseMotionListener + { + /** Keeps track of whether a drag is occurring. */ + private transient boolean isDragging; + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + if (splitPane.isOneTouchExpandable()) + { + if (e.getSource() == leftButton) + { + currentDividerLocation--; + if (currentDividerLocation < 0) + currentDividerLocation = 0; + moveDividerTo(currentDividerLocation); + return; + } + else if (e.getSource() == rightButton) + { + currentDividerLocation++; + if (currentDividerLocation > 2) + currentDividerLocation = 2; + moveDividerTo(currentDividerLocation); + return; + } + } + isDragging = true; + currentDividerLocation = 1; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + dragger = new DragController(e); + else + dragger = new VerticalDragController(e); + prepareForDragging(); + } + + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (isDragging) + dragger.completeDrag(e); + isDragging = false; + } + + /** + * Repeatedly invoked when the user is dragging the mouse cursor while + * having pressed a mouse button. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + if (dragger != null) + dragger.continueDrag(e); + } + + /** + * Repeatedly invoked when the user is dragging the mouse cursor without + * having pressed a mouse button. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Do nothing. + } + } + + /** + * Performs the tasks associated with an ongoing drag operation. + * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ + protected class DragController + { + /** + * The difference between where the mouse is clicked and the initial + * divider location. + */ + transient int offset; + + /** + * Creates a new DragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected DragController(MouseEvent e) + { + offset = e.getX(); + } + + /** + * This method returns true if the divider can move. + * + * @return True if dragging is allowed. + */ + protected boolean isValid() + { + // Views can always be resized? + return true; + } + + /** + * Returns a position for the divider given the MouseEvent. + * + * @param e MouseEvent. + * + * @return The position for the divider to move to. + */ + protected int positionForMouseEvent(MouseEvent e) + { + return e.getX() + getX() - offset; + } + + /** + * This method returns one of the two paramters for the orientation. In + * this case, it returns x. + * + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return The x coordinate. + */ + protected int getNeededLocation(int x, int y) + { + return x; + } + + /** + * This method is called to pass on the drag information to the UI through + * dragDividerTo. + * + * @param newX The x coordinate of the MouseEvent. + * @param newY The y coordinate of the MouseEvent. + */ + protected void continueDrag(int newX, int newY) + { + if (isValid()) + dragDividerTo(adjust(newX, newY)); + } + + /** + * This method is called to pass on the drag information to the UI + * through dragDividerTo. + * + * @param e The MouseEvent. + */ + protected void continueDrag(MouseEvent e) + { + if (isValid()) + dragDividerTo(positionForMouseEvent(e)); + } + + /** + * This method is called to finish the drag session by calling + * finishDraggingTo. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + */ + protected void completeDrag(int x, int y) + { + finishDraggingTo(adjust(x, y)); + } + + /** + * This method is called to finish the drag session by calling + * finishDraggingTo. + * + * @param e The MouseEvent. + */ + protected void completeDrag(MouseEvent e) + { + finishDraggingTo(positionForMouseEvent(e)); + } + + /** + * This is a helper method that includes the offset in the needed + * location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getX() - offset; + } + } + + /** + * This is a helper class that controls dragging when the orientation is + * VERTICAL_SPLIT. + */ + protected class VerticalDragController extends DragController + { + /** + * Creates a new VerticalDragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected VerticalDragController(MouseEvent e) + { + super(e); + offset = e.getY(); + } + + /** + * This method returns one of the two parameters given the orientation. In + * this case, it returns y. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The y coordinate. + */ + protected int getNeededLocation(int x, int y) + { + return y; + } + + /** + * This method returns the new location of the divider given a MouseEvent. + * + * @param e The MouseEvent. + * + * @return The new location of the divider. + */ + protected int positionForMouseEvent(MouseEvent e) + { + return e.getY() + getY() - offset; + } + + /** + * This is a helper method that includes the offset in the needed + * location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getY() - offset; + } + } + + /** + * This helper class acts as the Layout Manager for the divider. + */ + protected class DividerLayout implements LayoutManager + { + /** + * Creates a new DividerLayout object. + */ + protected DividerLayout() + { + } + + /** + * This method is called when a Component is added. + * + * @param string The constraints string. + * @param c The Component to add. + */ + public void addLayoutComponent(String string, Component c) + { + // Do nothing. + } + + /** + * This method is called to lay out the container. + * + * @param c The container to lay out. + */ + public void layoutContainer(Container c) + { + if (splitPane.isOneTouchExpandable()) + { + changeButtonOrientation(); + positionButtons(); + } + } + + /** + * This method returns the minimum layout size. + * + * @param c The container to calculate for. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * This method returns the preferred layout size. + * + * @param c The container to calculate for. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container c) + { + return new Dimension(dividerSize, dividerSize); + } + + /** + * This method is called when a component is removed. + * + * @param c The component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Do nothing. + } + + /** + * This method changes the button orientation when the orientation of the + * SplitPane changes. + */ + private void changeButtonOrientation() + { + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.EAST); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.WEST); + } + else + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.SOUTH); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.NORTH); + } + } + + /** + * This method sizes and positions the buttons. + */ + private void positionButtons() + { + int w = 0; + int h = 0; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + rightButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + leftButton.setLocation(ONE_TOUCH_OFFSET, + ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE); + w = dividerSize - 2 * ONE_TOUCH_OFFSET; + h = 2 * ONE_TOUCH_SIZE; + } + else + { + leftButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + rightButton.setLocation(ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE, + ONE_TOUCH_OFFSET); + h = dividerSize - 2 * ONE_TOUCH_OFFSET; + w = 2 * ONE_TOUCH_SIZE; + } + Dimension dims = new Dimension(w, h); + leftButton.setSize(dims); + rightButton.setSize(dims); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java new file mode 100644 index 0000000..ff7e8ac --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -0,0 +1,1556 @@ +/* BasicSplitPaneUI.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager2; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SplitPaneUI; + +/** + * This is the Basic Look and Feel implementation of the SplitPaneUI class. + */ +public class BasicSplitPaneUI extends SplitPaneUI +{ + /** + * This Layout Manager controls the position and size of the components when + * the JSplitPane's orientation is HORIZONTAL_SPLIT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class BasicHorizontalLayoutManager implements LayoutManager2 + { + // 3 components at a time. + // LEFT/TOP = 0 + // RIGHT/BOTTOM = 1 + // DIVIDER = 2 + + /** + * This array contains the components in the JSplitPane. The left/top + * component is at index 0, the right/bottom is at 1, and the divider is + * at 2. + */ + protected Component[] components = new Component[3]; + + // These are the _current_ widths of the associated component. + + /** + * This array contains the current width (for HORIZONTAL_SPLIT) or height + * (for VERTICAL_SPLIT) of the components. The indices are the same as + * for components. + */ + protected int[] sizes = new int[3]; + + /** + * This method adds the component given to the JSplitPane. The position of + * the component is given by the constraints object. + * + * @param comp The Component to add. + * @param constraints The constraints that bind the object. + */ + public void addLayoutComponent(Component comp, Object constraints) + { + addLayoutComponent((String) constraints, comp); + } + + /** + * This method is called to add a Component to the JSplitPane. The + * placement string determines where the Component will be placed. The + * string should be one of LEFT, RIGHT, TOP, BOTTOM or null (signals that + * the component is the divider). + * + * @param place The placement of the Component. + * @param component The Component to add. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void addLayoutComponent(String place, Component component) + { + int i = 0; + if (place == null) + i = 2; + else if (place.equals(JSplitPane.TOP) || place.equals(JSplitPane.LEFT)) + i = 0; + else if (place.equals(JSplitPane.BOTTOM) + || place.equals(JSplitPane.RIGHT)) + i = 1; + else + throw new IllegalArgumentException("Illegal placement in JSplitPane"); + components[i] = component; + resetSizeAt(i); + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method returns the width of the JSplitPane minus the insets. + * + * @param containerSize The Dimensions of the JSplitPane. + * @param insets The Insets of the JSplitPane. + * + * @return The width of the JSplitPane minus the insets. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.width - insets.left - insets.right; + } + + /** + * This method returns the given insets left value. If the given inset is + * null, then 0 is returned. + * + * @param insets The Insets to use with the JSplitPane. + * + * @return The inset's left value. + */ + protected int getInitialLocation(Insets insets) + { + if (insets != null) + return insets.left; + return 0; + } + + /** + * This specifies how a component is aligned with respect to other + * components in the x fdirection. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentX(Container target) + { + return target.getAlignmentX(); + } + + /** + * This specifies how a component is aligned with respect to other + * components in the y direction. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentY(Container target) + { + return target.getAlignmentY(); + } + + /** + * This method returns the preferred width of the component. + * + * @param c The component to measure. + * + * @return The preferred width of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.width; + return 0; + } + + /** + * This method returns the current width of the component. + * + * @param c The component to measure. + * + * @return The width of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getWidth(); + } + + /** + * This method returns the sizes array. + * + * @return The sizes array. + */ + protected int[] getSizes() + { + return sizes; + } + + /** + * This method invalidates the layout. It does nothing. + * + * @param c The container to invalidate. + */ + public void invalidateLayout(Container c) + { + // DO NOTHING + } + + /** + * This method lays out the components in the container. + * + * @param container The container to lay out. + */ + public void layoutContainer(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + distributeExtraSpace(); + Insets insets = split.getInsets(); + int width = getInitialLocation(insets); + Dimension dims = split.getSize(); + for (int i = 0; i < components.length; i += 2) + { + if (components[i] == null) + continue; + setComponentToSize(components[i], sizes[i], width, insets, dims); + width += sizes[i]; + } + if (components[1] != null) + { + setComponentToSize(components[1], sizes[1], width, insets, dims); + width += sizes[1]; + } + } + } + + /** + * This method returns the maximum size for the container given the + * components. It returns a new Dimension object that has width and + * height equal to Integer.MAX_VALUE. + * + * @param target The container to measure. + * + * @return The maximum size. + */ + public Dimension maximumLayoutSize(Container target) + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * This method returns the container's minimum size. The minimum width is + * the sum of all the component's minimum widths. The minimum height is + * the maximum of all the components' minimum heights. + * + * @param target The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + width += dims.width; + height = Math.max(height, dims.height); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the container's preferred size. The preferred width + * is the sum of all the component's preferred widths. The preferred + * height is the maximum of all the components' preferred heights. + * + * @param target The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + width += dims.width; + if (! (components[i] instanceof BasicSplitPaneDivider)) + height = Math.max(height, dims.height); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method removes the component from the layout. + * + * @param component The component to remove from the layout. + */ + public void removeLayoutComponent(Component component) + { + for (int i = 0; i < components.length; i++) + { + if (component == components[i]) + { + components[i] = null; + sizes[i] = 0; + } + } + } + + /** + * This method resets the size of Component to the preferred size. + * + * @param index The index of the component to reset. + */ + protected void resetSizeAt(int index) + { + if (components[index] != null) + sizes[index] = getPreferredSizeOfComponent(components[index]); + } + + /** + * This method resets the sizes of all the components. + */ + public void resetToPreferredSizes() + { + for (int i = 0; i < components.length; i++) + resetSizeAt(i); + } + + /** + * This methods sets the bounds of the given component. The width is the + * size. The height is the container size minus the top and bottom + * inset. The x coordinate is the location given. The y coordinate is + * the top inset. + * + * @param c The component to set. + * @param size The width of the component. + * @param location The x coordinate. + * @param insets The insets to use. + * @param containerSize The height of the container. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int w = size; + int h = containerSize.height - insets.top - insets.bottom; + int x = location; + int y = insets.top; + c.setBounds(x, y, w, h); + } + + /** + * This method stores the given int array as the new sizes array. + * + * @param newSizes The array to use as sizes. + */ + protected void setSizes(int[] newSizes) + { + sizes = newSizes; + } + + /** + * This method determines the size of each component. It should be called + * when a new Layout Manager is created for an existing JSplitPane. + */ + protected void updateComponents() + { + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + + if (left != null) + { + components[0] = left; + resetSizeAt(0); + } + if (right != null) + { + components[1] = right; + resetSizeAt(1); + } + components[2] = divider; + resetSizeAt(2); + } + + /** + * This method resizes the left and right components to fit inside the + * JSplitPane when there is extra space. + */ + void distributeExtraSpace() + { + int availSize = getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int[] newSizes = new int[3]; + double weight = splitPane.getResizeWeight(); + + int oldLen = sizes[0] + sizes[1]; + + // dividers don't change size. + availSize -= sizes[2] + oldLen; + + int rightAlloc = (int) (availSize * (1 - weight)); + int leftAlloc = availSize - rightAlloc; + + sizes[0] += leftAlloc; + sizes[1] += rightAlloc; + } + + /** + * This method returns the minimum width of the component at the given + * index. + * + * @param index The index to check. + * + * @return The minimum width. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.width; + else + return 0; + } + } //end BasicHorizontalLayoutManager + + /** + * This class is the Layout Manager for the JSplitPane when the orientation + * is VERTICAL_SPLIT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class BasicVerticalLayoutManager + extends BasicHorizontalLayoutManager + { + /** + * This method returns the height of the container minus the top and + * bottom inset. + * + * @param containerSize The size of the container. + * @param insets The insets of the container. + * + * @return The height minus top and bottom inset. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.height - insets.top - insets.bottom; + } + + /** + * This method returns the top inset. + * + * @param insets The Insets to use. + * + * @return The top inset. + */ + protected int getInitialLocation(Insets insets) + { + return insets.top; + } + + /** + * This method returns the preferred height of the component. + * + * @param c The component to measure. + * + * @return The preferred height of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.height; + return 0; + } + + /** + * This method returns the current height of the component. + * + * @param c The component to measure. + * + * @return The current height of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getHeight(); + } + + /** + * This method returns the minimum layout size. The minimum height is the + * sum of all the components' minimum heights. The minimum width is the + * maximum of all the components' minimum widths. + * + * @param container The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the preferred layout size. The preferred height is + * the sum of all the components' preferred heights. The preferred width + * is the maximum of all the components' preferred widths. + * + * @param container The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method sets the bounds of the given component. The y coordinate is + * the location given. The x coordinate is the left inset. The height is + * the size given. The width is the container size minus the left and + * right inset. + * + * @param c The component to set bounds for. + * @param size The height. + * @param location The y coordinate. + * @param insets The insets to use. + * @param containerSize The container's size. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int y = location; + int x = insets.left; + int h = size; + int w = containerSize.width - insets.left - insets.right; + + c.setBounds(x, y, w, h); + } + + /** + * This method returns the minimum height of the component at the given + * index. + * + * @param index The index of the component to check. + * + * @return The minimum height of the given component. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.height; + else + return 0; + } + } + + /** + * This class handles FocusEvents from the JComponent. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler extends FocusAdapter + { + /** + * This method is called when the JSplitPane gains focus. + * + * @param ev The FocusEvent. + */ + public void focusGained(FocusEvent ev) + { + // FIXME: implement. + } + + /** + * This method is called when the JSplitPane loses focus. + * + * @param ev The FocusEvent. + */ + public void focusLost(FocusEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling down + * and right key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardDownRightHandler implements ActionListener + { + /** + * This method is called when the down or right keys are pressed. + * + * @param ev The ActionEvent + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling end + * key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardEndHandler implements ActionListener + { + /** + * This method is called when the end key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling home + * key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardHomeHandler implements ActionListener + { + /** + * This method is called when the home key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling resize + * toggles. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardResizeToggleHandler implements ActionListener + { + /** + * This method is called when a resize is toggled. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handler up and + * left key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardUpLeftHandler implements ActionListener + { + /** + * This method is called when the left or up keys are pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This helper class handles PropertyChangeEvents from the JSplitPane. When + * a property changes, this will update the UI accordingly. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the JSplitPane's properties + * change. + * + * @param e DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + { + int newSize = splitPane.getDividerSize(); + int[] tmpSizes = layoutManager.getSizes(); + dividerSize = tmpSizes[2]; + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + int newSpace = newSize - tmpSizes[2]; + + tmpSizes[2] = newSize; + + tmpSizes[0] += newSpace / 2; + tmpSizes[1] += newSpace / 2; + + layoutManager.setSizes(tmpSizes); + } + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + int max = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int dividerLoc = getDividerLocation(splitPane); + double prop = ((double) dividerLoc) / max; + + resetLayoutManager(); + if (prop <= 1 && prop >= 0) + splitPane.setDividerLocation(prop); + } + layoutManager.layoutContainer(splitPane); + splitPane.repaint(); + // Don't have to deal with continuous_layout - only + // necessary in dragging modes (and it's checked + // every time you drag there) + // Don't have to deal with resize_weight (as there + // will be no extra space associated with this + // event - the changes to the weighting will + // be taken into account the next time the + // sizes change.) + // Don't have to deal with divider_location + // The method in JSplitPane calls our setDividerLocation + // so we'll know about those anyway. + // Don't have to deal with last_divider_location + // Although I'm not sure why, it doesn't seem to + // have any effect on Sun's JSplitPane. + // one_touch_expandable changes are dealt with + // by our divider. + } + } + + /** The location of the divider when dragging began. */ + protected int beginDragDividerLocation; + + /** The size of the divider while dragging. */ + protected int dividerSize; + + /** The location where the last drag location ended. */ + transient int lastDragLocation = -1; + + /** The distance the divider is moved when moved by keyboard actions. */ + protected static int KEYBOARD_DIVIDER_MOVE_OFFSET; + + /** The divider that divides this JSplitPane. */ + protected BasicSplitPaneDivider divider; + + /** The listener that listens for PropertyChangeEvents from the JSplitPane. */ + protected PropertyChangeListener propertyChangeListener; + + /** The JSplitPane's focus handler. */ + protected FocusListener focusListener; + + /** @deprecated The handler for down and right key presses. */ + protected ActionListener keyboardDownRightListener; + + /** @deprecated The handler for end key presses. */ + protected ActionListener keyboardEndListener; + + /** @deprecated The handler for home key presses. */ + protected ActionListener keyboardHomeListener; + + /** @deprecated The handler for toggling resizes. */ + protected ActionListener keyboardResizeToggleListener; + + /** @deprecated The handler for up and left key presses. */ + protected ActionListener keyboardUpLeftListener; + + /** The JSplitPane's current layout manager. */ + protected BasicHorizontalLayoutManager layoutManager; + + /** @deprecated The divider resize toggle key. */ + protected KeyStroke dividerResizeToggleKey; + + /** @deprecated The down key. */ + protected KeyStroke downKey; + + /** @deprecated The end key. */ + protected KeyStroke endKey; + + /** @deprecated The home key. */ + protected KeyStroke homeKey; + + /** @deprecated The left key. */ + protected KeyStroke leftKey; + + /** @deprecated The right key. */ + protected KeyStroke rightKey; + + /** @deprecated The up key. */ + protected KeyStroke upKey; + + /** Set to true when dragging heavy weight components. */ + protected boolean draggingHW; + + /** + * The constraints object used when adding the non-continuous divider to the + * JSplitPane. + */ + protected static final String NON_CONTINUOUS_DIVIDER + = "nonContinuousDivider"; + + /** The dark divider used when dragging in non-continuous layout mode. */ + protected Component nonContinuousLayoutDivider; + + /** The JSplitPane that this UI draws. */ + protected JSplitPane splitPane; + + /** + * Creates a new BasicSplitPaneUI object. + */ + public BasicSplitPaneUI() + { + } + + /** + * This method creates a new BasicSplitPaneUI for the given JComponent. + * + * @param x The JComponent to create a UI for. + * + * @return A new BasicSplitPaneUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicSplitPaneUI(); + } + + /** + * This method installs the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JSplitPane) + { + splitPane = (JSplitPane) c; + installDefaults(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * This method uninstalls the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to uninstall the UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + + splitPane = null; + } + + /** + * This method installs the defaults given by the Look and Feel. + */ + protected void installDefaults() + { + 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.setOpaque(true); + } + + /** + * This method uninstalls the defaults and nulls any objects created during + * install. + */ + protected void uninstallDefaults() + { + layoutManager = null; + splitPane.remove(divider); + divider = null; + nonContinuousLayoutDivider = null; + + splitPane.setBackground(null); + splitPane.setBorder(null); + } + + /** + * This method installs the listeners needed for this UI to function. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + + splitPane.addPropertyChangeListener(propertyChangeListener); + splitPane.addFocusListener(focusListener); + } + + /** + * This method uninstalls all listeners registered for the UI. + */ + protected void uninstallListeners() + { + splitPane.removePropertyChangeListener(propertyChangeListener); + splitPane.removeFocusListener(focusListener); + + focusListener = null; + propertyChangeListener = null; + } + + /** + * This method installs the keyboard actions for the JSplitPane. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method reverses the work done in installKeyboardActions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyHandler(); + } + + /** + * This method creates a new FocusListener. + * + * @return A new FocusListener. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method creates a new ActionListener for up and left key presses. + * + * @return A new ActionListener for up and left keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardUpLeftListener() + { + return new KeyboardUpLeftHandler(); + } + + /** + * This method creates a new ActionListener for down and right key presses. + * + * @return A new ActionListener for down and right keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardDownRightListener() + { + return new KeyboardDownRightHandler(); + } + + /** + * This method creates a new ActionListener for home key presses. + * + * @return A new ActionListener for home keys. + * + * @deprecated + */ + protected ActionListener createKeyboardHomeListener() + { + return new KeyboardHomeHandler(); + } + + /** + * This method creates a new ActionListener for end key presses.i + * + * @return A new ActionListener for end keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardEndListener() + { + return new KeyboardEndHandler(); + } + + /** + * This method creates a new ActionListener for resize toggle key events. + * + * @return A new ActionListener for resize toggle keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardResizeToggleListener() + { + return new KeyboardResizeToggleHandler(); + } + + /** + * This method returns the orientation of the JSplitPane. + * + * @return The orientation of the JSplitPane. + */ + public int getOrientation() + { + return splitPane.getOrientation(); + } + + /** + * This method sets the orientation of the JSplitPane. + * + * @param orientation The new orientation of the JSplitPane. + */ + public void setOrientation(int orientation) + { + splitPane.setOrientation(orientation); + } + + /** + * This method returns true if the JSplitPane is using continuous layout. + * + * @return True if the JSplitPane is using continuous layout. + */ + public boolean isContinuousLayout() + { + return splitPane.isContinuousLayout(); + } + + /** + * This method sets the continuous layout property of the JSplitPane. + * + * @param b True if the JsplitPane is to use continuous layout. + */ + public void setContinuousLayout(boolean b) + { + splitPane.setContinuousLayout(b); + } + + /** + * This method returns the last location the divider was dragged to. + * + * @return The last location the divider was dragged to. + */ + public int getLastDragLocation() + { + return lastDragLocation; + } + + /** + * This method sets the last location the divider was dragged to. + * + * @param l The last location the divider was dragged to. + */ + public void setLastDragLocation(int l) + { + lastDragLocation = l; + } + + /** + * This method returns the BasicSplitPaneDivider that divides this + * JSplitPane. + * + * @return The divider for the JSplitPane. + */ + public BasicSplitPaneDivider getDivider() + { + return divider; + } + + /** + * This method creates a nonContinuousLayoutDivider for use with the + * JSplitPane in nonContinousLayout mode. The default divider is a gray + * Canvas. + * + * @return The default nonContinousLayoutDivider. + */ + protected Component createDefaultNonContinuousLayoutDivider() + { + if (nonContinuousLayoutDivider == null) + { + nonContinuousLayoutDivider = new Canvas(); + nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY); + } + return nonContinuousLayoutDivider; + } + + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + */ + protected void setNonContinuousLayoutDivider(Component newDivider) + { + setNonContinuousLayoutDivider(newDivider, true); + } + + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + * @param rememberSizes FIXME: document. + */ + protected void setNonContinuousLayoutDivider(Component newDivider, + boolean rememberSizes) + { + // FIXME: use rememberSizes for something + nonContinuousLayoutDivider = newDivider; + } + + /** + * This method returns the nonContinuousLayoutDivider. + * + * @return The nonContinuousLayoutDivider. + */ + public Component getNonContinuousLayoutDivider() + { + return nonContinuousLayoutDivider; + } + + /** + * This method returns the JSplitPane that this BasicSplitPaneUI draws. + * + * @return The JSplitPane. + */ + public JSplitPane getSplitPane() + { + return splitPane; + } + + /** + * This method creates the divider used normally with the JSplitPane. + * + * @return The default divider. + */ + public BasicSplitPaneDivider createDefaultDivider() + { + if (divider == null) + divider = new BasicSplitPaneDivider(this); + return divider; + } + + /** + * This method is called when JSplitPane's resetToPreferredSizes is called. + * It resets the sizes of all components in the JSplitPane. + * + * @param jc The JSplitPane to reset. + */ + public void resetToPreferredSizes(JSplitPane jc) + { + layoutManager.resetToPreferredSizes(); + } + + /** + * This method sets the location of the divider. + * + * @param jc The JSplitPane to set the divider location in. + * @param location The new location of the divider. + */ + public void setDividerLocation(JSplitPane jc, int location) + { + setLastDragLocation(getDividerLocation(splitPane)); + splitPane.setLastDividerLocation(getDividerLocation(splitPane)); + int[] tmpSizes = layoutManager.getSizes(); + tmpSizes[0] = location + - layoutManager.getInitialLocation(splitPane.getInsets()); + tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()) + - tmpSizes[0] - tmpSizes[1]; + + layoutManager.setSizes(tmpSizes); + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method returns the location of the divider. + * + * @param jc The JSplitPane to retrieve the location for. + * + * @return The location of the divider. + */ + public int getDividerLocation(JSplitPane jc) + { + return layoutManager.sizes[0] + + layoutManager.getInitialLocation(splitPane.getInsets()); + } + + /** + * This method returns the smallest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The minimum divider location. + */ + public int getMinimumDividerLocation(JSplitPane jc) + { + int value = layoutManager.getInitialLocation(jc.getInsets()); + if (layoutManager.components[0] != null) + value += layoutManager.minimumSizeOfComponent(0); + return value; + } + + /** + * This method returns the largest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The maximum divider location. + */ + public int getMaximumDividerLocation(JSplitPane jc) + { + int value = layoutManager.getInitialLocation(jc.getInsets()) + + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) + - splitPane.getDividerSize(); + if (layoutManager.components[1] != null) + value -= layoutManager.minimumSizeOfComponent(1); + return value; + } + + /** + * This method is called after the children of the JSplitPane are painted. + * + * @param jc The JSplitPane. + * @param g The Graphics object to paint with. + */ + public void finishedPaintingChildren(JSplitPane jc, Graphics g) + { + if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null + && nonContinuousLayoutDivider.isVisible()) + javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider, + null, + nonContinuousLayoutDivider + .getBounds()); + } + + /** + * This method is called to paint the JSplitPane. + * + * @param g The Graphics object to paint with. + * @param jc The JSplitPane to paint. + */ + public void paint(Graphics g, JComponent jc) + { + } + + /** + * This method returns the preferred size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The preferred size of the JSplitPane. + */ + public Dimension getPreferredSize(JComponent jc) + { + return layoutManager.preferredLayoutSize((Container) jc); + } + + /** + * This method returns the minimum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The minimum size of the JSplitPane. + */ + public Dimension getMinimumSize(JComponent jc) + { + return layoutManager.minimumLayoutSize((Container) jc); + } + + /** + * This method returns the maximum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The maximum size of the JSplitPane. + */ + public Dimension getMaximumSize(JComponent jc) + { + return layoutManager.maximumLayoutSize((Container) jc); + } + + /** + * This method returns the border insets of the current border. + * + * @param jc The JSplitPane. + * + * @return The current border insets. + */ + public Insets getInsets(JComponent jc) + { + return splitPane.getBorder().getBorderInsets(splitPane); + } + + /** + * This method resets the current layout manager. The type of layout manager + * is dependent on the current orientation. + */ + protected void resetLayoutManager() + { + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + layoutManager = new BasicHorizontalLayoutManager(); + else + layoutManager = new BasicVerticalLayoutManager(); + getSplitPane().setLayout(layoutManager); + layoutManager.updateComponents(); + + // invalidating by itself does not invalidate the layout. + getSplitPane().revalidate(); + } + + /** + * This method is called when dragging starts. It resets lastDragLocation + * and dividerSize. + */ + protected void startDragging() + { + dividerSize = divider.getDividerSize(); + setLastDragLocation(-1); + + if (! splitPane.getLeftComponent().isLightweight() + || ! splitPane.getRightComponent().isLightweight()) + draggingHW = true; + + if (splitPane.isContinuousLayout()) + nonContinuousLayoutDivider.setVisible(false); + else + { + nonContinuousLayoutDivider.setVisible(true); + nonContinuousLayoutDivider.setBounds(divider.getBounds()); + } + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method is called whenever the divider is dragged. If the JSplitPane + * is in continuousLayout mode, the divider needs to be moved and the + * JSplitPane needs to be laid out. + * + * @param location The new location of the divider. + */ + protected void dragDividerTo(int location) + { + location = validLocation(location); + if (beginDragDividerLocation == -1) + beginDragDividerLocation = location; + + if (splitPane.isContinuousLayout()) + splitPane.setDividerLocation(location); + else + { + Point p = nonContinuousLayoutDivider.getLocation(); + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + p.x = location; + else + p.y = location; + nonContinuousLayoutDivider.setLocation(p); + } + setLastDragLocation(location); + splitPane.repaint(); + } + + /** + * This method is called when the dragging is finished. + * + * @param location The location where the drag finished. + */ + protected void finishDraggingTo(int location) + { + if (nonContinuousLayoutDivider != null) + nonContinuousLayoutDivider.setVisible(false); + draggingHW = false; + location = validLocation(location); + dragDividerTo(location); + splitPane.setDividerLocation(location); + splitPane.setLastDividerLocation(beginDragDividerLocation); + beginDragDividerLocation = -1; + splitPane.repaint(); + } + + /** + * This method returns the width of one of the sides of the divider's border. + * + * @return The width of one side of the divider's border. + * + * @deprecated 1.3 + */ + protected int getDividerBorderSize() + { + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + return divider.getBorder().getBorderInsets(divider).left; + else + return divider.getBorder().getBorderInsets(divider).top; + } + + /** + * This is a helper method that returns a valid location for the divider + * when dragging. + * + * @param location The location to check. + * + * @return A valid location. + */ + private int validLocation(int location) + { + if (location < getMinimumDividerLocation(splitPane)) + return getMinimumDividerLocation(splitPane); + if (location > getMaximumDividerLocation(splitPane)) + return getMaximumDividerLocation(splitPane); + return location; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java new file mode 100644 index 0000000..8a27f98 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -0,0 +1,3084 @@ +/* BasicTabbedPaneUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +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; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +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; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PanelUI; +import javax.swing.plaf.TabbedPaneUI; +import javax.swing.plaf.UIResource; +import javax.swing.text.View; + +/** + * This is the Basic Look and Feel's UI delegate for JTabbedPane. + */ +public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants +{ + /** + * A helper class that handles focus. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler extends FocusAdapter + { + /** + * This method is called when the component gains focus. + * + * @param e The FocusEvent. + */ + public void focusGained(FocusEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the component loses focus. + * + * @param e The FocusEvent. + */ + public void focusLost(FocusEvent e) + { + // FIXME: Implement. + } + } + + /** + * A helper class for determining if mouse presses occur inside tabs and + * sets the index appropriately. In SCROLL_TAB_MODE, this class also + * handles the mouse clicks on the scrolling buttons. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MouseHandler extends MouseAdapter + { + /** + * This method is called when the mouse is pressed. The index cannot + * change to a tab that is not enabled. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + int x = e.getX(); + int y = e.getY(); + int tabCount = tabPane.getTabCount(); + + 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; + } + } + + int index = tabForCoordinate(tabPane, x, y); + + // 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.revalidate(); + tabPane.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired from the JTabbedPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the properties of the JTabbedPane + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("tabLayoutPolicy")) + { + layoutManager = createLayoutManager(); + + tabPane.setLayout(layoutManager); + } + else if (e.getPropertyName().equals("tabPlacement") + && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); + } + tabPane.layout(); + tabPane.repaint(); + } + } + + /** + * A LayoutManager responsible for placing all the tabs and the visible + * component inside the JTabbedPane. This class is only used for + * WRAP_TAB_LAYOUT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TabbedPaneLayout implements LayoutManager + { + /** + * This method is called when a component is added to the JTabbedPane. + * + * @param name The name of the component. + * @param comp The component being added. + */ + public void addLayoutComponent(String name, Component comp) + { + // Do nothing. + } + + /** + * This method is called when the rectangles need to be calculated. It + * also fixes the size of the visible component. + */ + public void calculateLayoutInfo() + { + calculateTabRects(tabPane.getTabPlacement(), tabPane.getTabCount()); + + 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); + } + } + + /** + * This method calculates the size of the the JTabbedPane. + * + * @param minimum Whether the JTabbedPane will try to be as small as it + * can. + * + * @return The desired size of the JTabbedPane. + */ + protected Dimension calculateSize(boolean minimum) + { + int tabPlacement = tabPane.getTabPlacement(); + int width = 0; + int height = 0; + + int componentHeight = 0; + int componentWidth = 0; + Component c; + 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); + } + } + 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; + } + else + { + int min = calculateMaxTabHeight(tabPlacement); + height = Math.max(min, componentHeight); + + int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height); + width = tabAreaWidth + componentWidth; + } + + return new Dimension(width, height); + } + + // if tab placement is LEFT OR RIGHT, they share width. + // if tab placement is TOP OR BOTTOM, they share height + // PRE STEP: finds the default sizes for the labels as well as their locations. + // AND where they will be placed within the run system. + // 1. calls normalizeTab Runs. + // 2. calls rotate tab runs. + // 3. pads the tab runs. + // 4. pads the selected tab. + + /** + * This method is called to calculate the tab rectangles. This method + * will calculate the size and position of all rectangles (taking into + * account which ones should be in which tab run). It will pad them and + * normalize them as necessary. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The run the current selection is in. + */ + protected void calculateTabRects(int tabPlacement, int tabCount) + { + if (tabCount == 0) + return; + assureRectsCreated(tabCount); + + FontMetrics fm = getFontMetrics(); + SwingUtilities.calculateInnerArea(tabPane, calcRect); + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + int max = 0; + int runs = 0; + int start = getTabRunIndent(tabPlacement, 1); + 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; + } + } + 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; + } + } + runCount = runs; + + tabRuns[0] = 0; + normalizeTabRuns(tabPlacement, tabCount, start, max); + selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex()); + if (shouldRotateTabRuns(tabPlacement)) + 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; + } + } + padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); + } + + /** + * This method is called when the JTabbedPane is laid out in + * WRAP_TAB_LAYOUT. It calls calculateLayoutInfo to find the positions + * of all its components. + * + * @param parent The Container to lay out. + */ + public void layoutContainer(Container parent) + { + calculateLayoutInfo(); + } + + /** + * This method returns the minimum layout size for the given container. + * + * @param parent The container that is being sized. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return calculateSize(false); + } + + // If there is more free space in an adjacent run AND the tab in the run can fit in the + // adjacent run, move it. This method is not perfect, it is merely an approximation. + // If you play around with Sun's JTabbedPane, you'll see that + // it does do some pretty strange things with regards to not moving tabs + // that should be moved. + // start = the x position where the tabs will begin + // max = the maximum position of where the tabs can go to (tabAreaInsets.left + the width of the tab area) + + /** + * This method tries to "even out" the number of tabs in each run based on + * their widths. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + * @param start The x position where the tabs will begin. + * @param max The maximum x position where the tab can run to. + */ + protected void normalizeTabRuns(int tabPlacement, int tabCount, int start, + int max) + { + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + 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; + } + } + } + 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; + } + } + } + } + + /** + * This method pads the tab at the selected index by the selected tab pad + * insets (so that it looks larger). + * + * @param tabPlacement The placement of the tabs. + * @param selectedIndex The selected index. + */ + protected void padSelectedTab(int tabPlacement, int selectedIndex) + { + Insets insets = getSelectedTabPadInsets(tabPlacement); + rects[selectedIndex].x -= insets.left; + rects[selectedIndex].y -= insets.top; + rects[selectedIndex].width += insets.left + insets.right; + rects[selectedIndex].height += insets.top + insets.bottom; + } + + // If the tabs on the run don't fill the width of the window, make it fit now. + // start = starting index of the run + // end = last index of the run + // max = tabAreaInsets.left + width (or equivalent) + // assert start <= end. + + /** + * This method makes each tab in the run larger so that the tabs expand + * to fill the runs width/height (depending on tabPlacement). + * + * @param tabPlacement The placement of the tabs. + * @param start The index of the first tab. + * @param end The last index of the tab + * @param max The amount of space in the run (width for TOP and BOTTOM + * tabPlacement). + */ + protected void padTabRun(int tabPlacement, int start, int end, int max) + { + 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; + } + } + 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; + } + } + } + + /** + * This method returns the preferred layout size for the given container. + * + * @param parent The container to size. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + return calculateSize(false); + } + + /** + * This method returns the preferred tab height given a tabPlacement and + * width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param width The expected width. + * + * @return The preferred tab area height. + */ + protected int preferredTabAreaHeight(int tabPlacement, int width) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 0; + int runWidth = 0; + int tabWidth = 0; + + FontMetrics fm = getFontMetrics(); + + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + + // Only interested in width, this is a messed up rectangle now. + width -= tabAreaInsets.left + tabAreaInsets.right + insets.left + + insets.right; + + // The reason why we can't use runCount: + // This method is only called to calculate the size request + // for the tabbedPane. However, this size request is dependent on + // our desired width. We need to find out what the height would + // 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; + } + runs++; + + int maxTabHeight = calculateMaxTabHeight(tabPlacement); + int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs, + maxTabHeight); + return tabAreaHeight; + } + + /** + * This method calculates the preferred tab area width given a tab + * placement and height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param height The expected height. + * + * @return The preferred tab area width. + */ + protected int preferredTabAreaWidth(int tabPlacement, int height) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 0; + int runHeight = 0; + int tabHeight = 0; + + FontMetrics fm = getFontMetrics(); + + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + + height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top + + insets.bottom; + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + { + tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + tabHeight > height) + { + runHeight = tabHeight; + runs++; + } + else + runHeight += tabHeight; + } + runs++; + + int maxTabWidth = calculateMaxTabWidth(tabPlacement); + int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth); + return tabAreaWidth; + } + + /** + * This method rotates the places each run in the correct place the + * tabRuns array. See the comment for tabRuns for how the runs are placed + * in the array. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedRun The run the current selection is in. + */ + protected void rotateTabRuns(int tabPlacement, int selectedRun) + { + if (runCount == 1 || selectedRun == 1 || selectedRun == -1) + return; + int[] newTabRuns = new int[tabRuns.length]; + int currentRun = selectedRun; + int i = 1; + do + { + newTabRuns[i] = tabRuns[currentRun]; + currentRun = getNextTabRun(currentRun); + i++; + } + while (i < runCount); + if (runCount > 1) + newTabRuns[0] = tabRuns[currentRun]; + + tabRuns = newTabRuns; + BasicTabbedPaneUI.this.selectedRun = 1; + } + + /** + * This method is called when a component is removed from the + * JTabbedPane. + * + * @param comp The component removed. + */ + public void removeLayoutComponent(Component comp) + { + // Do nothing. + } + } + + /** + * This class acts as the LayoutManager for the JTabbedPane in + * SCROLL_TAB_MODE. + */ + private class TabbedPaneScrollLayout extends TabbedPaneLayout + { + /** + * This method returns the preferred layout size for the given container. + * + * @param parent The container to calculate a size for. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + return super.calculateSize(true); + } + + /** + * This method returns the minimum layout size for the given container. + * + * @param parent The container to calculate a size for. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return super.calculateSize(true); + } + + /** + * This method calculates the tab area height given a desired width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param width The expected width. + * + * @return The tab area height given the width. + */ + protected int preferredTabAreaHeight(int tabPlacement, int width) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 1; + + int maxTabHeight = calculateMaxTabHeight(tabPlacement); + int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs, + maxTabHeight); + return tabAreaHeight; + } + + /** + * This method calculates the tab area width given a desired height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param height The expected height. + * + * @return The tab area width given the height. + */ + protected int preferredTabAreaWidth(int tabPlacement, int height) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 1; + + int maxTabWidth = calculateMaxTabWidth(tabPlacement); + int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth); + return tabAreaWidth; + } + + /** + * This method is called to calculate the tab rectangles. This method + * will calculate the size and position of all rectangles (taking into + * account which ones should be in which tab run). It will pad them and + * normalize them as necessary. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + */ + protected void calculateTabRects(int tabPlacement, int tabCount) + { + if (tabCount == 0) + return; + assureRectsCreated(tabCount); + + FontMetrics fm = getFontMetrics(); + SwingUtilities.calculateInnerArea(tabPane, calcRect); + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + int max = 0; + int runs = 1; + int start = 0; + int top = 0; + 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; + } + } + 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; + } + } + runCount = runs; + + padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); + } + + /** + * This method is called when the JTabbedPane is laid out in + * SCROLL_TAB_LAYOUT. It finds the position for all components in the + * JTabbedPane. + * + * @param pane The JTabbedPane to be laid out. + */ + public void layoutContainer(Container pane) + { + super.layoutContainer(pane); + int tabCount = tabPane.getTabCount(); + Point p = null; + if (tabCount == 0) + 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 (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(); + } + } + 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); + } + viewport.setViewPosition(p); + viewport.repaint(); + } + } + + /** + * This class handles ChangeEvents from the JTabbedPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TabSelectionHandler implements ChangeListener + { + /** + * This method is called whenever a ChangeEvent is fired from the + * JTabbedPane. + * + * @param e The ChangeEvent fired. + */ + public void stateChanged(ChangeEvent e) + { + selectedRun = getRunForTab(tabPane.getTabCount(), + tabPane.getSelectedIndex()); + tabPane.revalidate(); + tabPane.repaint(); + } + } + + /** + * This helper class is a JPanel that fits inside the ScrollViewport. This + * panel's sole job is to paint the tab rectangles inside the viewport so + * that it's clipped correctly. + */ + private class ScrollingPanel extends JPanel + { + /** + * This is a private UI class for our panel. + */ + private class ScrollingPanelUI extends BasicPanelUI + { + /** + * This method overrides the default paint method. It paints the tab + * rectangles for the JTabbedPane in the panel. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + } + } + + /** + * This method overrides the updateUI method. It makes the default UI for + * this ScrollingPanel to be a ScrollingPanelUI. + */ + public void updateUI() + { + setUI((PanelUI) new ScrollingPanelUI()); + } + } + + /** + * This is a helper class that paints the panel that paints tabs. This + * custom JViewport is used so that the tabs painted in the panel will be + * clipped. This class implements UIResource so tabs are not added when + * this objects of this class are added to the JTabbedPane. + */ + private class ScrollingViewport extends JViewport implements UIResource + { + } + + /** + * This is a helper class that implements UIResource so it is not added as a + * tab when an object of this class is added to the JTabbedPane. + */ + private class ScrollingButton extends BasicArrowButton implements UIResource + { + /** + * Creates a ScrollingButton given the direction. + * + * @param dir The direction to point in. + */ + public ScrollingButton(int dir) + { + super(dir); + } + } + + /** The button that increments the current scroll location. + * This is package-private to avoid an accessor method. */ + transient ScrollingButton incrButton; + + /** The button that decrements the current scroll location. + * This is package-private to avoid an accessor method. */ + transient ScrollingButton decrButton; + + /** The viewport used to display the tabs. + * This is package-private to avoid an accessor method. */ + transient ScrollingViewport viewport; + + /** The panel inside the viewport that paints the tabs. + * This is package-private to avoid an accessor method. */ + transient ScrollingPanel panel; + + /** The starting visible tab in the run in SCROLL_TAB_MODE. + * This is package-private to avoid an accessor method. */ + transient int currentScrollLocation; + + /** A reusable rectangle. */ + protected Rectangle calcRect; + + /** An array of Rectangles keeping track of the tabs' area and position. */ + protected Rectangle[] rects; + + /** The insets around the content area. */ + protected Insets contentBorderInsets; + + /** The extra insets around the selected tab. */ + protected Insets selectedTabPadInsets; + + /** The insets around the tab area. */ + protected Insets tabAreaInsets; + + /** The insets around each and every tab. */ + protected Insets tabInsets; + + /** + * The outer bottom and right edge color for both the tab and content + * border. + */ + protected Color darkShadow; + + /** The color of the focus outline on the selected tab. */ + protected Color focus; + + /** FIXME: find a use for this. */ + protected Color highlight; + + /** The top and left edge color for both the tab and content border. */ + protected Color lightHighlight; + + /** The inner bottom and right edge color for the tab and content border. */ + protected Color shadow; + + /** The maximum tab height. */ + protected int maxTabHeight; + + /** The maximum tab width. */ + protected int maxTabWidth; + + /** The number of runs in the JTabbedPane. */ + protected int runCount; + + /** The index of the run that the selected index is in. */ + protected int selectedRun; + + /** The amount of space each run overlaps the previous by. */ + protected int tabRunOverlay; + + /** The gap between text and label */ + protected int textIconGap; + + // Keeps track of tab runs. + // The organization of this array is as follows (lots of experimentation to + // figure this out) + // index 0 = furthest away from the component area (aka outer run) + // index 1 = closest to component area (aka selected run) + // index > 1 = listed in order leading from selected run to outer run. + // each int in the array is the tab index + 1 (counting starts at 1) + // for the last tab in the run. (same as the rects array) + + /** This array keeps track of which tabs are in which run. See above. */ + protected int[] tabRuns; + + /** + * This is the keystroke for moving down. + * + * @deprecated 1.3 + */ + protected KeyStroke downKey; + + /** + * This is the keystroke for moving left. + * + * @deprecated 1.3 + */ + protected KeyStroke leftKey; + + /** + * This is the keystroke for moving right. + * + * @deprecated 1.3 + */ + protected KeyStroke rightKey; + + /** + * This is the keystroke for moving up. + * + * @deprecated 1.3 + */ + protected KeyStroke upKey; + + /** The listener that listens for focus events. */ + protected FocusListener focusListener; + + /** The listener that listens for mouse events. */ + protected MouseListener mouseListener; + + /** The listener that listens for property change events. */ + protected PropertyChangeListener propertyChangeListener; + + /** The listener that listens for change events. */ + protected ChangeListener tabChangeListener; + + /** The tab pane that this UI paints. */ + protected JTabbedPane tabPane; + + /** The current layout manager for the tabPane. + * This is package-private to avoid an accessor method. */ + transient LayoutManager layoutManager; + + /** The rectangle that describes the tab area's position and size. + * This is package-private to avoid an accessor method. */ + transient Rectangle tabAreaRect; + + /** The rectangle that describes the content area's position and + * size. This is package-private to avoid an accessor method. */ + transient Rectangle contentRect; + + /** + * Creates a new BasicTabbedPaneUI object. + */ + public BasicTabbedPaneUI() + { + super(); + } + + /** + * This method creates a ScrollingButton that points in the appropriate + * direction for an increasing button. + * This is package-private to avoid an accessor method. + * + * @return The increase ScrollingButton. + */ + ScrollingButton createIncreaseButton() + { + if (incrButton == null) + incrButton = new ScrollingButton(SwingConstants.NORTH); + if (tabPane.getTabPlacement() == SwingConstants.TOP + || tabPane.getTabPlacement() == SwingConstants.BOTTOM) + incrButton.setDirection(SwingConstants.EAST); + else + incrButton.setDirection(SwingConstants.SOUTH); + return incrButton; + } + + /** + * This method creates a ScrollingButton that points in the appropriate + * direction for a decreasing button. + * This is package-private to avoid an accessor method. + * + * @return The decrease ScrollingButton. + */ + ScrollingButton createDecreaseButton() + { + if (decrButton == null) + decrButton = new ScrollingButton(SwingConstants.SOUTH); + if (tabPane.getTabPlacement() == SwingConstants.TOP + || tabPane.getTabPlacement() == SwingConstants.BOTTOM) + decrButton.setDirection(SwingConstants.WEST); + else + decrButton.setDirection(SwingConstants.NORTH); + return decrButton; + } + + /** + * This method finds the point to set the view position at given the index + * of a tab. The tab will be the first visible tab in the run. + * This is package-private to avoid an accessor method. + * + * @param index The index of the first visible tab. + * + * @return The position of the first visible tab. + */ + Point findPointForIndex(int index) + { + int tabPlacement = tabPane.getTabPlacement(); + int selectedIndex = tabPane.getSelectedIndex(); + Insets insets = getSelectedTabPadInsets(tabPlacement); + int w = 0; + int h = 0; + + 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; + } + } + + else + { + 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); + return p; + } + + /** + * This method creates a new BasicTabbedPaneUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicTabbedPaneUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicTabbedPaneUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JTabbedPane) + { + tabPane = (JTabbedPane) c; + + installComponents(); + installDefaults(); + installListeners(); + installKeyboardActions(); + + layoutManager = createLayoutManager(); + tabPane.setLayout(layoutManager); + tabPane.layout(); + } + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall the UI for. + */ + public void uninstallUI(JComponent c) + { + layoutManager = null; + + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + uninstallComponents(); + + tabPane = null; + } + + /** + * This method creates the appropriate layout manager for the JTabbedPane's + * current tab layout policy. If the tab layout policy is + * SCROLL_TAB_LAYOUT, then all the associated components that need to be + * created will be done so now. + * + * @return A layout manager given the tab layout policy. + */ + protected LayoutManager createLayoutManager() + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) + 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(); + } + } + + /** + * This method installs components for this JTabbedPane. + */ + protected void installComponents() + { + // Nothing to be done. + } + + /** + * This method uninstalls components for this JTabbedPane. + */ + protected void uninstallComponents() + { + // Nothing to be done. + } + + /** + * This method installs defaults for the Look and Feel. + */ + 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")); + tabPane.setOpaque(false); + + highlight = defaults.getColor("TabbedPane.highlight"); + lightHighlight = defaults.getColor("TabbedPane.lightHighlight"); + + shadow = defaults.getColor("TabbedPane.shadow"); + darkShadow = defaults.getColor("TabbedPane.darkShadow"); + + focus = defaults.getColor("TabbedPane.focus"); + + textIconGap = defaults.getInt("TabbedPane.textIconGap"); + tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay"); + + tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets"); + selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets"); + tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); + contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); + + calcRect = new Rectangle(); + tabRuns = new int[10]; + tabAreaRect = new Rectangle(); + contentRect = new Rectangle(); + } + + /** + * This method uninstalls defaults for the Look and Feel. + */ + protected void uninstallDefaults() + { + calcRect = null; + tabAreaRect = null; + contentRect = null; + tabRuns = null; + + contentBorderInsets = null; + tabAreaInsets = null; + selectedTabPadInsets = null; + tabInsets = null; + + focus = null; + darkShadow = null; + shadow = null; + lightHighlight = null; + highlight = null; + + tabPane.setBackground(null); + tabPane.setForeground(null); + tabPane.setFont(null); + } + + /** + * This method creates and installs the listeners for this UI. + */ + protected void installListeners() + { + mouseListener = createMouseListener(); + tabChangeListener = createChangeListener(); + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + + tabPane.addMouseListener(mouseListener); + tabPane.addChangeListener(tabChangeListener); + tabPane.addPropertyChangeListener(propertyChangeListener); + tabPane.addFocusListener(focusListener); + } + + /** + * This method removes and nulls the listeners for this UI. + */ + protected void uninstallListeners() + { + tabPane.removeFocusListener(focusListener); + tabPane.removePropertyChangeListener(propertyChangeListener); + tabPane.removeChangeListener(tabChangeListener); + tabPane.removeMouseListener(mouseListener); + + focusListener = null; + propertyChangeListener = null; + tabChangeListener = null; + mouseListener = null; + } + + /** + * This method creates a new MouseListener. + * + * @return A new MouseListener. + */ + protected MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * This method creates a new FocusListener. + * + * @return A new FocusListener. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method creates a new ChangeListener. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener() + { + return new TabSelectionHandler(); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method installs keyboard actions for the JTabbedPane. + */ + protected void installKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method uninstalls keyboard actions for the JTabbedPane. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method returns the preferred size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return layoutManager.preferredLayoutSize(tabPane); + } + + /** + * This method returns the minimum size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return layoutManager.minimumLayoutSize(tabPane); + } + + /** + * This method returns the maximum size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + /** + * This method paints the JTabbedPane. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (tabPane.getTabCount() == 0) + return; + if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + } + + /** + * This method paints the tab area. This includes painting the rectangles + * that make up the tabs. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected index. + */ + protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) + { + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + + boolean isScroll = tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT; + + // Please note: the ordering of the painting is important. + // we WANT to paint the outermost run first and then work our way in. + int tabCount = tabPane.getTabCount(); + int currRun = 1; + if (tabCount < 1) + return; + + if (runCount > 1) + 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); + } + if (! isScroll) + paintTab(g, tabPlacement, rects, selectedIndex, ir, tr); + } + + /** + * This method paints an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param rects The array of rectangles that keep the size and position of + * the tabs. + * @param tabIndex The tab index to paint. + * @param iconRect The rectangle to use for the icon. + * @param textRect The rectangle to use for the text. + */ + protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, + int tabIndex, Rectangle iconRect, Rectangle textRect) + { + FontMetrics fm = getFontMetrics(); + Icon icon = getIconForTab(tabIndex); + String title = tabPane.getTitleAt(tabIndex); + boolean isSelected = tabIndex == tabPane.getSelectedIndex(); + calcRect = getTabBounds(tabPane, tabIndex); + + int x = calcRect.x; + int y = calcRect.y; + int w = calcRect.width; + 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; + } + } + + layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect, + textRect, isSelected); + paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); + paintTabBorder(g, tabPlacement, tabIndex, x, y, w, h, isSelected); + + // FIXME: Paint little folding corner and jagged edge clipped tab. + if (icon != null) + paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); + if (title != null && ! title.equals("")) + paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title, + textRect, isSelected); + } + + /** + * This method lays out the tab and finds the location to paint the icon + * and text. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param metrics The font metrics for the font to paint with. + * @param tabIndex The tab index to paint. + * @param title The string painted. + * @param icon The icon painted. + * @param tabRect The tab bounds. + * @param iconRect The calculated icon bounds. + * @param textRect The calculated text bounds. + * @param isSelected Whether this tab is selected. + */ + protected void layoutLabel(int tabPlacement, FontMetrics metrics, + int tabIndex, String title, Icon icon, + Rectangle tabRect, Rectangle iconRect, + Rectangle textRect, boolean isSelected) + { + SwingUtilities.layoutCompoundLabel(metrics, title, icon, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, tabRect, + iconRect, textRect, textIconGap); + + int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); + int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); + + iconRect.x += shiftX; + iconRect.y += shiftY; + + textRect.x += shiftX; + textRect.y += shiftY; + } + + /** + * This method paints the icon. + * + * @param g The Graphics object to paint. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index to paint. + * @param icon The icon to paint. + * @param iconRect The bounds of the icon. + * @param isSelected Whether this tab is selected. + */ + protected void paintIcon(Graphics g, int tabPlacement, int tabIndex, + Icon icon, Rectangle iconRect, boolean isSelected) + { + icon.paintIcon(tabPane, g, iconRect.x, iconRect.y); + } + + /** + * This method paints the text for the given tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param font The font to paint with. + * @param metrics The fontmetrics of the given font. + * @param tabIndex The tab index. + * @param title The string to paint. + * @param textRect The bounds of the string. + * @param isSelected Whether this tab is selected. + */ + protected void paintText(Graphics g, int tabPlacement, Font font, + FontMetrics metrics, int tabIndex, String title, + Rectangle textRect, boolean isSelected) + { + View textView = getTextViewForTab(tabIndex); + if (textView != null) + { + textView.paint(g, textRect); + return; + } + + Color fg = tabPane.getForegroundAt(tabIndex); + if (fg == null) + fg = tabPane.getForeground(); + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = tabPane.getBackground(); + + Color saved_color = g.getColor(); + Font f = g.getFont(); + g.setFont(font); + + if (tabPane.isEnabledAt(tabIndex)) + { + g.setColor(fg); + + 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()); + } + 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(saved_color); + g.setFont(f); + } + + /** + * This method returns how much the label for the tab should shift in the X + * direction. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index being painted. + * @param isSelected Whether this tab is selected. + * + * @return The amount the label should shift by in the X direction. + */ + protected int getTabLabelShiftX(int tabPlacement, int tabIndex, + boolean isSelected) + { + // No reason to shift. + return 0; + } + + /** + * This method returns how much the label for the tab should shift in the Y + * direction. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index being painted. + * @param isSelected Whether this tab is selected. + * + * @return The amount the label should shift by in the Y direction. + */ + protected int getTabLabelShiftY(int tabPlacement, int tabIndex, + boolean isSelected) + { + // No reason to shift. + return 0; + } + + /** + * This method paints the focus rectangle around the selected tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param rects The array of rectangles keeping track of size and position. + * @param tabIndex The tab index. + * @param iconRect The icon bounds. + * @param textRect The text bounds. + * @param isSelected Whether this tab is selected. + */ + protected void paintFocusIndicator(Graphics g, int tabPlacement, + Rectangle[] rects, int tabIndex, + Rectangle iconRect, Rectangle textRect, + boolean isSelected) + { + Color saved = g.getColor(); + calcRect = iconRect.union(textRect); + + g.setColor(focus); + + g.drawRect(calcRect.x, calcRect.y, calcRect.width, calcRect.height); + + g.setColor(saved); + } + + /** + * This method paints the border for an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * @param x The x position of the tab. + * @param y The y position of the tab. + * @param w The width of the tab. + * @param h The height of the tab. + * @param isSelected Whether the tab is selected. + */ + protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, + int x, int y, int w, int h, boolean isSelected) + { + Color saved = g.getColor(); + + 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); + } + + 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); + } + + if (! isSelected || tabPlacement != SwingConstants.RIGHT) + { + 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(saved); + } + + /** + * This method paints the background for an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * @param x The x position of the tab. + * @param y The y position of the tab. + * @param w The width of the tab. + * @param h The height of the tab. + * @param isSelected Whether the tab is selected. + */ + protected void paintTabBackground(Graphics g, int tabPlacement, + int tabIndex, int x, int y, int w, int h, + boolean isSelected) + { + Color saved = g.getColor(); + if (isSelected) + g.setColor(Color.LIGHT_GRAY); + else + { + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = Color.GRAY; + g.setColor(bg); + } + + g.fillRect(x, y, w, h); + + g.setColor(saved); + } + + /** + * This method paints the border around the content area. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The index of the selected tab. + */ + protected void paintContentBorder(Graphics g, int tabPlacement, + int selectedIndex) + { + Insets insets = getContentBorderInsets(tabPlacement); + int x = contentRect.x; + int y = contentRect.y; + int w = contentRect.width; + int h = contentRect.height; + paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h); + } + + /** + * This method paints the top edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + g.setColor(lightHighlight); + + int startgap = rects[selectedIndex].x; + int endgap = rects[selectedIndex].x + rects[selectedIndex].width; + + int diff = 0; + + 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); + } + else + g.drawLine(x, y, x + w, y); + + g.setColor(saved); + } + + /** + * This method paints the left edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + g.setColor(lightHighlight); + + int startgap = rects[selectedIndex].y; + int endgap = rects[selectedIndex].y + rects[selectedIndex].height; + + int diff = 0; + + 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); + } + else + g.drawLine(x, y, x, y + h); + + g.setColor(saved); + } + + /** + * This method paints the bottom edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + + int startgap = rects[selectedIndex].x; + int endgap = rects[selectedIndex].x + rects[selectedIndex].width; + + int diff = 0; + + 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); + } + 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(saved); + } + + /** + * This method paints the right edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + int startgap = rects[selectedIndex].y; + int endgap = rects[selectedIndex].y + rects[selectedIndex].height; + + int diff = 0; + + 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); + } + 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(saved); + } + + /** + * This method returns the tab bounds for the given index. + * + * @param pane The JTabbedPane. + * @param i The index to look for. + * + * @return The bounds of the tab with the given index. + */ + public Rectangle getTabBounds(JTabbedPane pane, int i) + { + return rects[i]; + } + + /** + * This method returns the number of runs. + * + * @param pane The JTabbedPane. + * + * @return The number of runs. + */ + public int getTabRunCount(JTabbedPane pane) + { + return runCount; + } + + /** + * This method returns the tab index given a coordinate. + * + * @param pane The JTabbedPane. + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return The tab index that the coordinate lands in. + */ + public int tabForCoordinate(JTabbedPane pane, int x, int y) + { + Point p = new Point(x, y); + int tabCount = tabPane.getTabCount(); + 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); + } + return -1; + } + + /** + * This method returns the tab bounds in the given rectangle. + * + * @param tabIndex The index to get bounds for. + * @param dest The rectangle to store bounds in. + * + * @return The rectangle passed in. + */ + protected Rectangle getTabBounds(int tabIndex, Rectangle dest) + { + dest.setBounds(getTabBounds(tabPane, tabIndex)); + return dest; + } + + /** + * This method returns the component that is shown in the content area. + * + * @return The component that is shown in the content area. + */ + protected Component getVisibleComponent() + { + return tabPane.getComponentAt(tabPane.getSelectedIndex()); + } + + /** + * This method sets the visible component. + * + * @param component The component to be set visible. + */ + protected void setVisibleComponent(Component component) + { + component.setVisible(true); + tabPane.setSelectedComponent(component); + } + + /** + * This method assures that enough rectangles are created given the + * tabCount. The old array is copied to the new one. + * + * @param tabCount The number of tabs. + */ + protected void assureRectsCreated(int tabCount) + { + if (rects == null) + rects = new Rectangle[tabCount]; + if (tabCount == rects.length) + return; + else + { + int numToCopy = Math.min(tabCount, rects.length); + Rectangle[] tmp = new Rectangle[tabCount]; + System.arraycopy(rects, 0, tmp, 0, numToCopy); + rects = tmp; + } + } + + /** + * This method expands the tabRuns array to give it more room. The old array + * is copied to the new one. + */ + protected void expandTabRunsArray() + { + // This method adds another 10 index positions to the tabRuns array. + if (tabRuns == null) + tabRuns = new int[10]; + else + { + int[] newRuns = new int[tabRuns.length + 10]; + System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); + tabRuns = newRuns; + } + } + + /** + * This method returns which run a particular tab belongs to. + * + * @param tabCount The number of tabs. + * @param tabIndex The tab to find. + * + * @return The tabRuns index that it belongs to. + */ + protected int getRunForTab(int tabCount, int tabIndex) + { + if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0) + 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; + } + return -1; + } + + /** + * This method returns the index of the last tab in a run. + * + * @param tabCount The number of tabs. + * @param run The run to check. + * + * @return The last tab in the given run. + */ + protected int lastTabInRun(int tabCount, int run) + { + if (tabRuns[run] == 0) + return tabCount - 1; + else + return tabRuns[run] - 1; + } + + /** + * This method returns the tab run overlay. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The tab run overlay. + */ + protected int getTabRunOverlay(int tabPlacement) + { + return tabRunOverlay; + } + + /** + * This method returns the tab run indent. It is used in WRAP_TAB_LAYOUT and + * makes each tab run start indented by a certain amount. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param run The run to get indent for. + * + * @return The amount a run should be indented. + */ + protected int getTabRunIndent(int tabPlacement, int run) + { + return 0; + } + + /** + * This method returns whether a tab run should be padded. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param run The run to check. + * + * @return Whether the given run should be padded. + */ + protected boolean shouldPadTabRun(int tabPlacement, int run) + { + return true; + } + + /** + * This method returns whether the tab runs should be rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return Whether runs should be rotated. + */ + protected boolean shouldRotateTabRuns(int tabPlacement) + { + return true; + } + + /** + * This method returns an icon for the tab. If the tab is disabled, it + * should return the disabledIcon. If it is enabled, then it should return + * the default icon. + * + * @param tabIndex The tab index to get an icon for. + * + * @return The icon for the tab index. + */ + protected Icon getIconForTab(int tabIndex) + { + if (tabPane.isEnabledAt(tabIndex)) + return tabPane.getIconAt(tabIndex); + else + return tabPane.getDisabledIconAt(tabIndex); + } + + /** + * This method returns a view that can paint the text for the label. + * + * @param tabIndex The tab index to get a view for. + * + * @return The view for the tab index. + */ + protected View getTextViewForTab(int tabIndex) + { + return null; + } + + /** + * This method returns the tab height, including insets, for the given index + * and fontheight. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The index of the tab to calculate. + * @param fontHeight The font height. + * + * @return This tab's height. + */ + protected int calculateTabHeight(int tabPlacement, int tabIndex, + int fontHeight) + { + Icon icon = getIconForTab(tabIndex); + Insets insets = getTabInsets(tabPlacement, tabIndex); + + 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); + } + else + calcRect.height = fontHeight; + + calcRect.height += insets.top + insets.bottom; + return calcRect.height; + } + + /** + * This method returns the max tab height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The maximum tab height. + */ + protected int calculateMaxTabHeight(int tabPlacement) + { + maxTabHeight = 0; + + FontMetrics fm = getFontMetrics(); + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), + maxTabHeight); + + return maxTabHeight; + } + + /** + * This method calculates the tab width, including insets, for the given tab + * index and font metrics. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index to calculate for. + * @param metrics The font's metrics. + * + * @return The tab width for the given index. + */ + protected int calculateTabWidth(int tabPlacement, int tabIndex, + FontMetrics metrics) + { + Icon icon = getIconForTab(tabIndex); + Insets insets = getTabInsets(tabPlacement, tabIndex); + + 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); + } + else + calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); + + calcRect.width += insets.left + insets.right; + return calcRect.width; + } + + /** + * This method calculates the max tab width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The maximum tab width. + */ + protected int calculateMaxTabWidth(int tabPlacement) + { + maxTabWidth = 0; + + FontMetrics fm = getFontMetrics(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm), + maxTabWidth); + + return maxTabWidth; + } + + /** + * This method calculates the tab area height, including insets, for the + * given amount of runs and tab height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param horizRunCount The number of runs. + * @param maxTabHeight The max tab height. + * + * @return The tab area height. + */ + protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount, + int maxTabHeight) + { + Insets insets = getTabAreaInsets(tabPlacement); + int tabAreaHeight = horizRunCount * maxTabHeight + - (horizRunCount - 1) * tabRunOverlay; + + tabAreaHeight += insets.top + insets.bottom; + + return tabAreaHeight; + } + + /** + * This method calculates the tab area width, including insets, for the + * given amount of runs and tab width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param vertRunCount The number of runs. + * @param maxTabWidth The max tab width. + * + * @return The tab area width. + */ + protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount, + int maxTabWidth) + { + Insets insets = getTabAreaInsets(tabPlacement); + int tabAreaWidth = vertRunCount * maxTabWidth + - (vertRunCount - 1) * tabRunOverlay; + + tabAreaWidth += insets.left + insets.right; + + return tabAreaWidth; + } + + /** + * This method returns the tab insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * + * @return The tab insets for the given index. + */ + protected Insets getTabInsets(int tabPlacement, int tabIndex) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(tabInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the selected tab pad insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The selected tab pad insets. + */ + protected Insets getSelectedTabPadInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(selectedTabPadInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the tab area insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The tab area insets. + */ + protected Insets getTabAreaInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(tabAreaInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the content border insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The content border insets. + */ + protected Insets getContentBorderInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(contentBorderInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the fontmetrics for the font of the JTabbedPane. + * + * @return The font metrics for the JTabbedPane. + */ + protected FontMetrics getFontMetrics() + { + FontMetrics fm = tabPane.getToolkit().getFontMetrics(tabPane.getFont()); + return fm; + } + + /** + * This method navigates from the selected tab into the given direction. As + * a result, a new tab will be selected (if possible). + * + * @param direction The direction to navigate in. + */ + protected void navigateSelectedTab(int direction) + { + int tabPlacement = tabPane.getTabPlacement(); + 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 (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); + } + } + } + + /** + * This method selects the next tab in the run. + * + * @param current The current selected index. + */ + protected void selectNextTabInRun(int current) + { + tabPane.setSelectedIndex(getNextTabIndexInRun(tabPane.getTabCount(), + current)); + } + + /** + * This method selects the previous tab in the run. + * + * @param current The current selected index. + */ + protected void selectPreviousTabInRun(int current) + { + tabPane.setSelectedIndex(getPreviousTabIndexInRun(tabPane.getTabCount(), + current)); + } + + /** + * This method selects the next tab (regardless of runs). + * + * @param current The current selected index. + */ + protected void selectNextTab(int current) + { + tabPane.setSelectedIndex(getNextTabIndex(current)); + } + + /** + * This method selects the previous tab (regardless of runs). + * + * @param current The current selected index. + */ + protected void selectPreviousTab(int current) + { + tabPane.setSelectedIndex(getPreviousTabIndex(current)); + } + + /** + * This method selects the correct tab given an offset from the current tab + * index. If the tab placement is TOP or BOTTOM, the offset will be in the + * y direction, otherwise, it will be in the x direction. A new coordinate + * will be found by adding the offset to the current location of the tab. + * The tab that the new location will be selected. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab to start from. + * @param offset The coordinate offset. + */ + protected void selectAdjacentRunTab(int tabPlacement, int tabIndex, + int offset) + { + int x = rects[tabIndex].x + rects[tabIndex].width / 2; + 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; + } + + int index = tabForCoordinate(tabPane, x, y); + if (index != -1) + tabPane.setSelectedIndex(index); + } + + // This method is called when you press up/down to cycle through tab runs. + // it returns the distance (between the two runs' x/y position. + // where one run is the current selected run and the other run is the run in the + // direction of the scroll (dictated by the forward flag) + // the offset is an absolute value of the difference + + /** + * This method calculates the offset distance for use in + * selectAdjacentRunTab. The offset returned will be a difference in the y + * coordinate between the run in the desired direction and the current run + * (for tabPlacement in TOP or BOTTOM). Use x coordinate for LEFT and + * RIGHT. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + * @param tabIndex The starting index. + * @param forward If forward, the run in the desired direction will be the + * next run. + * + * @return The offset between the two runs. + */ + protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex, + boolean forward) + { + int currRun = getRunForTab(tabCount, tabIndex); + int offset; + int nextRun = (forward) ? getNextTabRun(currRun) : getPreviousTabRun(currRun); + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + offset = rects[lastTabInRun(tabCount, nextRun)].y + - rects[lastTabInRun(tabCount, currRun)].y; + else + offset = rects[lastTabInRun(tabCount, nextRun)].x + - rects[lastTabInRun(tabCount, currRun)].x; + return offset; + } + + /** + * This method returns the previous tab index. + * + * @param base The index to start from. + * + * @return The previous tab index. + */ + protected int getPreviousTabIndex(int base) + { + base--; + if (base < 0) + return tabPane.getTabCount() - 1; + return base; + } + + /** + * This method returns the next tab index. + * + * @param base The index to start from. + * + * @return The next tab index. + */ + protected int getNextTabIndex(int base) + { + base++; + if (base == tabPane.getTabCount()) + return 0; + return base; + } + + /** + * This method returns the next tab index in the run. If the next index is + * out of this run, it will return the starting tab index for the run. + * + * @param tabCount The number of tabs. + * @param base The index to start from. + * + * @return The next tab index in the run. + */ + protected int getNextTabIndexInRun(int tabCount, int base) + { + int index = getNextTabIndex(base); + int run = getRunForTab(tabCount, base); + if (index == lastTabInRun(tabCount, run) + 1) + index = lastTabInRun(tabCount, getPreviousTabRun(run)) + 1; + return getNextTabIndex(base); + } + + /** + * This method returns the previous tab index in the run. If the previous + * index is out of this run, it will return the last index for the run. + * + * @param tabCount The number of tabs. + * @param base The index to start from. + * + * @return The previous tab index in the run. + */ + protected int getPreviousTabIndexInRun(int tabCount, int base) + { + int index = getPreviousTabIndex(base); + int run = getRunForTab(tabCount, base); + if (index == lastTabInRun(tabCount, getPreviousTabRun(run))) + index = lastTabInRun(tabCount, run); + return getPreviousTabIndex(base); + } + + /** + * This method returns the index of the previous run. + * + * @param baseRun The run to start from. + * + * @return The index of the previous run. + */ + protected int getPreviousTabRun(int baseRun) + { + if (getTabRunCount(tabPane) == 1) + return 1; + + int prevRun = --baseRun; + if (prevRun < 0) + prevRun = getTabRunCount(tabPane) - 1; + return prevRun; + } + + /** + * This method returns the index of the next run. + * + * @param baseRun The run to start from. + * + * @return The index of the next run. + */ + protected int getNextTabRun(int baseRun) + { + if (getTabRunCount(tabPane) == 1) + return 1; + + int nextRun = ++baseRun; + if (nextRun == getTabRunCount(tabPane)) + nextRun = 0; + return nextRun; + } + + /** + * This method rotates the insets given a direction to rotate them in. + * Target placement should be one of TOP, LEFT, BOTTOM, RIGHT. The rotated + * insets will be stored in targetInsets. Passing in TOP as the direction + * does nothing. Passing in LEFT switches top and left, right and bottom. + * Passing in BOTTOM switches top and bottom. Passing in RIGHT switches top + * for left, left for bottom, bottom for right, and right for top. + * + * @param topInsets The reference insets. + * @param targetInsets An Insets object to store the new insets. + * @param targetPlacement The rotation direction. + */ + protected static void rotateInsets(Insets topInsets, Insets targetInsets, + int targetPlacement) + { + // 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; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java new file mode 100644 index 0000000..700b406 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -0,0 +1,224 @@ +/* BasicTableHeaderUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TableHeaderUI; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class BasicTableHeaderUI + extends TableHeaderUI +{ + + public static ComponentUI createUI(JComponent h) + { + return new BasicTableHeaderUI(); + } + + protected JTableHeader header; + protected MouseInputListener mouseInputListener; + protected CellRendererPane rendererPane; + protected Border cellBorder; + + 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) {} + } + + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + public BasicTableHeaderUI() + { + mouseInputListener = createMouseInputListener(); + } + + 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"); + } + + protected void installKeyboardActions() + { + } + + protected void installListeners() + { + header.addMouseListener(mouseInputListener); + } + + public void installUI(JComponent c) + { + header = (JTableHeader) c; + installDefaults(); + installKeyboardActions(); + installListeners(); + } + + protected void uninstallDefaults() + { + header.setBackground(null); + header.setForeground(null); + header.setFont(null); + } + + protected void uninstallKeyboardActions() + { + } + + protected void uninstallListeners() + { + header.removeMouseListener(mouseInputListener); + } + + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallKeyboardActions(); + uninstallDefaults(); + } + + public void paint(Graphics gfx, JComponent c) + { + TableColumnModel cmod = header.getColumnModel(); + int ncols = cmod.getColumnCount(); + if (ncols == 0) + return; + + Rectangle clip = gfx.getClipBounds(); + TableCellRenderer defaultRend = header.getDefaultRenderer(); + + for (int i = 0; i < ncols; ++i) + { + Rectangle bounds = header.getHeaderRect(i); + if (bounds.intersects(clip)) + { + TableColumn col = cmod.getColumn(i); + TableCellRenderer rend = col.getHeaderRenderer(); + if (rend == null) + rend = defaultRend; + Object val = col.getHeaderValue(); + Component comp = rend.getTableCellRendererComponent(header.getTable(), + val, + false, // isSelected + false, // isFocused + -1, i); + comp.setFont(header.getFont()); + comp.setBackground(header.getBackground()); + comp.setForeground(header.getForeground()); + if (comp instanceof JComponent) + ((JComponent)comp).setBorder(cellBorder); + gfx.translate(bounds.x, bounds.y); + comp.setSize(bounds.width, bounds.height); + comp.setLocation(0,0); + comp.paint(gfx); + gfx.translate(-bounds.x, -bounds.y); + } + } + + } + + public Dimension getPreferredSize(JComponent c) + { + TableColumnModel cmod = header.getColumnModel(); + TableCellRenderer defaultRend = header.getDefaultRenderer(); + int ncols = cmod.getColumnCount(); + Dimension ret = new Dimension(0,0); + int spacing = 0; + + if (header.getTable() != null + && header.getTable().getIntercellSpacing() != null) + spacing = header.getTable().getIntercellSpacing().width; + + for (int i = 0; i < ncols; ++i) + { + TableColumn col = cmod.getColumn(i); + TableCellRenderer rend = col.getHeaderRenderer(); + if (rend == null) + rend = defaultRend; + Object val = col.getHeaderValue(); + Component comp = rend.getTableCellRendererComponent(header.getTable(), + val, + false, // isSelected + false, // isFocused + -1, i); + comp.setFont(header.getFont()); + comp.setBackground(header.getBackground()); + comp.setForeground(header.getForeground()); + if (comp instanceof JComponent) + ((JComponent)comp).setBorder(cellBorder); + + Dimension d = comp.getPreferredSize(); + ret.width += spacing; + ret.height = Math.max(d.height, ret.height); + } + ret.width = cmod.getTotalColumnWidth(); + return ret; + } + + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java new file mode 100644 index 0000000..7787436 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java @@ -0,0 +1,398 @@ +/* BasicTableUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; + +import javax.swing.BorderFactory; +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TableUI; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class BasicTableUI + extends TableUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicTableUI(); + } + + protected FocusListener focusListener; + protected KeyListener keyListener; + protected MouseInputListener mouseInputListener; + protected CellRendererPane rendererPane; + protected JTable table; + + /** The normal cell border. */ + Border cellBorder; + + /** The cell border for selected/highlighted cells. */ + Border highlightCellBorder; + + class FocusHandler implements FocusListener + { + public void focusGained(FocusEvent e) + { + } + public void focusLost(FocusEvent e) + { + } + } + + class KeyHandler implements KeyListener + { + public void keyPressed(KeyEvent e) + { + } + public void keyReleased(KeyEvent e) + { + } + public void keyTyped(KeyEvent e) + { + } + } + + class MouseInputHandler implements MouseInputListener + { + Point begin, curr; + + private void updateSelection(boolean controlPressed) + { + if (table.getRowSelectionAllowed()) + { + int lo_row = table.rowAtPoint(begin); + int hi_row = table.rowAtPoint(curr); + ListSelectionModel rowModel = table.getSelectionModel(); + if (lo_row != -1 && hi_row != -1) + { + if (controlPressed && rowModel.getSelectionMode() + != ListSelectionModel.SINGLE_SELECTION) + rowModel.addSelectionInterval(lo_row, hi_row); + else + rowModel.setSelectionInterval(lo_row, hi_row); + } + } + + if (table.getColumnSelectionAllowed()) + { + int lo_col = table.columnAtPoint(begin); + int hi_col = table.columnAtPoint(curr); + ListSelectionModel colModel = table.getColumnModel(). + getSelectionModel(); + if (lo_col != -1 && hi_col != -1) + { + if (controlPressed && colModel.getSelectionMode() != + ListSelectionModel.SINGLE_SELECTION) + colModel.addSelectionInterval(lo_col, hi_col); + else + colModel.setSelectionInterval(lo_col, hi_col); + } + } + } + + public void mouseClicked(MouseEvent e) + { + } + public void mouseDragged(MouseEvent e) + { + curr = new Point(e.getX(), e.getY()); + updateSelection(e.isControlDown()); + } + public void mouseEntered(MouseEvent e) + { + } + public void mouseExited(MouseEvent e) + { + } + public void mouseMoved(MouseEvent e) + { + } + public void mousePressed(MouseEvent e) + { + 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()); + + } + public void mouseReleased(MouseEvent e) + { + begin = null; + curr = null; + } + } + + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + public Dimension getMaximumSize(JComponent comp) + { + return getPreferredSize(comp); + } + + public Dimension getMinimumSize(JComponent comp) + { + return getPreferredSize(comp); + } + + public Dimension getPreferredSize(JComponent comp) + { + int width = table.getColumnModel().getTotalColumnWidth(); + int height = table.getRowCount() * table.getRowHeight(); + return new Dimension(width, height); + } + + 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")); + table.setOpaque(true); + + highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder"); + cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); + } + protected void installKeyboardActions() + { + } + + protected void installListeners() + { + table.addFocusListener(focusListener); + table.addKeyListener(keyListener); + table.addMouseListener(mouseInputListener); + table.addMouseMotionListener(mouseInputListener); + } + + protected void uninstallDefaults() + { + // TODO: this method used to do the following which is not + // quite right (at least it breaks apps that run fine with the + // JDK): + // + // table.setFont(null); + // table.setGridColor(null); + // table.setForeground(null); + // table.setBackground(null); + // table.setSelectionForeground(null); + // table.setSelectionBackground(null); + // + // This would leave the component in a corrupt state, which is + // not acceptable. A possible solution would be to have component + // level defaults installed, that get overridden by the UI defaults + // and get restored in this method. I am not quite sure about this + // though. / Roman Kennke + } + + protected void uninstallKeyboardActions() + { + } + + protected void uninstallListeners() + { + table.removeFocusListener(focusListener); + table.removeKeyListener(keyListener); + table.removeMouseListener(mouseInputListener); + table.removeMouseMotionListener(mouseInputListener); + } + + public void installUI(JComponent comp) + { + table = (JTable)comp; + focusListener = createFocusListener(); + keyListener = createKeyListener(); + mouseInputListener = createMouseInputListener(); + installDefaults(); + installKeyboardActions(); + installListeners(); + } + + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallKeyboardActions(); + uninstallDefaults(); + } + + public void paint(Graphics gfx, JComponent ignored) + { + int ncols = table.getColumnCount(); + int nrows = table.getRowCount(); + if (nrows == 0 || ncols == 0) + return; + + Rectangle clip = gfx.getClipBounds(); + TableColumnModel cols = table.getColumnModel(); + + int height = table.getRowHeight(); + int x0 = 0, y0 = 0; + int x = x0; + int y = y0; + + Dimension gap = table.getIntercellSpacing(); + int ymax = clip.y + clip.height; + int xmax = clip.x + clip.width; + + // paint the cell contents + for (int c = 0; c < ncols && x < xmax; ++c) + { + y = y0; + TableColumn col = cols.getColumn(c); + int width = col.getWidth(); + int modelCol = col.getModelIndex(); + + 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. + if (comp instanceof JComponent) + { + if (table.isCellSelected(r, c)) + ((JComponent) comp).setBorder(highlightCellBorder); + else + ((JComponent) comp).setBorder(cellBorder); + } + comp.paint(gfx); + gfx.translate(-x, -y); + } + y += height; + if (gap != null) + y += gap.height; + } + x += width; + if (gap != null) + x += gap.width; + } + + // tighten up the x and y max bounds + ymax = y; + xmax = x; + + Color grid = table.getGridColor(); + + // paint vertical grid lines + if (grid != null && table.getShowVerticalLines()) + { + x = x0; + Color save = gfx.getColor(); + gfx.setColor(grid); + boolean paintedLine = false; + for (int c = 0; c < ncols && x < xmax; ++c) + { + x += cols.getColumn(c).getWidth();; + if (gap != null) + x += gap.width; + gfx.drawLine(x, y0, x, ymax); + paintedLine = true; + } + gfx.setColor(save); + } + + // paint horizontal grid lines + if (grid != null && table.getShowHorizontalLines()) + { + y = y0; + Color save = gfx.getColor(); + gfx.setColor(grid); + boolean paintedLine = false; + 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; + } + gfx.setColor(save); + } + + } + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java new file mode 100644 index 0000000..97b0ccb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -0,0 +1,68 @@ +/* BasicTextAreaUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicTextAreaUI extends BasicTextUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicTextAreaUI(); + } + + public BasicTextAreaUI() + { + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "TextArea"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java new file mode 100644 index 0000000..a300446 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -0,0 +1,80 @@ +/* BasicTextFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.beans.PropertyChangeEvent; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.FieldView; +import javax.swing.text.View; + +public class BasicTextFieldUI extends BasicTextUI +{ + public BasicTextFieldUI() + { + super(); + } + + public View create(Element elem) + { + return new FieldView(elem); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicTextFieldUI(); + } + + protected String getPropertyPrefix() + { + return "TextField"; + } + + public void installUI(JComponent c) + { + super.installUI(c); + } + + protected void propertyChange(PropertyChangeEvent event) + { + // Does nothing by default. + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java new file mode 100644 index 0000000..55d908e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java @@ -0,0 +1,68 @@ +/* BasicTextPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicTextPaneUI extends BasicEditorPaneUI +{ + public BasicTextPaneUI() + { + // Do nothing here. + } + + public static ComponentUI createUI(JComponent comp) + { + return new BasicTextPaneUI(); + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "TextPane"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java new file mode 100644 index 0000000..dd0828e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java @@ -0,0 +1,635 @@ +/* BasicTextUI.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.TextUI; +import javax.swing.plaf.UIResource; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.DefaultCaret; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +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; + + +public abstract class BasicTextUI extends TextUI + implements ViewFactory +{ + public static class BasicCaret extends DefaultCaret + implements UIResource + { + public BasicCaret() + { + } + } + + public static class BasicHighlighter extends DefaultHighlighter + implements UIResource + { + public BasicHighlighter() + { + } + } + + private class RootView extends View + { + private View view; + + public RootView() + { + super(null); + } + + // View methods. + + public ViewFactory getViewFactory() + { + // FIXME: Handle EditorKit somehow. + return BasicTextUI.this; + } + + public void setView(View v) + { + if (view != null) + view.setParent(null); + + if (v != null) + v.setParent(null); + + view = v; + } + + public Container getContainer() + { + return textComponent; + } + + public float getPreferredSpan(int axis) + { + if (view != null) + return view.getPreferredSpan(axis); + + return Integer.MAX_VALUE; + } + + public void paint(Graphics g, Shape s) + { + if (view != null) + view.paint(g, s); + } + + public Shape modelToView(int position, Shape a, Position.Bias bias) + throws BadLocationException + { + if (view == null) + return null; + + return ((PlainView) view).modelToView(position, a, bias).getBounds(); + } + + /** + * Notification about text insertions. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.insertUpdate(ev, shape, vf); + } + + /** + * Notification about text removals. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.removeUpdate(ev, shape, vf); + } + + /** + * Notification about text changes. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.changedUpdate(ev, shape, vf); + } + } + + class UpdateHandler implements PropertyChangeListener + { + public void propertyChange(PropertyChangeEvent event) + { + if (event.getPropertyName().equals("document")) + { + // Document changed. + modelChanged(); + } + } + } + + /** + * Listens for changes on the underlying model and forwards notifications + * to the View. This also updates the caret position of the text component. + * + * TODO: Maybe this should somehow be handled through EditorKits + */ + class DocumentHandler implements DocumentListener + { + /** + * Notification about a document change event. + * + * @param ev the DocumentEvent describing the change + */ + public void changedUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + } + + /** + * Notification about a document insert event. + * + * @param ev the DocumentEvent describing the insertion + */ + public void insertUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + int caretPos = textComponent.getCaretPosition(); + if (caretPos >= ev.getOffset()) + textComponent.setCaretPosition(caretPos + ev.getLength()); + } + + /** + * Notification about a document removal event. + * + * @param ev the DocumentEvent describing the removal + */ + public void removeUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + int caretPos = textComponent.getCaretPosition(); + if (caretPos >= ev.getOffset()) + textComponent.setCaretPosition(ev.getOffset()); + } + } + + static EditorKit kit = new DefaultEditorKit(); + + RootView rootView = new RootView(); + JTextComponent textComponent; + UpdateHandler updateHandler = new UpdateHandler(); + + /** The DocumentEvent handler. */ + DocumentHandler documentHandler = new DocumentHandler(); + + public BasicTextUI() + { + } + + protected Caret createCaret() + { + return new BasicCaret(); + } + + protected Highlighter createHighlighter() + { + return new BasicHighlighter(); + } + + protected final JTextComponent getComponent() + { + return textComponent; + } + + public void installUI(final JComponent c) + { + super.installUI(c); + c.setOpaque(true); + + textComponent = (JTextComponent) c; + + Document doc = textComponent.getDocument(); + if (doc == null) + { + doc = getEditorKit(textComponent).createDefaultDocument(); + textComponent.setDocument(doc); + } + + textComponent.addPropertyChangeListener(updateHandler); + modelChanged(); + + installDefaults(); + installListeners(); + installKeyboardActions(); + } + + protected void installDefaults() + { + Caret caret = textComponent.getCaret(); + if (caret == null) + { + caret = createCaret(); + textComponent.setCaret(caret); + } + + Highlighter highlighter = textComponent.getHighlighter(); + if (highlighter == null) + 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")); + } + + private FocusListener focuslistener = new FocusListener() { + public void focusGained(FocusEvent e) + { + textComponent.repaint(); + } + public void focusLost(FocusEvent e) + { + textComponent.repaint(); + } + }; + + protected void installListeners() + { + textComponent.addFocusListener(focuslistener); + installDocumentListeners(); + } + + /** + * Installs the document listeners on the textComponent's model. + */ + private void installDocumentListeners() + { + Document doc = textComponent.getDocument(); + if (doc != null) + doc.addDocumentListener(documentHandler); + } + + /** + * Returns the name of the keymap for this type of TextUI. + * + * This is implemented so that the classname of this TextUI + * without the package prefix is returned. This way subclasses + * don't have to override this method. + * + * @return the name of the keymap for this TextUI + */ + protected String getKeymapName() + { + String fullClassName = getClass().getName(); + int index = fullClassName.lastIndexOf('.'); + String className = fullClassName.substring(index + 1); + return className; + } + + protected Keymap createKeymap() + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + JTextComponent.KeyBinding[] bindings = + (JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings"); + if (bindings == null) + { + bindings = new JTextComponent.KeyBinding[0]; + defaults.put(prefix + ".keyBindings", bindings); + } + + Keymap km = JTextComponent.addKeymap(getKeymapName(), + JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP)); + JTextComponent.loadKeymap(km, bindings, textComponent.getActions()); + return km; + } + + protected void installKeyboardActions() + { + // load any bindings for the older Keymap interface + Keymap km = JTextComponent.getKeymap(getKeymapName()); + if (km == null) + km = createKeymap(); + textComponent.setKeymap(km); + + // load any bindings for the newer InputMap / ActionMap interface + SwingUtilities.replaceUIInputMap(textComponent, + JComponent.WHEN_FOCUSED, + getInputMap(JComponent.WHEN_FOCUSED)); + SwingUtilities.replaceUIActionMap(textComponent, getActionMap()); + } + + InputMap getInputMap(int condition) + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + switch (condition) + { + case JComponent.WHEN_IN_FOCUSED_WINDOW: + // FIXME: is this the right string? nobody seems to use it. + return (InputMap) defaults.get(prefix + ".windowInputMap"); + case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: + return (InputMap) defaults.get(prefix + ".ancestorInputMap"); + default: + case JComponent.WHEN_FOCUSED: + return (InputMap) defaults.get(prefix + ".focusInputMap"); + } + } + + ActionMap getActionMap() + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap"); + if (am == null) + { + am = createActionMap(); + defaults.put(prefix + ".actionMap", am); + } + return am; + } + + ActionMap createActionMap() + { + Action[] actions = textComponent.getActions(); + ActionMap am = new ActionMapUIResource(); + for (int i = 0; i < actions.length; ++i) + { + String name = (String) actions[i].getValue(Action.NAME); + if (name != null) + am.put(name, actions[i]); + } + return am; + } + + public void uninstallUI(final JComponent component) + { + super.uninstallUI(component); + rootView.setView(null); + + textComponent.removePropertyChangeListener(updateHandler); + + uninstallDefaults(); + uninstallListeners(); + uninstallKeyboardActions(); + + textComponent = null; + } + + protected void uninstallDefaults() + { + // Do nothing here. + } + + protected void uninstallListeners() + { + textComponent.removeFocusListener(focuslistener); + } + + protected void uninstallKeyboardActions() + { + // Do nothing here. + } + + protected abstract String getPropertyPrefix(); + + public Dimension getPreferredSize(JComponent c) + { + View v = getRootView(textComponent); + + float w = v.getPreferredSpan(View.X_AXIS); + float h = v.getPreferredSpan(View.Y_AXIS); + + return new Dimension((int) w, (int) h); + } + + /** + * Returns the maximum size for text components that use this UI. + * + * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE). + * + * @return the maximum size for text components that use this UI + */ + public Dimension getMaximumSize(JComponent c) + { + // Sun's implementation returns Integer.MAX_VALUE here, so do we. + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public final void paint(Graphics g, JComponent c) + { + paintSafely(g); + } + + protected void paintSafely(Graphics g) + { + Caret caret = textComponent.getCaret(); + Highlighter highlighter = textComponent.getHighlighter(); + + if (textComponent.isOpaque()) + paintBackground(g); + + if (highlighter != null + && textComponent.getSelectionStart() != textComponent.getSelectionEnd()) + highlighter.paint(g); + + rootView.paint(g, getVisibleEditorRect()); + + if (caret != null && textComponent.hasFocus()) + caret.paint(g); + } + + protected void paintBackground(Graphics g) + { + g.setColor(textComponent.getBackground()); + g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); + } + + public void damageRange(JTextComponent t, int p0, int p1) + { + damageRange(t, p0, p1, null, null); + } + + public void damageRange(JTextComponent t, int p0, int p1, + Position.Bias firstBias, Position.Bias secondBias) + { + } + + public EditorKit getEditorKit(JTextComponent t) + { + return kit; + } + + public int getNextVisualPositionFrom(JTextComponent t, int pos, + Position.Bias b, int direction, + Position.Bias[] biasRet) + throws BadLocationException + { + return 0; + } + + public View getRootView(JTextComponent t) + { + return rootView; + } + + public Rectangle modelToView(JTextComponent t, int pos) + throws BadLocationException + { + return modelToView(t, pos, Position.Bias.Forward); + } + + public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) + throws BadLocationException + { + return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds(); + } + + public int viewToModel(JTextComponent t, Point pt) + { + return viewToModel(t, pt, null); + } + + public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn) + { + return 0; + } + + public View create(Element elem) + { + // Subclasses have to implement this to get this functionality. + return null; + } + + public View create(Element elem, int p0, int p1) + { + // Subclasses have to implement this to get this functionality. + return null; + } + + protected Rectangle getVisibleEditorRect() + { + int width = textComponent.getWidth(); + int height = textComponent.getHeight(); + + if (width <= 0 || height <= 0) + return null; + + Insets insets = textComponent.getInsets(); + return new Rectangle(insets.left, insets.top, + width - insets.left + insets.right, + height - insets.top + insets.bottom); + } + + protected final void setView(View view) + { + rootView.setView(view); + view.setParent(rootView); + } + + protected void modelChanged() + { + if (textComponent == null || rootView == null) + return; + ViewFactory factory = rootView.getViewFactory(); + if (factory == null) + return; + Document doc = textComponent.getDocument(); + if (doc == null) + return; + installDocumentListeners(); + Element elem = doc.getDefaultRootElement(); + if (elem == null) + return; + setView(factory.create(elem)); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java new file mode 100644 index 0000000..84509ad --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java @@ -0,0 +1,62 @@ +/* BasicToggleButtonUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +public class BasicToggleButtonUI extends BasicButtonUI +{ + public static ComponentUI createUI(final JComponent component) + { + return new BasicToggleButtonUI(); + } + + /** + * Returns the prefix for the UI defaults property for this UI class. + * This is 'ToggleButton' for this class. + * + * @return the prefix for the UI defaults property + */ + protected String getPropertyPrefix() + { + return "ToggleButton"; + } +} + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java new file mode 100644 index 0000000..db29fdc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java @@ -0,0 +1,127 @@ +/* BasicToolBarSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +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; + +/** + * The Basic Look and Feel UI delegate for Separator. + */ +public class BasicToolBarSeparatorUI extends BasicSeparatorUI +{ + private transient Dimension size; + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicToolBarSeparatorUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicToolBarSeparatorUI(); + } + + /** + * This method installs the defaults that are given by the Basic L&F. + * + * @param s The Separator that is being installed. + */ + protected void installDefaults(JSeparator s) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + size = defaults.getDimension("ToolBar.separatorSize"); + } + + /** + * This method does nothing as a Separator is just blank space. + * + * @param g The Graphics object to paint with + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + // Do nothing. + } + + /** + * This method returns the preferred size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return size; + } + + /** + * This method returns the minimum size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return size; + } + + /** + * This method returns the maximum size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return size; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java new file mode 100644 index 0000000..bc655a2 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java @@ -0,0 +1,1435 @@ +/* BasicToolBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JToolBar; +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; +import javax.swing.plaf.BorderUIResource.EtchedBorderUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ToolBarUI; +import javax.swing.plaf.UIResource; + +/** + * This is the Basic Look and Feel UI class for JToolBar. + */ +public class BasicToolBarUI extends ToolBarUI implements SwingConstants +{ + /** Static owner of all DragWindows. + * This is package-private to avoid an accessor method. */ + static JFrame owner = new JFrame(); + + /** The border used when the JToolBar is in nonrollover mode. */ + private static Border nonRolloverBorder; + + /** The border used when the JToolBar is in rollover mode. */ + private static Border rolloverBorder; + + /** The last known BorderLayout constraint before floating. */ + protected String constraintBeforeFloating; + + /** The last known orientation of the JToolBar before floating. + * This is package-private to avoid an accessor method. */ + int lastGoodOrientation; + + /** The color of the border when it is dockable. */ + protected Color dockingBorderColor; + + /** The background color of the JToolBar when it is dockable. */ + protected Color dockingColor; + + /** The docking listener responsible for mouse events on the JToolBar. */ + protected MouseInputListener dockingListener; + + /** The window used for dragging the JToolBar. */ + protected BasicToolBarUI.DragWindow dragWindow; + + /** The color of the border when it is not dockable. */ + protected Color floatingBorderColor; + + /** The background color of the JToolBar when it is not dockable. */ + protected Color floatingColor; + + /** The index of the focused component. */ + protected int focusedCompIndex; + + /** The PropertyChangeListener for the JToolBar. */ + protected PropertyChangeListener propertyListener; + + /** The JToolBar this UI delegate is responsible for. */ + protected JToolBar toolBar; + + /** The Container listener for the JToolBar. */ + protected ContainerListener toolBarContListener; + + /** The Focus listener for the JToolBar. */ + protected FocusListener toolBarFocusListener; + + /** + * The floating window that is responsible for holding the JToolBar when it + * is dragged outside of its original parent. + */ + private transient Window floatFrame; + + /** The original parent of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Container origParent; + + /** A hashtable of components and their original borders. + * This is package-private to avoid an accessor method. */ + transient Hashtable borders; + + /** A window listener for the floatable frame. */ + private transient WindowListener windowListener; + + /** A set of cached bounds of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Dimension cachedBounds; + + /** The cached orientation of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient int cachedOrientation; + + /** + * This method creates a new BasicToolBarUI object for the given JToolBar. + */ + public BasicToolBarUI() + { + // Do nothing here. + } + + /** + * This method returns whether the JToolBar can dock at the given position. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return Whether the JToolBar can dock. + */ + public boolean canDock(Component c, Point p) + { + return areaOfClick(c, p) != -1; + } + + /** + * This helper method returns the position of the JToolBar if it can dock. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return One of the SwingConstants directions or -1 if the JToolBar can't + * dock. + */ + private int areaOfClick(Component c, Point p) + { + // Has to dock in immediate parent, not eventual root container. + Rectangle pBounds = c.getBounds(); + + // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last. + Dimension d = toolBar.getSize(); + int limit = Math.min(d.width, d.height); + + // The order of checking is 1. top 2. bottom 3. left 4. right + if (! pBounds.contains(p)) + return -1; + + if (p.y < limit) + return SwingConstants.NORTH; + + if (p.y > (pBounds.height - limit)) + return SwingConstants.SOUTH; + + if (p.x < limit) + return SwingConstants.WEST; + + if (p.x > (pBounds.width - limit)) + return SwingConstants.EAST; + + return -1; + } + + /** + * This method creates a new DockingListener for the JToolBar. + * + * @return A new DockingListener for the JToolBar. + */ + protected MouseInputListener createDockingListener() + { + return new DockingListener(toolBar); + } + + /** + * This method creates a new DragWindow for the given JToolBar. + * + * @param toolbar The JToolBar to create a DragWindow for. + * + * @return A new DragWindow. + */ + protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar) + { + return new DragWindow(); + } + + /** + * This method creates a new floating frame for the JToolBar. By default, + * this UI uses createFloatingWindow instead. This method of creating a + * floating frame is deprecated. + * + * @param toolbar The JToolBar to create a floating frame for. + * + * @return A new floating frame. + */ + protected JFrame createFloatingFrame(JToolBar toolbar) + { + // FIXME: Though deprecated, this should still work. + return null; + } + + /** + * This method creates a new floating window for the JToolBar. This is the + * method used by default to create a floating container for the JToolBar. + * + * @param toolbar The JToolBar to create a floating window for. + * + * @return A new floating window. + */ + protected RootPaneContainer createFloatingWindow(JToolBar toolbar) + { + // This one is used by default though. + return new ToolBarDialog(); + } + + /** + * This method creates a new WindowListener for the JToolBar. + * + * @return A new WindowListener. + */ + protected WindowListener createFrameListener() + { + return new FrameListener(); + } + + /** + * This method creates a new nonRolloverBorder for JButtons when the + * JToolBar's rollover property is set to false. + * + * @return A new NonRolloverBorder. + */ + protected Border createNonRolloverBorder() + { + return new EtchedBorderUIResource(); + } + + /** + * This method creates a new PropertyChangeListener for the JToolBar. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyListener() + { + return new PropertyListener(); + } + + /** + * This method creates a new rollover border for JButtons when the + * JToolBar's rollover property is set to true. + * + * @return A new rollover border. + */ + protected Border createRolloverBorder() + { + return new EtchedBorderUIResource() + { + public void paintBorder(Component c, Graphics g, int x, int y, + int width, int height) + { + if (c instanceof JButton) + { + if (((JButton) c).getModel().isRollover()) + super.paintBorder(c, g, x, y, width, height); + } + } + }; + } + + /** + * This method creates a new Container listener for the JToolBar. + * + * @return A new Container listener. + */ + protected ContainerListener createToolBarContListener() + { + return new ToolBarContListener(); + } + + /** + * This method creates a new FocusListener for the JToolBar. + * + * @return A new FocusListener for the JToolBar. + */ + protected FocusListener createToolBarFocusListener() + { + return new ToolBarFocusListener(); + } + + /** + * This method creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a UI delegate for. + * + * @return A new UI delegate. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicToolBarUI(); + } + + /** + * This method is called to drag the DragWindow around when the JToolBar is + * being dragged around. + * + * @param position The mouse cursor coordinates relative to the JToolBar. + * @param origin The screen position of the JToolBar. + */ + protected void dragTo(Point position, Point origin) + { + int loc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, position, + origParent)); + + if (loc != -1) + { + dragWindow.setBorderColor(dockingBorderColor); + dragWindow.setBackground(dockingColor); + } + else + { + dragWindow.setBorderColor(floatingBorderColor); + dragWindow.setBackground(floatingColor); + } + + int w = 0; + int h = 0; + + boolean tmp = ((loc == SwingConstants.NORTH) + || (loc == SwingConstants.SOUTH) || (loc == -1)); + + if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp) + || ((cachedOrientation == VERTICAL) && ! tmp)) + { + w = cachedBounds.width; + h = cachedBounds.height; + } + else + { + w = cachedBounds.height; + h = cachedBounds.width; + } + + Point p = dragWindow.getOffset(); + Insets insets = toolBar.getInsets(); + + dragWindow.setBounds((origin.x + position.x) - p.x + - ((insets.left + insets.right) / 2), + (origin.y + position.y) - p.y + - ((insets.top + insets.bottom) / 2), w, h); + + if (! dragWindow.isVisible()) + dragWindow.show(); + } + + /** + * This method is used at the end of a drag session to place the frame in + * either its original parent as a docked JToolBar or in its floating + * frame. + * + * @param position The position of the mouse cursor relative to the + * JToolBar. + * @param origin The screen position of the JToolBar before the drag session + * started. + */ + protected void floatAt(Point position, Point origin) + { + Point p = new Point(position); + int aoc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, p, origParent)); + + Container oldParent = toolBar.getParent(); + + oldParent.remove(toolBar); + oldParent.doLayout(); + oldParent.repaint(); + + Container newParent; + + if (aoc == -1) + newParent = ((RootPaneContainer) floatFrame).getContentPane(); + else + { + floatFrame.hide(); + newParent = origParent; + } + + String constraint; + switch (aoc) + { + case SwingConstants.EAST: + constraint = BorderLayout.EAST; + break; + case SwingConstants.NORTH: + constraint = BorderLayout.NORTH; + break; + case SwingConstants.SOUTH: + constraint = BorderLayout.SOUTH; + break; + case SwingConstants.WEST: + constraint = BorderLayout.WEST; + break; + default: + constraint = BorderLayout.CENTER; + break; + } + + int newOrientation = SwingConstants.HORIZONTAL; + if ((aoc != -1) + && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST))) + newOrientation = SwingConstants.VERTICAL; + + if (aoc != -1) + { + constraintBeforeFloating = constraint; + lastGoodOrientation = newOrientation; + } + + newParent.add(toolBar, constraint); + + setFloating(aoc == -1, null); + toolBar.setOrientation(newOrientation); + + Insets insets = floatFrame.getInsets(); + Dimension dims = toolBar.getPreferredSize(); + p = dragWindow.getOffset(); + setFloatingLocation((position.x + origin.x) - p.x + - ((insets.left + insets.right) / 2), + (position.y + origin.y) - p.y + - ((insets.top + insets.bottom) / 2)); + + if (aoc == -1) + { + floatFrame.pack(); + floatFrame.setSize(dims.width + insets.left + insets.right, + dims.height + insets.top + insets.bottom); + floatFrame.show(); + } + + newParent.invalidate(); + newParent.validate(); + newParent.repaint(); + } + + /** + * This method returns the docking color. + * + * @return The docking color. + */ + public Color getDockingColor() + { + return dockingColor; + } + + /** + * This method returns the Color which is displayed when over a floating + * area. + * + * @return The color which is displayed when over a floating area. + */ + public Color getFloatingColor() + { + return floatingColor; + } + + /** + * This method returns the maximum size of the given JComponent for this UI. + * + * @param c The JComponent to find the maximum size for. + * + * @return The maximum size for this UI. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the given JComponent for this UI. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size for this UI. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the given JComponent for this + * UI. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size for this UI. + */ + public Dimension getPreferredSize(JComponent c) + { + return toolBar.getLayout().preferredLayoutSize(c); + } + + /** + * This method installs the needed components for the JToolBar. + */ + protected void installComponents() + { + floatFrame = (Window) createFloatingWindow(toolBar); + + dragWindow = createDragWindow(toolBar); + + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + + nonRolloverBorder = createNonRolloverBorder(); + rolloverBorder = createRolloverBorder(); + + borders = new Hashtable(); + + fillHashtable(); + } + + /** + * This method installs the defaults as specified by the look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + toolBar.setBorder(new ToolBarBorder()); + toolBar.setBackground(defaults.getColor("ToolBar.background")); + toolBar.setForeground(defaults.getColor("ToolBar.foreground")); + toolBar.setFont(defaults.getFont("ToolBar.font")); + + dockingBorderColor = defaults.getColor("ToolBar.dockingForeground"); + dockingColor = defaults.getColor("ToolBar.dockingBackground"); + + floatingBorderColor = defaults.getColor("ToolBar.floatingForeground"); + floatingColor = defaults.getColor("ToolBar.floatingBackground"); + } + + /** + * This method installs the keyboard actions for the JToolBar as specified + * by the look and feel. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs listeners for the JToolBar. + * + * @param toolbar The JToolBar to register listeners for. + */ + protected void installListeners(JToolBar toolbar) + { + dockingListener = createDockingListener(); + toolBar.addMouseListener(dockingListener); + toolBar.addMouseMotionListener(dockingListener); + + propertyListener = createPropertyListener(); + toolBar.addPropertyChangeListener(propertyListener); + + toolBarContListener = createToolBarContListener(); + toolBar.addContainerListener(toolBarContListener); + + windowListener = createFrameListener(); + floatFrame.addWindowListener(windowListener); + + toolBarFocusListener = createToolBarFocusListener(); + toolBar.addFocusListener(toolBarFocusListener); + } + + /** + * This method installs non rollover borders for each component inside the + * given JComponent. + * + * @param c The JComponent whose children need to have non rollover borders + * installed. + */ + protected void installNonRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNonRollover(components[i]); + } + + /** + * This method installs normal (or their original) borders for each + * component inside the given JComponent. + * + * @param c The JComponent whose children need to have their original + * borders installed. + */ + protected void installNormalBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNormal(components[i]); + } + + /** + * This method install rollover borders for each component inside the given + * JComponent. + * + * @param c The JComponent whose children need to have rollover borders + * installed. + */ + protected void installRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToRollover(components[i]); + } + + /** + * This method fills the borders hashtable with a list of components that + * are JButtons and their borders. + */ + private void fillHashtable() + { + Component[] c = toolBar.getComponents(); + + for (int i = 0; i < c.length; i++) + { + if (c[i] instanceof JButton) + { + // Don't really care about anything other than JButtons + JButton b = (JButton) c[i]; + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + } + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install a UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JToolBar) + { + toolBar = (JToolBar) c; + toolBar.setOpaque(true); + installDefaults(); + installComponents(); + installListeners(toolBar); + installKeyboardActions(); + } + } + + /** + * This method returns whether the JToolBar is floating. + * + * @return Whether the JToolBar is floating. + */ + public boolean isFloating() + { + return floatFrame.isVisible(); + } + + /** + * This method returns whether rollover borders have been set. + * + * @return Whether rollover borders have been set. + */ + public boolean isRolloverBorders() + { + return toolBar.isRollover(); + } + + /** + * This method navigates in the given direction giving focus to the next + * component in the given direction. + * + * @param direction The direction to give focus to. + */ + protected void navigateFocusedComp(int direction) + { + // FIXME: Implement. + } + + /** + * This method sets the border of the given component to a non rollover + * border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNonRollover(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + b.setRolloverEnabled(false); + b.setBorder(nonRolloverBorder); + } + } + + /** + * This method sets the border of the given component to its original value. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNormal(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + Border border = (Border) borders.get(b); + b.setBorder(border); + } + } + + /** + * This method sets the border of the given component to a rollover border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToRollover(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + b.setRolloverEnabled(true); + b.setBorder(rolloverBorder); + } + } + + /** + * This method sets the docking color. + * + * @param c The docking color. + */ + public void setDockingColor(Color c) + { + dockingColor = c; + } + + /** + * This method sets the floating property for the JToolBar. + * + * @param b Whether the JToolBar is floating. + * @param p FIXME + */ + public void setFloating(boolean b, Point p) + { + // FIXME: use p for something. It's not location + // since we already have setFloatingLocation. + floatFrame.setVisible(b); + } + + /** + * This method sets the color displayed when the JToolBar is not in a + * dockable area. + * + * @param c The floating color. + */ + public void setFloatingColor(Color c) + { + floatingColor = c; + } + + /** + * This method sets the floating location of the JToolBar. + * + * @param x The x coordinate for the floating frame. + * @param y The y coordinate for the floating frame. + */ + public void setFloatingLocation(int x, int y) + { + // x,y are the coordinates of the new JFrame created to store the toolbar + // XXX: The floating location is bogus is not floating. + floatFrame.setLocation(x, y); + floatFrame.invalidate(); + floatFrame.validate(); + floatFrame.repaint(); + } + + /** + * This is a convenience method for changing the orientation of the + * JToolBar. + * + * @param orientation The new orientation. + */ + public void setOrientation(int orientation) + { + toolBar.setOrientation(orientation); + } + + /** + * This method changes the child components to have rollover borders if the + * given parameter is true. Otherwise, the components are set to have non + * rollover borders. + * + * @param rollover Whether the children will have rollover borders. + */ + public void setRolloverBorders(boolean rollover) + { + if (rollover) + installRolloverBorders(toolBar); + else + installNonRolloverBorders(toolBar); + } + + /** + * This method uninstall UI installed components from the JToolBar. + */ + protected void uninstallComponents() + { + installNormalBorders(toolBar); + borders = null; + rolloverBorder = null; + nonRolloverBorder = null; + cachedBounds = null; + + floatFrame = null; + dragWindow = null; + } + + /** + * This method removes the defaults installed by the Look and Feel. + */ + protected void uninstallDefaults() + { + toolBar.setBackground(null); + toolBar.setForeground(null); + toolBar.setFont(null); + + dockingBorderColor = null; + dockingColor = null; + floatingBorderColor = null; + floatingColor = null; + } + + /** + * This method uninstalls keyboard actions installed by the UI. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls listeners installed by the UI. + */ + protected void uninstallListeners() + { + toolBar.removeFocusListener(toolBarFocusListener); + toolBarFocusListener = null; + + floatFrame.removeWindowListener(windowListener); + windowListener = null; + + toolBar.removeContainerListener(toolBarContListener); + toolBarContListener = null; + + toolBar.removeMouseMotionListener(dockingListener); + toolBar.removeMouseListener(dockingListener); + dockingListener = null; + } + + /** + * This method uninstalls the UI. + * + * @param c The JComponent that is having this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + toolBar = null; + } + + /** + * This is the MouseHandler class that allows the user to drag the JToolBar + * in and out of the parent and dock it if it can. + */ + public class DockingListener implements MouseInputListener + { + /** Whether the JToolBar is being dragged. */ + protected boolean isDragging; + + /** + * The origin point. This point is saved from the beginning press and is + * used until the end of the drag session. + */ + protected Point origin; + + /** The JToolBar being dragged. */ + protected JToolBar toolBar; + + /** + * Creates a new DockingListener object. + * + * @param t The JToolBar this DockingListener is being used for. + */ + public DockingListener(JToolBar t) + { + toolBar = t; + } + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // Don't care. + } + + /** + * This method is called when the mouse is dragged. It delegates the drag + * painting to the dragTo method. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + if (isDragging) + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse enters the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + // Don't care (yet). + } + + /** + * This method is called when the mouse exits the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + // Don't care (yet). + } + + /** + * This method is called when the mouse is moved in the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * This method is called when the mouse is pressed in the JToolBar. If the + * press doesn't occur in a place where it causes the JToolBar to be + * dragged, it returns. Otherwise, it starts a drag session. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + if (! toolBar.isFloatable()) + return; + + Point ssd = e.getPoint(); + Insets insets = toolBar.getInsets(); + + // Verify that this click occurs in the top inset. + if (toolBar.getOrientation() == SwingConstants.HORIZONTAL) + { + if (e.getX() > insets.left) + return; + } + else + { + if (e.getY() > insets.top) + return; + } + + origin = new Point(0, 0); + 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); + + isDragging = true; + + if (dragWindow != null) + dragWindow.setOffset(new Point(e.getX(), e.getY())); + + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse is released from the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (! isDragging || ! toolBar.isFloatable()) + return; + + isDragging = false; + floatAt(e.getPoint(), origin); + dragWindow.hide(); + } + } + + /** + * This is the window that appears when the JToolBar is being dragged + * around. + */ + protected class DragWindow extends Window + { + /** + * The current border color. It changes depending on whether the JToolBar + * is over a place that allows it to dock. + */ + private Color borderColor; + + /** The between the mouse and the top left corner of the window. */ + private Point offset; + + /** + * Creates a new DragWindow object. + * This is package-private to avoid an accessor method. + */ + DragWindow() + { + super(owner); + } + + /** + * The color that the border should be. + * + * @return The border color. + */ + public Color getBorderColor() + { + if (borderColor == null) + return Color.BLACK; + + return borderColor; + } + + /** + * This method returns the insets for the DragWindow. + * + * @return The insets for the DragWindow. + */ + public Insets getInsets() + { + // This window has no decorations, so insets are empty. + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns the mouse offset from the top left corner of the + * DragWindow. + * + * @return The mouse offset. + */ + public Point getOffset() + { + return offset; + } + + /** + * This method paints the DragWindow. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + // No visiting children necessary. + Color saved = g.getColor(); + Rectangle b = getBounds(); + + g.setColor(getBorderColor()); + g.drawRect(0, 0, b.width - 1, b.height - 1); + + g.setColor(saved); + } + + /** + * This method changes the border color. + * + * @param c The new border color. + */ + public void setBorderColor(Color c) + { + borderColor = c; + } + + /** + * This method changes the mouse offset. + * + * @param p The new mouse offset. + */ + public void setOffset(Point p) + { + offset = p; + } + + /** + * FIXME: Do something. + * + * @param o DOCUMENT ME! + */ + public void setOrientation(int o) + { + // FIXME: implement. + } + } + + /** + * This helper class listens for Window events from the floatable window and + * if it is closed, returns the JToolBar to the last known good location. + */ + protected class FrameListener extends WindowAdapter + { + /** + * This method is called when the floating window is closed. + * + * @param e The WindowEvent. + */ + public void windowClosing(WindowEvent e) + { + Container parent = toolBar.getParent(); + parent.remove(toolBar); + + if (origParent != null) + { + origParent.add(toolBar, + (constraintBeforeFloating != null) + ? constraintBeforeFloating : BorderLayout.NORTH); + toolBar.setOrientation(lastGoodOrientation); + } + + origParent.invalidate(); + origParent.validate(); + origParent.repaint(); + } + } + + /** + * This helper class listens for PropertyChangeEvents from the JToolBar. + */ + protected class PropertyListener implements PropertyChangeListener + { + /** + * This method is called when a property from the JToolBar is changed. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + // FIXME: need name properties so can change floatFrame title. + if (e.getPropertyName().equals("rollover")) + setRolloverBorders(toolBar.isRollover()); + } + } + + /** + * This helper class listens for components added to and removed from the + * JToolBar. + */ + protected class ToolBarContListener implements ContainerListener + { + /** + * This method is responsible for setting rollover or non rollover for new + * buttons added to the JToolBar. + * + * @param e The ContainerEvent. + */ + public void componentAdded(ContainerEvent e) + { + if (e.getChild() instanceof JButton) + { + JButton b = (JButton) e.getChild(); + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + + if (isRolloverBorders()) + setBorderToRollover(e.getChild()); + else + setBorderToNonRollover(e.getChild()); + + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + } + + /** + * This method is responsible for giving the child components their + * original borders when they are removed. + * + * @param e The ContainerEvent. + */ + public void componentRemoved(ContainerEvent e) + { + setBorderToNormal(e.getChild()); + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + } + } + + /** + * This is the floating window that is returned when getFloatingWindow is + * called. + */ + private class ToolBarDialog extends JDialog implements UIResource + { + /** + * Creates a new ToolBarDialog object with the name given by the JToolBar. + */ + public ToolBarDialog() + { + super(); + setName((toolBar.getName() != null) ? toolBar.getName() : ""); + } + } + + /** + * DOCUMENT ME! + */ + protected class ToolBarFocusListener implements FocusListener + { + /** + * Creates a new ToolBarFocusListener object. + */ + protected ToolBarFocusListener() + { + // FIXME: implement. + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void focusGained(FocusEvent e) + { + // FIXME: implement. + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void focusLost(FocusEvent e) + { + // FIXME: implement. + } + } + + /** + * This helper class acts as the border for the JToolBar. + */ + private static class ToolBarBorder implements Border + { + /** The size of the larger, draggable side of the border. */ + private static final int offset = 10; + + /** The other sides. */ + private static final int regular = 2; + + /** + * This method returns the border insets for the JToolBar. + * + * @param c The Component to find insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + int orientation = tb.getOrientation(); + + if (! tb.isFloatable()) + return new Insets(regular, regular, regular, regular); + else if (orientation == SwingConstants.HORIZONTAL) + return new Insets(regular, offset, regular, regular); + else + return new Insets(offset, regular, regular, regular); + } + + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return false; + } + + /** + * This method paints the ribbed area of the border. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate of the area. + * @param y The y coordinate of the area. + * @param w The width of the area. + * @param h The height of the area. + * @param size The size of the bump. + * @param c The color of the bumps. + */ + private void paintBumps(Graphics g, int x, int y, int w, int h, int size, + Color c) + { + Color saved = g.getColor(); + g.setColor(c); + + int hgap = 2 * size; + int vgap = 4 * size; + int count = 0; + + for (int i = x; i < (w + x); i += hgap) + for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y); + j += vgap) + g.fillRect(i, j, size, size); + + g.setColor(saved); + } + + /** + * This method paints the border around the given Component. + * + * @param c The Component whose border is being painted. + * @param g The Graphics object to paint with. + * @param x The x coordinate of the component. + * @param y The y coordinate of the component. + * @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) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + + int orientation = tb.getOrientation(); + + if (orientation == SwingConstants.HORIZONTAL) + { + paintBumps(g, x, y, offset, height, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY); + } + else + { + paintBumps(g, x, y, width, offset, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY); + } + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java new file mode 100644 index 0000000..b7a08aa --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java @@ -0,0 +1,288 @@ +/* BasicToolTipUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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 javax.swing.JComponent; +import javax.swing.JToolTip; +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; + +/** + * This is the Basic Look and Feel UI class for JToolTip. + */ +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); + } + + /** + * 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; + + /** + * Creates a new BasicToolTipUI object. + */ + public BasicToolTipUI() + { + super(); + } + + /** + * This method creates a new BasicToolTip UI for the given + * JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A BasicToolTipUI that can be used by the given JComponent. + */ + public static ComponentUI createUI(JComponent c) + { + if (shared == null) + shared = new BasicToolTipUI(); + return shared; + } + + /** + * This method returns the msximum size of the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + JToolTip tip = (JToolTip) c; + 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, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, vr, ir, tr, 0); + return new Dimension(insets.left + tr.width + insets.right, + insets.top + tr.height + insets.bottom); + } + + /** + * This method installs the defaults for the given JComponent. + * + * @param c The JComponent to install defaults for. + */ + 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); + } + + /** + * This method installs the listeners for the given JComponent. + * + * @param c The JComponent to install listeners for. + */ + protected void installListeners(JComponent c) + { + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + c.setOpaque(true); + installDefaults(c); + installListeners(c); + } + + /** + * This method paints the given JComponent with the given Graphics object. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + JToolTip tip = (JToolTip) c; + + String text = tip.getTipText(); + if (text == null) + return; + + Rectangle vr = new Rectangle(); + 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, + 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.setColor(saved); + } + + /** + * This method uninstalls the defaults for the given JComponent. + * + * @param c The JComponent to uninstall defaults for. + */ + protected void uninstallDefaults(JComponent c) + { + c.setForeground(null); + c.setBackground(null); + c.setFont(null); + c.setBorder(null); + } + + /** + * This method uninstalls listeners for the given JComponent. + * + * @param c The JComponent to uninstall listeners for. + */ + protected void uninstallListeners(JComponent c) + { + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(c); + uninstallListeners(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java new file mode 100644 index 0000000..b9d3b62 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -0,0 +1,2813 @@ +/* BasicTreeUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.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.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.CellRendererPane; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.MouseInputListener; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TreeUI; +import javax.swing.tree.AbstractLayoutCache; +import javax.swing.tree.FixedHeightLayoutCache; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellEditor; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeSelectionModel; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * A delegate providing the user interface for JTree according to + * the Basic look and feel. + * + * @see javax.swing.JTree + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Lillian Angel (langel@redhat.com) + */ +public class BasicTreeUI + extends TreeUI +{ + + /** Collapse Icon for the tree. */ + protected transient Icon collapsedIcon; + + /** Expanded Icon for the tree. */ + protected transient Icon expandedIcon; + + /** Distance between left margin and where vertical dashes will be drawn. */ + protected int leftChildIndent; + + /** + * Distance between leftChildIndent and where cell contents will be drawn. + */ + protected int rightChildIndent; + + /** + * Total fistance that will be indented. The sum of leftChildIndent and + * rightChildIndent . + */ + protected int totalChildIndent; + + /** Minimum preferred size. */ + protected Dimension preferredMinsize; + + /** Index of the row that was last selected. */ + protected int lastSelectedRow; + + /** Component that we're going to be drawing onto. */ + protected JTree tree; + + /** Renderer that is being used to do the actual cell drawing. */ + protected transient TreeCellRenderer currentCellRenderer; + + /** + * Set to true if the renderer that is currently in the tree was created by + * this instance. + */ + protected boolean createdRenderer; + + /** Editor for the tree. */ + protected transient TreeCellEditor cellEditor; + + /** + * Set to true if editor that is currently in the tree was created by this + * instance. + */ + protected boolean createdCellEditor; + + /** + * Set to false when editing and shouldSelectCall() returns true meaning the + * node should be selected before editing, used in completeEditing. + */ + protected boolean stopEditingInCompleteEditing; + + /** Used to paint the TreeCellRenderer. */ + protected CellRendererPane rendererPane; + + /** Size needed to completely display all the nodes. */ + protected Dimension preferredSize; + + /** Is the preferredSize valid? */ + protected boolean validCachedPreferredSize; + + /** Object responsible for handling sizing and expanded issues. */ + protected AbstractLayoutCache treeState; + + /** Used for minimizing the drawing of vertical lines. */ + protected Hashtable drawingCache; + + /** + * True if doing optimizations for a largeModel. Subclasses that don't + * support this may wish to override createLayoutCache to not return a + * FixedHeightLayoutCache instance. + */ + protected boolean largeModel; + + /** Responsible for telling the TreeState the size needed for a node. */ + protected AbstractLayoutCache.NodeDimensions nodeDimensions; + + /** Used to determine what to display. */ + protected TreeModel treeModel; + + /** Model maintaining the selection. */ + protected TreeSelectionModel treeSelectionModel; + + /** + * How much the depth should be offset to properly calculate x locations. + * This is based on whether or not the root is visible, and if the root + * handles are visible. + */ + protected int depthOffset; + + /** + * When editing, this will be the Component that is doing the actual editing. + */ + protected Component editingComponent; + + /** Path that is being edited. */ + protected TreePath editingPath; + + /** + * Row that is being edited. Should only be referenced if editingComponent is + * null. + */ + protected int editingRow; + + /** Set to true if the editor has a different size than the renderer. */ + protected boolean editorHasDifferentSize; + + /** Listeners */ + private PropertyChangeListener propertyChangeListener; + + private FocusListener focusListener; + + private TreeSelectionListener treeSelectionListener; + + private MouseInputListener mouseInputListener; + + private KeyListener keyListener; + + private PropertyChangeListener selectionModelPropertyChangeListener; + + private ComponentListener componentListener; + + private CellEditorListener cellEditorListener; + + private TreeExpansionListener treeExpansionListener; + + private TreeModelListener treeModelListener; + + /** + * Creates a new BasicTreeUI object. + */ + public BasicTreeUI() + { + drawingCache = new Hashtable(); + cellEditor = createDefaultCellEditor(); + currentCellRenderer = createDefaultCellRenderer(); + nodeDimensions = createNodeDimensions(); + rendererPane = createCellRendererPane(); + configureLayoutCache(); + + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + treeSelectionListener = createTreeSelectionListener(); + mouseInputListener = new MouseInputHandler(null, null, null); + keyListener = createKeyListener(); + selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); + componentListener = createComponentListener(); + cellEditorListener = createCellEditorListener(); + treeExpansionListener = createTreeExpansionListener(); + treeModelListener = createTreeModelListener(); + + createdRenderer = true; + createdCellEditor = true; + editingRow = -1; + lastSelectedRow = -1; + } + + /** + * Returns an instance of the UI delegate for the specified component. + * + * @param c the JComponent for which we need a UI delegate + * for. + * @return the ComponentUI for c. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicTreeUI(); + } + + /** + * Returns the Hash color. + * + * @return the Color of the Hash. + */ + protected Color getHashColor() + { + return UIManager.getLookAndFeelDefaults().getColor("Tree.hash"); + } + + /** + * Sets the Hash color. + * + * @param the Color to set the Hash to. + */ + protected void setHashColor(Color color) + { + // FIXME: not implemented + + } + + /** + * Sets the left child's indent value. + * + * @param newAmount is the new indent value for the left child. + */ + public void setLeftChildIndent(int newAmount) + { + leftChildIndent = newAmount; + } + + /** + * Returns the indent value for the left child. + * + * @return the indent value for the left child. + */ + public int getLeftChildIndent(int newAmount) + { + return leftChildIndent; + } + + /** + * Sets the right child's indent value. + * + * @param newAmount is the new indent value for the right child. + */ + public void setRightChildIndent(int newAmount) + { + rightChildIndent = newAmount; + } + + /** + * Returns the indent value for the right child. + * + * @return the indent value for the right child. + */ + public int getRightChildIndent(int newAmount) + { + return rightChildIndent; + } + + /** + * Sets the expanded icon. + * + * @param newG is the new expanded icon. + */ + public void setExpandedIcon(Icon newG) + { + expandedIcon = newG; + } + + /** + * Returns the current expanded icon. + * + * @return the current expanded icon. + */ + public Icon getExpandedIcon() + { + return expandedIcon; + } + + /** + * Sets the collapsed icon. + * + * @param newG is the new collapsed icon. + */ + public void setCollapsedIcon(Icon newG) + { + collapsedIcon = newG; + } + + /** + * Returns the current collapsed icon. + * + * @return the current collapsed icon. + */ + public Icon getCollapsedIcon() + { + return collapsedIcon; + } + + /** + * Updates the componentListener, if necessary. + * + * @param largeModel sets this.largeModel to it. + */ + protected void setLargeModel(boolean largeModel) + { + if (largeModel != this.largeModel) + { + tree.removeComponentListener(componentListener); + this.largeModel = largeModel; + tree.addComponentListener(componentListener); + } + } + + /** + * Returns true if largeModel is set + * + * @return true if largeModel is set, otherwise false. + */ + protected boolean isLargeModel() + { + return largeModel; + } + + /** + * Sets the row height. + * + * @param rowHeight is the height to set this.rowHeight to. + */ + protected void setRowHeight(int rowHeight) + { + treeState.setRowHeight(rowHeight); + } + + /** + * Returns the current row height. + * + * @return current row height. + */ + protected int getRowHeight() + { + return treeState.getRowHeight(); + } + + /** + * Sets the TreeCellRenderer to tcr. This invokes + * updateRenderer. + * + * @param tcr is the new TreeCellRenderer. + */ + protected void setCellRenderer(TreeCellRenderer tcr) + { + currentCellRenderer = tcr; + updateRenderer(); + } + + /** + * Return currentCellRenderer, which will either be the trees renderer, or + * defaultCellRenderer, which ever was not null. + * + * @return the current Cell Renderer + */ + protected TreeCellRenderer getCellRenderer() + { + if (currentCellRenderer != null) + return currentCellRenderer; + + return createDefaultCellRenderer(); + } + + /** + * Sets the tree's model. + * + * @param model to set the treeModel to. + */ + protected void setModel(TreeModel model) + { + treeState.setModel(model); + treeModel = model; + } + + /** + * Returns the tree's model + * + * @return treeModel + */ + protected TreeModel getModel() + { + return treeModel; + } + + /** + * Sets the root to being visible. + * + * @param newValue sets the visibility of the root + */ + protected void setRootVisible(boolean newValue) + { + treeState.setRootVisible(newValue); + } + + /** + * Returns true if the root is visible. + * + * @return true if the root is visible. + */ + protected boolean isRootVisible() + { + return treeState.isRootVisible(); + } + + /** + * Determines whether the node handles are to be displayed. + * + * @param newValue sets whether or not node handles should be displayed. + */ + protected void setShowsRootHandles(boolean newValue) + { + tree.setShowsRootHandles(newValue); + } + + /** + * Returns true if the node handles are to be displayed. + * + * @return true if the node handles are to be displayed. + */ + protected boolean getShowsRootHandles() + { + return tree.getShowsRootHandles(); + } + + /** + * Sets the cell editor. + * + * @param editor to set the cellEditor to. + */ + protected void setCellEditor(TreeCellEditor editor) + { + cellEditor = editor; + } + + /** + * Returns the TreeCellEditor for this tree. + * + * @return the cellEditor for this tree. + */ + protected TreeCellEditor getCellEditor() + { + return cellEditor; + } + + /** + * Configures the receiver to allow, or not allow, editing. + * + * @param newValue sets the receiver to allow editing if true. + */ + protected void setEditable(boolean newValue) + { + tree.setEditable(newValue); + } + + /** + * Returns true if the receiver allows editing. + * + * @return true if the receiver allows editing. + */ + protected boolean isEditable() + { + return tree.isEditable(); + } + + /** + * Resets the selection model. The appropriate listeners are installed on the + * model. + * + * @param newLSM resets the selection model. + */ + protected void setSelectionModel(TreeSelectionModel newLSM) + { + if (newLSM != null) + { + treeSelectionModel = newLSM; + tree.setSelectionModel(treeSelectionModel); + } + } + + /** + * Returns the current selection model. + * + * @return the current selection model. + */ + protected TreeSelectionModel getSelectionModel() + { + return treeSelectionModel; + } + + /** + * Returns the Rectangle enclosing the label portion that the last item in + * path will be drawn to. Will return null if any component in path is + * currently valid. + * + * @param tree is the current tree the path will be drawn to. + * @param path is the current path the tree to draw to. + * @return the Rectangle enclosing the label portion that the last item in + * the path will be drawn to. + */ + public Rectangle getPathBounds(JTree tree, TreePath path) + { + Object cell = path.getLastPathComponent(); + TreeModel mod = tree.getModel(); + Point loc = getCellLocation(0, 0, tree, mod, cell, mod.getRoot()); + int x = (int) loc.getX(); + int y = (int) loc.getY(); + return getCellBounds(x, y, cell); + } + + /** + * Returns the path for passed in row. If row is not visible null is + * returned. + * + * @param tree is the current tree to return path for. + * @param row is the row number of the row to return. + * @return the path for passed in row. If row is not visible null is + * returned. + */ + public TreePath getPathForRow(JTree tree, int row) + { + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + + for (int i = 0; i < row; i++) + node = getNextVisibleNode(node); + + // in case nothing was found + if (node == null) + return null; + + // something was found + return new TreePath(node.getPath()); + } + + /** + * 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. + */ + DefaultMutableTreeNode getNextVisibleNode(DefaultMutableTreeNode node) + { + DefaultMutableTreeNode next = null; + TreePath current = null; + + if (node != null) + next = node.getNextNode(); + + if (next != null) + { + current = new TreePath(next.getPath()); + if (tree.isVisible(current)) + return next; + + while (next != null && !tree.isVisible(current)) + { + next = next.getNextNode(); + + if (next != null) + current = new TreePath(next.getPath()); + } + } + return next; + } + + /** + * Get previous 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. + */ + DefaultMutableTreeNode getPreviousVisibleNode + (DefaultMutableTreeNode node) + { + DefaultMutableTreeNode prev = null; + TreePath current = null; + + if (node != null) + prev = node.getPreviousNode(); + + if (prev != null) + { + current = new TreePath(prev.getPath()); + if (tree.isVisible(current)) + return prev; + + while (prev != null && !tree.isVisible(current)) + { + prev = prev.getPreviousNode(); + + if (prev != null) + current = new TreePath(prev.getPath()); + } + } + return prev; + } + + /** + * Returns the row that the last item identified in path is visible at. Will + * return -1 if any of the elments in the path are not currently visible. + * + * @param tree is the current tree to return the row for. + * @param path is the path used to find the row. + * @return the row that the last item identified in path is visible at. Will + * return -1 if any of the elments in the path are not currently + * visible. + */ + public int getRowForPath(JTree tree, TreePath path) + { + // FIXME: check visibility + // right now, just returns last element because + // expand/collapse is not implemented + return path.getPathCount() - 1; + } + + /** + * Returns the number of rows that are being displayed. + * + * @param tree is the current tree to return the number of rows for. + * @return the number of rows being displayed. + */ + public int getRowCount(JTree tree) + { + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + int count = 0; + + while (node != null) + { + count++; + node = getNextVisibleNode(node); + } + + return count; + } + + /** + * Returns the path to the node that is closest to x,y. If there is nothing + * currently visible this will return null, otherwise it'll always return a + * valid path. If you need to test if the returned object is exactly at x,y + * you should get the bounds for the returned path and test x,y against that. + * + * @param tree the tree to search for the closest path + * @param x is the x coordinate of the location to search + * @param y is the y coordinate of the location to search + * @return the tree path closes to x,y. + */ + public TreePath getClosestPathForLocation(JTree tree, int x, int y) + { + return treeState.getPathClosestTo(x, y); + } + + /** + * Returns true if the tree is being edited. The item that is being edited + * can be returned by getEditingPath(). + * + * @param tree is the tree to check for editing. + * @return true if the tree is being edited. + */ + public boolean isEditing(JTree tree) + { + // FIXME: not implemented + return false; + } + + /** + * Stops the current editing session. This has no effect if the tree is not + * being edited. Returns true if the editor allows the editing session to + * stop. + * + * @param tree is the tree to stop the editing on + * @return true if the editor allows the editing session to stop. + */ + public boolean stopEditing(JTree tree) + { + // FIXME: not implemented + return false; + } + + /** + * Cancels the current editing session. + * + * @param tree is the tree to cancel the editing session on. + */ + public void cancelEditing(JTree tree) + { + // FIXME: not implemented + } + + /** + * Selects the last item in path and tries to edit it. Editing will fail if + * the CellEditor won't allow it for the selected item. + * + * @param tree is the tree to edit on. + * @param path is the path in tree to edit on. + */ + public void startEditingAtPath(JTree tree, TreePath path) + { + // FIXME: not implemented + } + + /** + * Returns the path to the element that is being editted. + * + * @param tree is the tree to get the editing path from. + * @return the path that is being edited. + */ + public TreePath getEditingPath(JTree tree) + { + // FIXME: not implemented + return null; + } + + /** + * Invoked after the tree instance variable has been set, but before any + * default/listeners have been installed. + */ + protected void prepareForUIInstall() + { + // FIXME: not implemented + } + + /** + * Invoked from installUI after all the defaults/listeners have been + * installed. + */ + protected void completeUIInstall() + { + // FIXME: not implemented + } + + /** + * Invoked from uninstallUI after all the defaults/listeners have been + * uninstalled. + */ + protected void completeUIUninstall() + { + // FIXME: not implemented + } + + /** + * Installs the subcomponents of the tree, which is the renderer pane. + */ + protected void installComponents() + { + // FIXME: not implemented + } + + /** + * Creates an instance of NodeDimensions that is able to determine the size + * of a given node in the tree. + * + * @return the NodeDimensions of a given node in the tree + */ + protected AbstractLayoutCache.NodeDimensions createNodeDimensions() + { + // FIXME: not implemented + return null; + } + + /** + * Creates a listener that is reponsible for the updates the UI based on how + * the tree changes. + * + * @return the PropertyChangeListener that is reposnsible for the updates + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates the listener responsible for updating the selection based on mouse + * events. + * + * @return the MouseListener responsible for updating. + */ + protected MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * Creates the listener that is responsible for updating the display when + * focus is lost/grained. + * + * @return the FocusListener responsible for updating. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * Creates the listener reponsible for getting key events from the tree. + * + * @return the KeyListener responsible for getting key events. + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + + /** + * Creates the listener responsible for getting property change events from + * the selection model. + * + * @returns the PropertyChangeListener reponsible for getting property change + * events from the selection model. + */ + protected PropertyChangeListener createSelectionModelPropertyChangeListener() + { + return new SelectionModelPropertyChangeHandler(); + } + + /** + * Creates the listener that updates the display based on selection change + * methods. + * + * @return the TreeSelectionListener responsible for updating. + */ + protected TreeSelectionListener createTreeSelectionListener() + { + return new TreeSelectionHandler(); + } + + /** + * Creates a listener to handle events from the current editor + * + * @return the CellEditorListener that handles events from the current editor + */ + protected CellEditorListener createCellEditorListener() + { + return new CellEditorHandler(); + } + + /** + * Creates and returns a new ComponentHandler. This is used for the large + * model to mark the validCachedPreferredSize as invalid when the component + * moves. + * + * @return a new ComponentHandler. + */ + protected ComponentListener createComponentListener() + { + return new ComponentHandler(); + } + + /** + * Creates and returns the object responsible for updating the treestate when + * a nodes expanded state changes. + * + * @return the TreeExpansionListener responsible for updating the treestate + */ + protected TreeExpansionListener createTreeExpansionListener() + { + return new TreeExpansionHandler(); + } + + /** + * Creates the object responsible for managing what is expanded, as well as + * the size of nodes. + * + * @return the object responsible for managing what is expanded. + */ + protected AbstractLayoutCache createLayoutCache() + { + return new FixedHeightLayoutCache(); + } + + /** + * Returns the renderer pane that renderer components are placed in. + * + * @return the rendererpane that render components are placed in. + */ + protected CellRendererPane createCellRendererPane() + { + return new CellRendererPane(); + } + + /** + * Creates a default cell editor. + * + * @return the default cell editor. + */ + protected TreeCellEditor createDefaultCellEditor() + { + return new DefaultTreeCellEditor(tree, + (DefaultTreeCellRenderer) createDefaultCellRenderer(), cellEditor); + } + + /** + * Returns the default cell renderer that is used to do the stamping of each + * node. + * + * @return the default cell renderer that is used to do the stamping of each + * node. + */ + protected TreeCellRenderer createDefaultCellRenderer() + { + return new DefaultTreeCellRenderer(); + } + + /** + * Returns a listener that can update the tree when the model changes. + * + * @return a listener that can update the tree when the model changes. + */ + protected TreeModelListener createTreeModelListener() + { + return new TreeModelHandler(); + } + + /** + * Uninstall all registered listeners + */ + protected void uninstallListeners() + { + tree.removePropertyChangeListener(propertyChangeListener); + tree.removeFocusListener(focusListener); + tree.removeTreeSelectionListener(treeSelectionListener); + tree.removeMouseListener(mouseInputListener); + tree.removeKeyListener(keyListener); + tree.removePropertyChangeListener(selectionModelPropertyChangeListener); + tree.removeComponentListener(componentListener); + tree.getCellEditor().removeCellEditorListener(cellEditorListener); + tree.removeTreeExpansionListener(treeExpansionListener); + tree.getModel().removeTreeModelListener(treeModelListener); + } + + /** + * Uninstall all keyboard actions. + */ + protected void uninstallKeyboardActions() + { + } + + /** + * Uninstall the rendererPane. + */ + protected void uninstallComponents() + { + // FIXME: not implemented + } + + /** + * The vertical element of legs between nodes starts at the bottom of the + * parent node by default. This method makes the leg start below that. + * + * @return the vertical leg buffer + */ + protected int getVerticalLegBuffer() + { + // FIXME: not implemented + return 0; + } + + /** + * 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. + * + * @return the horizontal leg buffer + */ + protected int getHorizontalLegBuffer() + { + // FIXME: not implemented + return 0; + } + + /** + * Make all the nodes that are expanded in JTree expanded in LayoutCache. + * This invokes update ExpandedDescendants with the root path. + */ + protected void updateLayoutCacheExpandedNodes() + { + // FIXME: not implemented + } + + /** + * Updates the expanded state of all the descendants of the path + * by getting the expanded descendants from the tree and forwarding to the + * tree state. + * + * @param path the path used to update the expanded states + */ + protected void updateExpandedDescendants(TreePath path) + { + // FIXME: not implemented + } + + /** + * Returns a path to the last child of parent + * + * @param parent is the topmost path to specified + * @return a path to the last child of parent + */ + protected TreePath getLastChildPath(TreePath parent) + { + return ((TreePath) parent.getLastPathComponent()); + } + + /** + * Updates how much each depth should be offset by. + */ + protected void updateDepthOffset() + { + // FIXME: not implemented + } + + /** + * Updates the cellEditor based on editability of the JTree that we're + * contained in. Ig the tree is editable but doesn't have a cellEditor, a + * basic one will be used. + */ + protected void updateCellEditor() + { + // FIXME: not implemented + } + + /** + * Messaged from the tree we're in when the renderer has changed. + */ + protected void updateRenderer() + { + // FIXME: not implemented + } + + /** + * Resets the treeState instance based on the tree we're providing the look + * and feel for. + */ + protected void configureLayoutCache() + { + treeState = createLayoutCache(); + } + + /** + * Marks the cached size as being invalid, and messages the tree with + * treeDidChange. + */ + protected void updateSize() + { + // FIXME: not implemented + } + + /** + * Updates the preferredSize instance variable, which is + * returned from getPreferredSize(). 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. + */ + protected void updateCachedPreferredSize() + { + // FIXME: not implemented + } + + /** + * Messaged from the VisibleTreeNode after it has been expanded. + * + * @param path is the path that has been expanded. + */ + protected void pathWasExpanded(TreePath path) + { + // FIXME: not implemented + } + + /** + * Messaged from the VisibleTreeNode after it has collapsed + */ + protected void pathWasCollapsed(TreePath path) + { + // FIXME: not implemented + } + + /** + * Install all defaults for the tree. + * + * @param tree is the JTree to install defaults for + */ + protected void installDefaults(JTree tree) + { + 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); + + rightChildIndent = defaults.getInt("Tree.rightChildIndent"); + leftChildIndent = defaults.getInt("Tree.leftChildIndent"); + setRowHeight(defaults.getInt("Tree.rowHeight")); + } + + /** + * Install all keyboard actions for this + */ + protected void installKeyboardActions() + { + } + + /** + * Install all listeners for this + */ + protected void installListeners() + { + tree.addPropertyChangeListener(propertyChangeListener); + tree.addFocusListener(focusListener); + tree.addTreeSelectionListener(treeSelectionListener); + tree.addMouseListener(mouseInputListener); + tree.addKeyListener(keyListener); + tree.addPropertyChangeListener(selectionModelPropertyChangeListener); + tree.addComponentListener(componentListener); + cellEditor.addCellEditorListener(cellEditorListener); + tree.addTreeExpansionListener(treeExpansionListener); + treeModel.addTreeModelListener(treeModelListener); + } + + /** + * Install the UI for the component + * + * @param c the component to install UI for + */ + public void installUI(JComponent c) + { + super.installUI(c); + installDefaults((JTree) c); + tree = (JTree) c; + setModel(tree.getModel()); + tree.setRootVisible(true); + tree.expandPath(new TreePath(((DefaultMutableTreeNode) + (tree.getModel()).getRoot()).getPath())); + treeSelectionModel = tree.getSelectionModel(); + installListeners(); + installKeyboardActions(); + completeUIInstall(); + } + + /** + * Uninstall the defaults for the tree + * + * @param tree to uninstall defaults for + */ + protected void uninstallDefaults(JTree tree) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + tree.setFont(null); + tree.setForeground(null); + tree.setBackground(null); + tree.setCellRenderer(null); + } + + /** + * Uninstall the UI for the component + * + * @param c the component to uninstall UI for + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults((JTree) c); + uninstallKeyboardActions(); + uninstallListeners(); + tree = null; + completeUIUninstall(); + } + + /** + * 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 Graphics context in which to paint + * @param c the component being painted; this argument is often ignored, but + * might be used if the UI object is stateless and shared by multiple + * components + */ + public void paint(Graphics g, JComponent c) + { + JTree tree = (JTree) c; + TreeModel mod = tree.getModel(); + g.translate(10, 10); + paintRecursive(g, 0, 0, 0, 0, tree, mod, mod.getRoot()); + paintControlIcons(g, 0, 0, 0, 0, tree, mod, mod.getRoot()); + g.translate(-10, -10); + } + + /** + * Ensures that the rows identified by beginRow through endRow are visible. + * + * @param beginRow is the first row + * @param endRow is the last row + */ + protected void ensureRowsAreVisible(int beginRow, int endRow) + { + // FIXME: not implemented + } + + /** + * Sets the preferred minimum size. + * + * @param newSize is the new preferred minimum size. + */ + public void setPreferredMinSize(Dimension newSize) + { + // FIXME: not implemented + } + + /** + * Gets the preferred minimum size. + * + * @returns the preferred minimum size. + */ + public Dimension getPreferredMinSize() + { + // FIXME: not implemented + return null; + } + + /** + * Returns the preferred size to properly display the tree, this is a cover + * method for getPreferredSize(c, false). + * + * @param c the component whose preferred size is being queried; this + * argument is often ignored but might be used if the UI object is + * stateless and shared by multiple components + * @return the preferred size + */ + public Dimension getPreferredSize(JComponent c) + { + return getPreferredSize(c, false); + } + + /** + * Returns the preferred size to represent the tree in c. If checkConsistancy + * is true, checkConsistancy is messaged first. + * + * @param c the component whose preferred size is being queried. + * @param checkConsistancy if true must check consistancy + * @return the preferred size + */ + public Dimension getPreferredSize(JComponent c, boolean checkConsistancy) + { + // FIXME: checkConsistancy not implemented, c not used + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + int maxWidth = 0; + int count = 0; + if (node != null) + { + maxWidth = (int) (getCellBounds(0, 0, node).getWidth()); + while (node != null) + { + count++; + DefaultMutableTreeNode nextNode = node.getNextNode(); + if (nextNode != null) + maxWidth = Math.max(maxWidth, (int) (getCellBounds(0, 0, nextNode) + .getWidth())); + node = nextNode; + } + } + + return new Dimension(maxWidth, (getRowHeight() * count)); + } + + /** + * Returns the minimum size for this component. Which will be the min + * preferred size or (0,0). + * + * @param c the component whose min size is being queried. + * @returns the preferred size or null + */ + public Dimension getMinimumSize(JComponent c) + { + // FIXME: not implemented + return getPreferredSize(c); + } + + /** + * Returns the maximum size for the component, which will be the preferred + * size if the instance is currently in JTree or (0,0). + * + * @param c the component whose preferred size is being queried + * @return the max size or null + */ + public Dimension getMaximumSize(JComponent c) + { + // FIXME: not implemented + return getPreferredSize(c); + } + + /** + * Messages to stop the editing session. If the UI the receiver is providing + * the look and feel for returns true from + * getInvokesStopCellEditing, stopCellEditing will be invoked + * on the current editor. Then completeEditing will be messaged with false, + * true, false to cancel any lingering editing. + */ + protected void completeEditing() + { + // FIXME: not implemented + } + + /** + * Stops the editing session. If messageStop is true, the editor is messaged + * with stopEditing, if messageCancel is true the editor is messaged with + * cancelEditing. If messageTree is true, the treeModel is messaged with + * valueForPathChanged. + * + * @param messageStop message to stop editing + * @param messageCancel message to cancel editing + * @param messageTree message to treeModel + */ + protected void completeEditing(boolean messageStop, boolean messageCancel, + boolean messageTree) + { + // FIXME: not implemented + } + + /** + * Will start editing for node if there is a cellEditor and shouldSelectCall + * returns true. This assumes that path is valid and visible. + * + * @param path is the path to start editing + * @param event is the MouseEvent performed on the path + * @return true if successful + */ + protected boolean startEditing(TreePath path, MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * If the mouseX and mouseY are in the expand + * or collapse region of the row, this will toggle the row. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + */ + protected void checkForClickInExpandControl(TreePath path, int mouseX, + int mouseY) + { + // FIXME: not implemented + } + + /** + * Returns true if the mouseX and mouseY fall + * in the area of row that is used to expand/collpse the node and the node at + * row does not represent a leaf. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + * @return true if the mouseX and mouseY fall + * in the area of row that is used to expand/collpse the node and the + * node at row does not represent a leaf. + */ + protected boolean isLocationInExpandControl(TreePath path, int mouseX, + int mouseY) + { + // FIXME: not implemented + return false; + } + + /** + * Messaged when the user clicks the particular row, this invokes + * toggleExpandState. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + */ + protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY) + { + // FIXME: not implemented + } + + /** + * Expands path if it is not expanded, or collapses row if it is expanded. If + * expanding a path and JTree scroll on expand, ensureRowsAreVisible is + * invoked to scroll as many of the children to visible as possible (tries to + * scroll to last visible descendant of path). + * + * @param path the path we are concerned with + */ + protected void toggleExpandState(TreePath path) + { + // FIXME: not implemented + } + + /** + * Returning true signifies a mouse event on the node should toggle the + * selection of only the row under the mouse. + * + * @param event is the MouseEvent performed on the row. + * @return true signifies a mouse event on the node should toggle the + * selection of only the row under the mouse. + */ + protected boolean isToggleSelectionEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Returning true signifies a mouse event on the node should select from the + * anchor point. + * + * @param event is the MouseEvent performed on the node. + * @return true signifies a mouse event on the node should select from the + * anchor point. + */ + protected boolean isMultiSelectEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Returning true indicates the row under the mouse should be toggled based + * on the event. This is invoked after checkForClickInExpandControl, implying + * the location is not in the expand (toggle) control. + * + * @param event is the MouseEvent performed on the row. + * @return true indicates the row under the mouse should be toggled based on + * the event. + */ + protected boolean isToggleEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Messaged to update the selection based on a MouseEvent over a particular + * row. If the even is a toggle selection event, the row is either selected, + * or deselected. If the event identifies a multi selection event, the + * selection is updated from the anchor point. Otherwise, the row is + * selected, and if the even specified a toggle event the row is + * expanded/collapsed. + * + * @param path is the path selected for an event + * @param event is the MouseEvent performed on the path. + */ + protected void selectPathForEvent(TreePath path, MouseEvent event) + { + // FIXME: not implemented + } + + /** + * Returns true if the node at row is a leaf. + * + * @param row is the row we are concerned with. + * @return true if the node at row is a leaf. + */ + protected boolean isLeaf(int row) + { + TreePath pathForRow = getPathForRow(tree, row); + if (pathForRow == null) + return true; + + Object node = pathForRow.getLastPathComponent(); + + if (node instanceof TreeNode) + return ((TreeNode) node).isLeaf(); + else + return true; + } + + /** + * Selects the specified path in the tree depending on modes. + * Package private for use in inner classes. + * + * @param tree is the tree we are selecting the path in + * @param path is the path we are selecting + */ + void selectPath(JTree tree, TreePath path) + { + if (path != null) + { + if (tree.isPathSelected(path)) + tree.removeSelectionPath(path); + else 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) + { + // TODO + } + else + { + tree.getSelectionModel().setSelectionMode( + TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + tree.addSelectionPath(path); + tree.setLeadSelectionPath(path); + } + } + } + + /* * INTERNAL CLASSES * */ + + /** + * Updates the preferred size when scrolling, if necessary. + */ + public class ComponentHandler + extends ComponentAdapter + implements ActionListener + { + /** + * Timer used when inside a scrollpane and the scrollbar is adjusting + */ + protected Timer timer; + + /** ScrollBar that is being adjusted */ + protected JScrollBar scrollBar; + + /** + * Constructor + */ + public ComponentHandler() + { + } + + /** + * Invoked when the component's position changes. + * + * @param e the event that occurs when moving the component + */ + public void componentMoved(ComponentEvent e) + { + } + + /** + * Creats, if necessary, and starts a Timer to check if needed to resize + * the bounds + */ + protected void startTimer() + { + } + + /** + * Returns the JScrollPane housing the JTree, or null if one isn't found. + * + * @return JScrollPane housing the JTree, or null if one isn't found. + */ + protected JScrollPane getScrollPane() + { + return null; + } + + /** + * Public as a result of Timer. If the scrollBar is null, or not + * adjusting, this stops the timer and updates the sizing. + * + * @param ae is the action performed + */ + public void actionPerformed(ActionEvent ae) + { + } + }// ComponentHandler + + /** + * Listener responsible for getting cell editing events and updating the tree + * accordingly. + */ + public class CellEditorHandler + implements CellEditorListener + { + /** + * Constructor + */ + public CellEditorHandler() + { + } + + /** + * Messaged when editing has stopped in the tree. Tells the listeners + * editing has stopped. + * + * @param e is the notification event + */ + public void editingStopped(ChangeEvent e) + { + } + + /** + * Messaged when editing has been canceled in the tree. This tells the + * listeners the editor has canceled editing. + * + * @param e is the notification event + */ + public void editingCanceled(ChangeEvent e) + { + } + }// CellEditorHandler + + /** + * Repaints the lead selection row when focus is lost/grained. + */ + public class FocusHandler + implements FocusListener + { + /** + * Constructor + */ + public FocusHandler() + { + } + + /** + * Invoked when focus is activated on the tree we're in, redraws the lead + * row. Invoked when a component gains the keyboard focus. + * + * @param e is the focus event that is activated + */ + public void focusGained(FocusEvent e) + { + } + + /** + * Invoked when focus is deactivated on the tree we're in, redraws the + * lead row. Invoked when a component loses the keyboard focus. + * + * @param e is the focus event that is deactivated + */ + public void focusLost(FocusEvent e) + { + } + }// FocusHandler + + /** + * This is used to get multiple key down events to appropriately genereate + * events. + */ + public class KeyHandler + extends KeyAdapter + { + /** Key code that is being generated for. */ + protected Action repeatKeyAction; + + /** Set to true while keyPressed is active */ + protected boolean isKeyDown; + + /** + * Constructor + */ + public KeyHandler() + { + } + + /** + * Invoked when a key has been typed. Moves the keyboard focus to the + * first element whose first letter matches the alphanumeric key pressed + * by the user. Subsequent same key presses move the keyboard focus to the + * next object that starts with the same letter. + * + * @param e the key typed + */ + public void keyTyped(KeyEvent e) + { + } + + /** + * Invoked when a key has been pressed. + * + * @param e the key pressed + */ + public void keyPressed(KeyEvent e) + { + TreePath start = BasicTreeUI.this.tree.getLeadSelectionPath(); + DefaultMutableTreeNode last = null; + + if (start != null) + last = (DefaultMutableTreeNode) start.getLastPathComponent(); + if (last != null) + { + if (e.getKeyCode() == KeyEvent.VK_DOWN) + { + DefaultMutableTreeNode next = (DefaultMutableTreeNode) + BasicTreeUI.this.getNextVisibleNode(last); + + if (next != null) + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, + new TreePath(next.getPath())); + } + else if (e.getKeyCode() == KeyEvent.VK_UP) + { + DefaultMutableTreeNode prev = (DefaultMutableTreeNode) + BasicTreeUI.this.getPreviousVisibleNode(last); + + if (prev != null) + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, + new TreePath(prev.getPath())); + } + else if (e.getKeyCode() == KeyEvent.VK_LEFT) + { + TreePath path = new TreePath(last.getPath()); + + if (!last.isLeaf() && BasicTreeUI.this.tree.isExpanded(path)) + { + BasicTreeUI.this.tree.collapsePath(path); + BasicTreeUI.this.tree.fireTreeCollapsed(path); + } + } + else if (e.getKeyCode() == KeyEvent.VK_RIGHT) + { + TreePath path = new TreePath(last.getPath()); + + if (!last.isLeaf() && BasicTreeUI.this.tree.isCollapsed(path)) + { + BasicTreeUI.this.tree.expandPath(path); + BasicTreeUI.this.tree.fireTreeExpanded(path); + } + } + } + } + + /** + * Invoked when a key has been released + * + * @param e the key released + */ + public void keyReleased(KeyEvent e) + { + } + }// KeyHandler + + /** + * MouseListener is responsible for updating the selevtion based on mouse + * events. + */ + public class MouseHandler + extends MouseAdapter + implements MouseMotionListener + { + /** + * Constructor + */ + public MouseHandler() + { + } + + /** + * Invoked when a mouse button has been pressed on a component. + * + * @param e is the mouse event that occured + */ + public void mousePressed(MouseEvent e) + { + } + + /** + * Invoked when a mouse button is pressed on a component and then dragged. + * MOUSE_DRAGGED events will continue to be delivered to the component + * where the drag originated until the mouse button is released + * (regardless of whether the mouse position is within the bounds of the + * component). + * + * @param e is the mouse event that occured + */ + public void mouseDragged(MouseEvent e) + { + } + + /** + * Invoked when the mouse button has been moved on a component (with no + * buttons no down). + * + * @param e the mouse event that occured + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * Invoked when a mouse button has been released on a component. + * + * @param e is the mouse event that occured + */ + public void mouseReleased(MouseEvent e) + { + } + }// 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 + { + /** Source that events are coming from */ + protected Component source; + + /** Destination that receives all events. */ + protected Component destination; + + /** Number of mouse clicks on a non-leaf */ + private int clickCount = 0; + + /** + * Constructor + * + * @param source that events are coming from + * @param destination that receives all events + * @param event is the event received + */ + public MouseInputHandler(Component source, Component destination, + MouseEvent e) + { + } + + /** + * Invoked when the mouse button has been clicked (pressed and released) + * on a component. + * + * @param e mouse event that occured + */ + public void mouseClicked(MouseEvent e) + { + Point click = e.getPoint(); + int clickX = (int) click.getX(); + int clickY = (int) click.getY(); + int row = (clickY / getRowHeight()) - 1; + TreePath path = BasicTreeUI.this.tree.getPathForRow(row); + + boolean inBounds = false; + boolean cntlClick = false; + Rectangle bounds = BasicTreeUI.this.getPathBounds( + BasicTreeUI.this.tree, path); + int x = (int) bounds.getX(); + int y = (int) bounds.getY(); + + if (clickY > y && clickY < (y + bounds.height + 10)) + { + if (clickX > x && clickX < (x + bounds.width + 20)) + inBounds = true; + else if (clickX < (x - rightChildIndent + 5) && + clickX > (x - rightChildIndent - 5)) + cntlClick = true; + } + + if ((inBounds || cntlClick) && path != null && + BasicTreeUI.this.tree.isVisible(path)) + { + if (!cntlClick && !BasicTreeUI.this.isLeaf(row)) + clickCount++; + + if (clickCount == 2 || cntlClick == true) + { + clickCount = 0; + BasicTreeUI.this.tree.getSelectionModel().clearSelection(); + if (BasicTreeUI.this.tree.isExpanded(path)) + { + BasicTreeUI.this.tree.collapsePath(path); + BasicTreeUI.this.tree.fireTreeCollapsed(path); + } + else + { + BasicTreeUI.this.tree.expandPath(path); + BasicTreeUI.this.tree.fireTreeExpanded(path); + } + } + + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, path); + } + } + + /** + * Invoked when a mouse button has been pressed on a component. + * + * @param e mouse event that occured + */ + public void mousePressed(MouseEvent e) + { + } + + /** + * Invoked when a mouse button has been released on a component. + * + * @param e mouse event that occured + */ + public void mouseReleased(MouseEvent e) + { + } + + /** + * Invoked when the mouse enters a component. + * + * @param e mouse event that occured + */ + public void mouseEntered(MouseEvent e) + { + } + + /** + * Invoked when the mouse exits a component. + * + * @param e mouse event that occured + */ + public void mouseExited(MouseEvent e) + { + } + + /** + * Invoked when a mouse button is pressed on a component and then dragged. + * MOUSE_DRAGGED events will continue to be delivered to the component + * where the drag originated until the mouse button is released + * (regardless of whether the mouse position is within the bounds of the + * component). + * + * @param e mouse event that occured + */ + public void mouseDragged(MouseEvent e) + { + } + + /** + * Invoked when the mouse cursor has been moved onto a component but no + * buttons have been pushed. + * + * @param e mouse event that occured + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * Removes event from the source + */ + protected void removeFromSource() + { + } + }// MouseInputHandler + + /** + * Class responsible for getting size of node, method is forwarded to + * BasicTreeUI method. X location does not include insets, that is handled in + * getPathBounds. + */ + public class NodeDimensionsHandler + extends AbstractLayoutCache.NodeDimensions + { + /** + * Constructor + */ + public NodeDimensionsHandler() + { + } + + /** + * Responsible for getting the size of a particular node. + * + * @param value the value to be represented + * @param row row being queried + * @param depth the depth of the row + * @param expanded true if row is expanded + * @param size a Rectangle containing the size needed to represent value + * @return containing the node dimensions, or null if node has no + * dimension + */ + public Rectangle getNodeDimensions(Object value, int row, int depth, + boolean expanded, Rectangle size) + { + return null; + } + + /** + * Returns the amount to indent the given row + * + * @return amount to indent the given row. + */ + protected int getRowX(int row, int depth) + { + return 0; + } + }// NodeDimensionsHandler + + /** + * PropertyChangeListener for the tree. Updates the appropriate varaible, or + * TreeState, based on what changes. + */ + public class PropertyChangeHandler + implements PropertyChangeListener + { + + /** + * Constructor + */ + public PropertyChangeHandler() + { + } + + /** + * This method gets called when a bound property is changed. + * + * @param event A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent event) + { + } + }// PropertyChangeHandler + + /** + * Listener on the TreeSelectionModel, resets the row selection if any of the + * properties of the model change. + */ + public class SelectionModelPropertyChangeHandler + implements PropertyChangeListener + { + + /** + * Constructor + */ + public SelectionModelPropertyChangeHandler() + { + } + + /** + * This method gets called when a bound property is changed. + * + * @param event A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent event) + { + } + }// SelectionModelPropertyChangeHandler + + /** + * ActionListener that invokes cancelEditing when action performed. + */ + public class TreeCancelEditingAction + extends AbstractAction + { + + /** + * Constructor + */ + public TreeCancelEditingAction() + { + } + + /** + * Invoked when an action occurs. + * + * @param e event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + }// TreeCancelEditingAction + + /** + * Updates the TreeState in response to nodes expanding/collapsing. + */ + public class TreeExpansionHandler + implements TreeExpansionListener + { + + /** + * Constructor + */ + public TreeExpansionHandler() + { + } + + /** + * Called whenever an item in the tree has been expanded. + * + * @param event is the event that occured + */ + public void treeExpanded(TreeExpansionEvent event) + { + BasicTreeUI.this.tree.repaint(); + } + + /** + * Called whenever an item in the tree has been collapsed. + * + * @param event is the event that occured + */ + public void treeCollapsed(TreeExpansionEvent event) + { + BasicTreeUI.this.tree.repaint(); + } + }// TreeExpansionHandler + + /** + * TreeHomeAction is used to handle end/home actions. Scrolls either the + * first or last cell to be visible based on direction. + */ + public class TreeHomeAction + extends AbstractAction + { + + /** direction is either home or end */ + protected int direction; + + /** + * Constructor + * + * @param direction - it is home or end + * @param name is the name of the direction + */ + public TreeHomeAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreeHomeAction + + /** + * TreeIncrementAction is used to handle up/down actions. Selection is moved + * up or down based on direction. + */ + public class TreeIncrementAction + extends AbstractAction + { + + /** Specifies the direction to adjust the selection by. */ + protected int direction; + + /** + * Constructor + * + * @param direction up or down + * @param name is the name of the direction + */ + public TreeIncrementAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreeIncrementAction + + /** + * Forwards all TreeModel events to the TreeState. + */ + public class TreeModelHandler + implements TreeModelListener + { + /** + * Constructor + */ + public TreeModelHandler() + { + } + + /** + * Invoked after a node (or a set of siblings) has changed in some way. + * The node(s) have not changed locations in the tree or altered their + * children arrays, but other attributes have changed and may affect + * presentation. Example: the name of a file has changed, but it is in the + * same location in the file system. To indicate the root has changed, + * childIndices and children will be null. Use e.getPath() to get the + * parent of the changed node(s). e.getChildIndices() returns the + * index(es) of the changed node(s). + * + * @param e is the event that occured + */ + public void treeNodesChanged(TreeModelEvent e) + { + } + + /** + * Invoked after nodes have been inserted into the tree. Use e.getPath() + * to get the parent of the new node(s). e.getChildIndices() returns the + * index(es) of the new node(s) in ascending order. + * + * @param e is the event that occured + */ + public void treeNodesInserted(TreeModelEvent e) + { + } + + /** + * Invoked after nodes have been removed from the tree. Note that if a + * subtree is removed from the tree, this method may only be invoked once + * for the root of the removed subtree, not once for each individual set + * of siblings removed. Use e.getPath() to get the former parent of the + * deleted node(s). e.getChildIndices() returns, in ascending order, the + * index(es) the node(s) had before being deleted. + * + * @param e is the event that occured + */ + public void treeNodesRemoved(TreeModelEvent e) + { + } + + /** + * Invoked after the tree has drastically changed structure from a given + * node down. If the path returned by e.getPath() is of length one and the + * first element does not identify the current root node the first element + * should become the new root of the tree. Use e.getPath() to get the path + * to the node. e.getChildIndices() returns null. + * + * @param e is the event that occured + */ + public void treeStructureChanged(TreeModelEvent e) + { + } + }// TreeModelHandler + + /** + * TreePageAction handles page up and page down events. + */ + public class TreePageAction + extends AbstractAction + { + /** Specifies the direction to adjust the selection by. */ + protected int direction; + + /** + * Constructor + * + * @param direction up or down + * @param name is the name of the direction + */ + public TreePageAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreePageAction + + /** + * Listens for changes in the selection model and updates the display + * accordingly. + */ + public class TreeSelectionHandler + implements TreeSelectionListener + { + /** + * Constructor + */ + public TreeSelectionHandler() + { + } + + /** + * Messaged when the selection changes in the tree we're displaying for. + * Stops editing, messages super and displays the changed paths. + * + * @param event the event that characterizes the change. + */ + public void valueChanged(TreeSelectionEvent event) + { + } + }// TreeSelectionHandler + + /** + * For the first selected row expandedness will be toggled. + */ + public class TreeToggleAction + extends AbstractAction + { + /** + * Constructor + * + * @param name is the name of Action field + */ + public TreeToggleAction(String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + } // TreeToggleAction + + /** + * 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 + { + /** + * Determines direction to traverse, 1 means expand, -1 means collapse. + */ + protected int direction; + + /** + * Constructor + * + * @param direction to traverse + * @param name is the name of the direction + */ + public TreeTraverseAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + } // TreeTraverseAction + + /** + * Returns the cell bounds for painting selected cells + * + * @param x is the x location of the cell + * @param y is the y location of the cell + * @param cell is the Object to get the bounds for + * + * @returns Rectangle that represents the cell bounds + */ + private Rectangle getCellBounds(int x, int y, Object cell) + { + if (cell != null) + { + String s = cell.toString(); + Font f = tree.getFont(); + FontMetrics fm = tree.getToolkit().getFontMetrics(tree.getFont()); + + return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s), + fm.getHeight()); + } + return null; + } + + /** + * Retrieves the location of some node, recursively starting at from + * some node. + * + * @param x is the starting x position, offset + * @param y is the starting y position, offset + * @param tree is the tree to traverse + * @param mod is the TreeModel to use + * @param node is the node to get the location for + * @param startNode is the node to start searching from + * + * @return Point - the location of node + */ + private Point getCellLocation(int x, int y, JTree tree, TreeModel mod, + Object node, Object startNode) + { + int rowHeight = getRowHeight(); + if (startNode == null || startNode.equals(node)) + return new Point(x + ((((DefaultMutableTreeNode) node). + getLevel() + 1) * rightChildIndent), y); + + if (!mod.isLeaf(startNode) + && tree.isExpanded(new TreePath( + ((DefaultMutableTreeNode) startNode).getPath()))) + { + Object child = mod.getChild(startNode, 0); + if (child != null) + return getCellLocation(x, y + rowHeight, tree, mod, + node, child); + } + + return getCellLocation(x, y + rowHeight, tree, mod, node, + getNextVisibleNode((DefaultMutableTreeNode) startNode)); + } + + /** + * Paints a leaf in the tree + * + * @param g the Graphics context in which to paint + * @param x the x location of the leaf + * @param y the y location of the leaf + * @param tree the tree to draw on + * @param leaf the object to draw + */ + private void paintLeaf(Graphics g, int x, int y, JTree tree, Object leaf) + { + TreePath curr = new TreePath(((DefaultMutableTreeNode) leaf).getPath()); + boolean selected = tree.isPathSelected(curr); + + if (tree.isVisible(curr)) + { + DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) + tree.getCellRenderer(); + boolean hasIcons = false; + Icon li = dtcr.getLeafIcon(); + if (li != null) + hasIcons = true; + + if (selected) + { + Component c = dtcr.getTreeCellRendererComponent(tree, leaf, + true, false, true, 0, false); + + if (hasIcons) + { + li.paintIcon(c, g, x, y + 2); + x += li.getIconWidth() + 4; + } + rendererPane.paintComponent(g, c, tree, + getCellBounds(x, y, leaf)); + } + else + { + Component c = dtcr.getTreeCellRendererComponent( + tree, leaf, false, false, true, 0, false); + + g.translate(x, y); + + if (hasIcons) + { + Component icon = dtcr.getTreeCellRendererComponent(tree, + li, false, false, true, 0, false); + icon.paint(g); + } + + c.paint(g); + g.translate(-x, -y); + } + } + } + + /** + * Paints a non-leaf in the tree + * + * @param g the Graphics context in which to paint + * @param x the x location of the non-leaf + * @param y the y location of the non-leaf + * @param tree the tree to draw on + * @param nonLeaf the object to draw + */ + private void paintNonLeaf(Graphics g, int x, int y, JTree tree, + Object nonLeaf) + { + TreePath curr = new TreePath(((DefaultMutableTreeNode) nonLeaf).getPath()); + boolean selected = tree.isPathSelected(curr); + boolean expanded = tree.isExpanded(curr); + + if (tree.isVisible(curr)) + { + DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) + tree.getCellRenderer(); + boolean hasIcons = false; + boolean hasOtherIcons = false; + Icon oi = dtcr.getOpenIcon(); + Icon ci = dtcr.getClosedIcon(); + + if (oi != null || ci != null) + hasIcons = true; + + if (selected) + { + Component c = dtcr.getTreeCellRendererComponent(tree, nonLeaf, + true, expanded, false, 0, false); + + if (hasIcons) + { + if (expanded) + { + oi.paintIcon(c, g, x, y + 2); + x += (oi.getIconWidth() + 4); + } + else + { + ci.paintIcon(c, g, x, y + 2); + x += (ci.getIconWidth() + 4); + } + + } + rendererPane.paintComponent(g, c, tree, + getCellBounds(x, y, nonLeaf)); + } + else + { + Component c = dtcr.getTreeCellRendererComponent(tree, nonLeaf, + false, expanded, false, 0, false); + g.translate(x, y); + + if (hasIcons) + { + Component icon; + if (expanded) + icon = dtcr.getTreeCellRendererComponent(tree, + oi, false, false, false, 0, false); + else + icon = dtcr.getTreeCellRendererComponent(tree, + ci, false, false, false, 0, false); + + icon.paint(g); + } + c.paint(g); + g.translate(-x, -y); + } + } + } + + /** + * Recursively paints all elements of the tree + * + * @param g the Graphics context in which to paint + * @param indentation 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 is the current object to draw + * + * @return int - current descent of the tree + */ + private int paintRecursive(Graphics g, int indentation, int descent, + int childNumber, int depth, JTree tree, TreeModel mod, Object curr) + { + Rectangle clip = g.getClipBounds(); + if (indentation > clip.x + clip.width + rightChildIndent + || descent > clip.y + clip.height + getRowHeight()) + return descent; + + int halfHeight = getRowHeight() / 2; + int halfWidth = rightChildIndent / 2; + int y0 = descent + halfHeight; + int heightOfLine = descent + halfHeight; + + if (mod.isLeaf(curr)) + { + paintLeaf(g, indentation + 4, descent, tree, curr); + descent += getRowHeight(); + } + else + { + if (depth > 0 || tree.isRootVisible()) + { + paintNonLeaf(g, indentation + 4, descent, tree, curr); + descent += getRowHeight(); + y0 += halfHeight; + } + + int max = mod.getChildCount(curr); + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr) + .getPath()))) + { + for (int i = 0; i < max; ++i) + { + g.setColor(getHashColor()); + heightOfLine = descent + halfHeight; + g.drawLine(indentation + halfWidth, heightOfLine, + indentation + rightChildIndent, heightOfLine); + + descent = paintRecursive(g, indentation + rightChildIndent, + descent, i, depth + 1, tree, mod, mod.getChild(curr, i)); + } + } + } + + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr) + .getPath()))) + if (y0 != heightOfLine) + { + g.setColor(getHashColor()); + g.drawLine(indentation + halfWidth, y0, indentation + halfWidth, + heightOfLine); + } + + return descent; + } + + /** + * Recursively paints all the control icons on the tree. + * + * @param g the Graphics context in which to paint + * @param indentation 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 is the current object to draw + * + * @return int - current descent of the tree + */ + private int paintControlIcons(Graphics g, int indentation, int descent, + int childNumber, 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(); + if (ci == null || ei == null || indentation > clip.x + clip.width + + rightChildIndent || descent > clip.y + clip.height + + getRowHeight()) + return descent; + + if (mod.isLeaf(node)) + descent += rowHeight; + else + { + if (depth > 0 || tree.isRootVisible()) + descent += rowHeight; + + int max = mod.getChildCount(node); + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node) + .getPath()))) + { + if (!node.equals(mod.getRoot())) + ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h); + + for (int i = 0; i < max; ++i) + { + descent = paintControlIcons(g, indentation + rightChildIndent, + descent, i, depth + 1, tree, mod, mod.getChild(node, i)); + } + } + else if (!node.equals(mod.getRoot())) + ci.paintIcon(tree, g, indentation - rightChildIndent - 3, + descent - getRowHeight()); + } + + return descent; + } +} // BasicTreeUI \ No newline at end of file diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java new file mode 100644 index 0000000..8ce772b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java @@ -0,0 +1,234 @@ +/* BasicViewportUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.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 + { + public void stateChanged(ChangeEvent event) + { + JViewport v = (JViewport) event.getSource(); + v.repaint(); + } + } + + void installDefaults(JComponent c) + { + c.setOpaque(true); + } + + void uninstallDefaults(JComponent c) + { + } + + void installListeners(JComponent c) + { + ((JViewport)c).addChangeListener(changeListener); + } + + void uninstallListeners(JComponent c) + { + ((JViewport)c).removeChangeListener(changeListener); + } + + public BasicViewportUI() + { + changeListener = new ChangeHandler(); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicViewportUI(); + } + + public void installUI(JComponent c) + { + super.installUI(c); + installListeners(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 (oldClip.intersection (viewBounds)); + 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); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java new file mode 100644 index 0000000..8bdcc51 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java @@ -0,0 +1,103 @@ +/* ComboPopup.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import javax.swing.JList; + +public interface ComboPopup +{ + /** + * This method display popup menu containing list of JComboBox's items to + * the screen + */ + void show(); + + /** + * This method hides popup menu with list of JComboBox's item from the + * screen + */ + void hide(); + + /** + * Retursn true if popup menu with JComboBOx's item is currently visible on + * the screen and false otherwise + * + * @return true if JComboBox's popup menu with list of items is currently + * visible on the screen and false otherwise. + */ + boolean isVisible(); + + /** + * Return JList that is used to draw cells of the JComboBox. + * + * @return JList that is used to draw cells of the JcomboBox + */ + JList getList(); + + /** + * This method returns MouseListener that listen's to mouse events occuring + * in the combo box + * + * @return MouseListenere + */ + MouseListener getMouseListener(); + + /** + * This method returns MouseListener that listen's to mouse events occuring + * in the combo box. + * + * @return MouseMotionListener + */ + MouseMotionListener getMouseMotionListener(); + + /** + * This method returns KeyListener that listen's to key events occuring in + * the combo box. + * + * @return KeyListener + */ + KeyListener getKeyListener(); + + /* This method removes any listeners that were installed */ + void uninstallingUI(); +} diff --git a/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java b/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java new file mode 100644 index 0000000..9760e82 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java @@ -0,0 +1,78 @@ +/* DefaultMenuLayout.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.basic; + +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.BoxLayout; +import javax.swing.plaf.UIResource; + +/** + * The LayoutManager that is used in PopupMenus. This is a derived from + * {@link BoxLayout}. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class DefaultMenuLayout + extends BoxLayout + implements UIResource +{ + + /** + * Creates a new instance of DefaultMenuLayout. + * + * @param target the component that is laid out + * @param axis the axis along which the component is laid out + */ + public DefaultMenuLayout(Container target, int axis) + { + super(target, axis); + } + + /** + * Returns the preferred size for the layout of the menu. + * + * @param target the Container which's preferred size we calculate + */ + public Dimension preferredLayoutSize(Container target) + { + return super.preferredLayoutSize(target); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png new file mode 100644 index 0000000..daeb16c Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png new file mode 100644 index 0000000..60f6a8a Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png new file mode 100644 index 0000000..54047dc Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png new file mode 100644 index 0000000..7c89911 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png new file mode 100644 index 0000000..a3841ba Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png new file mode 100644 index 0000000..13a9fa4e Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png new file mode 100644 index 0000000..a6408ec Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png new file mode 100644 index 0000000..db283c2 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png new file mode 100644 index 0000000..65381bd Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png new file mode 100644 index 0000000..c22763a Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png new file mode 100644 index 0000000..f898bee Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png new file mode 100644 index 0000000..99f8c6e Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png new file mode 100644 index 0000000..59d9a61 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png new file mode 100644 index 0000000..5b0971c Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png new file mode 100644 index 0000000..ceba0b6e Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png new file mode 100644 index 0000000..fa3055f Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png new file mode 100644 index 0000000..c760313 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png new file mode 100644 index 0000000..6a557a0 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png differ diff --git a/libjava/classpath/javax/swing/plaf/basic/package.html b/libjava/classpath/javax/swing/plaf/basic/package.html new file mode 100644 index 0000000..700c8cd --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/package.html @@ -0,0 +1,46 @@ + + + + +GNU Classpath - javax.swing.plaf.basic + + +

Provides a "basic" look and feel implementation.

+ + + diff --git a/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia new file mode 100644 index 0000000..02bfbbe Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia differ diff --git a/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png new file mode 100644 index 0000000..def4cbc Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png new file mode 100644 index 0000000..0f01ab0 Binary files /dev/null and b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png differ diff --git a/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java new file mode 100644 index 0000000..673aec1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java @@ -0,0 +1,221 @@ +/* DefaultMetalTheme.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Font; + +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; + +/** + * The default theme for the {@link MetalLookAndFeel}. + * + * @see MetalLookAndFeel#setCurrentTheme(MetalTheme) + */ +public class DefaultMetalTheme extends MetalTheme +{ + private static final ColorUIResource PRIMARY1 = + new ColorUIResource(102, 102, 153); + private static final ColorUIResource PRIMARY2 = + new ColorUIResource(153, 153, 204); + private static final ColorUIResource PRIMARY3 = + new ColorUIResource(204, 204, 255); + private static final ColorUIResource SECONDARY1 = + new ColorUIResource(102, 102, 102); + private static final ColorUIResource SECONDARY2 = + new ColorUIResource(153, 153, 153); + private static final ColorUIResource SECONDARY3 = + new ColorUIResource(204, 204, 204); + + private static final FontUIResource CONTROL_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + private static final FontUIResource MENU_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + private static final FontUIResource SUB_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 10); + private static final FontUIResource SYSTEM_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + private static final FontUIResource USER_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + private static final FontUIResource WINDOW_TITLE_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + + /** + * Creates a new instance of this theme. + */ + public DefaultMetalTheme() + { + // Do nothing here. + } + + /** + * Returns the name of the theme. + * + * @return "Steel". + */ + public String getName() + { + return "Steel"; + } + + /** + * Returns the first primary color for this theme. + * + * @return The first primary color. + */ + protected ColorUIResource getPrimary1() + { + return PRIMARY1; + } + + /** + * Returns the second primary color for this theme. + * + * @return The second primary color. + */ + protected ColorUIResource getPrimary2() + { + return PRIMARY2; + } + + /** + * Returns the third primary color for this theme. + * + * @return The third primary color. + */ + protected ColorUIResource getPrimary3() + { + return PRIMARY3; + } + + /** + * Returns the first secondary color for this theme. + * + * @return The first secondary color. + */ + protected ColorUIResource getSecondary1() + { + return SECONDARY1; + } + + /** + * Returns the second secondary color for this theme. + * + * @return The second secondary color. + */ + protected ColorUIResource getSecondary2() + { + return SECONDARY2; + } + + /** + * Returns the third secondary color for this theme. + * + * @return The third secondary color. + */ + protected ColorUIResource getSecondary3() + { + return SECONDARY3; + } + + /** + * Returns the font used for text on controls. In this case, the font is + * FontUIResource("Dialog", Font.BOLD, 12). + * + * @return The font. + */ + public FontUIResource getControlTextFont() + { + return CONTROL_TEXT_FONT; + } + /** + * Returns the font used for text in menus. In this case, the font is + * FontUIResource("Dialog", Font.BOLD, 12). + * + * @return The font used for text in menus. + */ + public FontUIResource getMenuTextFont() + { + return MENU_TEXT_FONT; + } + + /** + * Returns the font used for sub text. In this case, the font is + * FontUIResource("Dialog", Font.PLAIN, 10). + * + * @return The font used for sub text. + */ + public FontUIResource getSubTextFont() + { + return SUB_TEXT_FONT; + } + + /** + * Returns the font used for system text. In this case, the font is + * FontUIResource("Dialog", Font.PLAIN, 12). + * + * @return The font used for system text. + */ + public FontUIResource getSystemTextFont() + { + return SYSTEM_TEXT_FONT; + } + + /** + * Returns the font used for user text. In this case, the font is + * FontUIResource("Dialog", Font.PLAIN, 12). + * + * @return The font used for user text. + */ + public FontUIResource getUserTextFont() + { + return USER_TEXT_FONT; + } + + /** + * Returns the font used for window titles. In this case, the font is + * FontUIResource("Dialog", Font.BOLD, 12). + * + * @return The font used for window titles. + */ + public FontUIResource getWindowTitleFont() + { + return WINDOW_TITLE_FONT; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java new file mode 100644 index 0000000..f260ef6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -0,0 +1,443 @@ +/* MetalBorders.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.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JButton; +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.BasicGraphicsUtils; +import javax.swing.plaf.basic.BasicBorders; + +/** + * This factory class creates borders for the different Swing components + * UI. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalBorders +{ + + /** The shared instance for getButtonBorder(). */ + private static Border buttonBorder; + + /** The shared instance for getRolloverButtonBorder(). */ + private static Border toolbarButtonBorder; + + /** + * A MarginBorder that gets shared by multiple components. + * Created on demand by the private helper function {@link + * #getMarginBorder()}. + */ + private static BasicBorders.MarginBorder marginBorder; + + /** + * The border that is drawn around Swing buttons. + */ + 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. + */ + public ButtonBorder() + { + } + + /** + * Paints the 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(); + + // 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); + + // 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 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); + } + } + + /** + * Returns the insets of the ButtonBorder. + * + * @param c the component for which the border is used + * + * @return the insets of the ButtonBorder + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the ButtonBorder in the specified Insets object. + * + * @param c the component for which the border is used + * @param newInsets the insets object where to put the values + * + * @return the insets of the ButtonBorder + */ + 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; + newInsets.top = borderInsets.top; + return newInsets; + } + } + + /** + * A border for JScrollPanes. + */ + public static class ScrollPaneBorder + extends AbstractBorder + implements UIResource + { + /** The border insets. */ + private static Insets insets = new Insets(1, 1, 2, 2); + + /** + * Constructs a new ScrollPaneBorder. + */ + public ScrollPaneBorder() + { + } + + /** + * Returns the insets of the border for the Component c. + * + * @param c the Component for which we return the border insets + */ + public Insets getBorderInsets(Component c) + { + return insets; + } + + /** + * Paints the border. + * + * @param c the Component for which the border is painted + * @param g the Graphics context + * @param x the X coordinate of the upper left corner of the border + * @param y the Y coordinate of the upper left corner of the border + * @param w the width of the border + * @param h the height of the border + */ + public void paintBorder(Component c, Graphics g, int x, int y, + int w, int h) + { + Color darkShadow = MetalLookAndFeel.getControlDarkShadow(); + Color shadow = MetalLookAndFeel.getControlShadow(); + Color light = MetalLookAndFeel.getWhite(); + Color middle = MetalLookAndFeel.getControl(); + + // paint top border line + g.setColor(darkShadow); + g.drawLine(x, y, x + w - 2, y); + + // paint left border line + g.drawLine(x, y, x, y + h - 2); + + // paint right inner border line + g.drawLine(x + w - 2, y, x + w - 2, y + h + 1); + + // paint bottom inner border line + g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2); + + // draw right outer border line + g.setColor(light); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + + // draw bottom outer border line + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + + // paint the lighter points + g.setColor(middle); + g.drawLine(x + w - 1, y, x + w - 1, y); + g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2); + g.drawLine(x, y + h - 1, x, y + h - 1); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + + } + + } + + /** + * This border is used in Toolbar buttons as inner border. + */ + static class RolloverMarginBorder extends AbstractBorder + { + /** The borders insets. */ + protected static Insets borderInsets = new Insets(3, 3, 3, 3); + + /** + * Creates a new instance of RolloverBorder. + */ + public RolloverMarginBorder() + { + } + + /** + * Returns the insets of the RolloverBorder. + * + * @param c the component for which the border is used + * + * @return the insets of the RolloverBorder + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the RolloverMarginBorder in the specified + * Insets object. + * + * @param c the component for which the border is used + * @param newInsets the insets object where to put the values + * + * @return the insets of the RolloverMarginBorder + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(0, 0, 0, 0); + + AbstractButton b = (AbstractButton) c; + Insets margin = b.getMargin(); + newInsets.bottom = borderInsets.bottom; + newInsets.left = borderInsets.left; + newInsets.right = borderInsets.right; + newInsets.top = borderInsets.top; + return newInsets; + } + } + + /** + * A border implementation for popup menus. + */ + public static class PopupMenuBorder + extends AbstractBorder + implements UIResource + { + + /** The border's insets. */ + protected static Insets borderInsets = new Insets(2, 2, 1, 1); + + /** + * Constructs a new PopupMenuBorder. + */ + public PopupMenuBorder() + { + } + + /** + * Returns the insets of the border, creating a new Insets instance + * with each call. + * + * @param c the component for which we return the border insets + * (not used here) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the border, using the supplied Insets instance. + * + * @param c the component for which we return the border insets + * (not used here) + * @param i the Insets instance to fill with the Insets values + */ + public Insets getBorderInsets(Component c, Insets i) + { + Insets insets; + if (i == null) + insets = new Insets(borderInsets.top, borderInsets.left, + borderInsets.bottom, borderInsets.right); + else + { + insets = i; + insets.top = borderInsets.top; + insets.left = borderInsets.left; + insets.bottom = borderInsets.bottom; + insets.right = borderInsets.right; + } + + return insets; + } + + /** + * Paints the border for component c using the + * Graphics context g with the dimension + * x, y, w, h. + * + * @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) + { + Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); + Color light = MetalLookAndFeel.getPrimaryControlHighlight(); + + // draw dark outer border + g.setColor(darkShadow); + g.drawRect(x, y, w - 1, h - 1); + + // 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); + } + + } + + /** + * Returns a border for Swing buttons in the Metal Look & Feel. + * + * @return a border for Swing buttons in the Metal Look & Feel + */ + public static Border getButtonBorder() + { + if (buttonBorder == null) + { + Border outer = new ButtonBorder(); + Border inner = getMarginBorder(); + buttonBorder = new BorderUIResource.CompoundBorderUIResource + (outer, inner); + } + return buttonBorder; + } + + /** + * Returns a border for Toolbar buttons in the Metal Look & Feel. + * + * @return a border for Toolbar buttons in the Metal Look & Feel + */ + static Border getToolbarButtonBorder() + { + if (toolbarButtonBorder == null) + { + Border outer = new ButtonBorder(); + Border inner = new RolloverMarginBorder(); + toolbarButtonBorder = new BorderUIResource.CompoundBorderUIResource + (outer, inner); + } + return toolbarButtonBorder; + } + + /** + * Returns a shared instance of {@link BasicBorders.MarginBorder}. + * + * @return a shared instance of {@link BasicBorders.MarginBorder} + */ + static Border getMarginBorder() + { + if (marginBorder == null) + marginBorder = new BasicBorders.MarginBorder(); + return marginBorder; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java new file mode 100644 index 0000000..a7b53c4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java @@ -0,0 +1,101 @@ +/* MetalButtonUI.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 javax.swing.AbstractButton; +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.basic.BasicButtonUI; + +/** + * The Metal Look & Feel implementation for + * {@link javax.swing.AbstractButton}s. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalButtonUI + extends BasicButtonUI +{ + + // FIXME: probably substitute with a Map in the future in the case + // that this UI becomes stateful + + /** The cached MetalButtonUI instance. */ + private static MetalButtonUI instance = null; + + /** + * Creates a new instance of MetalButtonUI. + */ + public MetalButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalButtonUI. + * + * @param component a button for which a UI instance should be returned + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalButtonUI(); + return instance; + } + + /** + * Install the Look & Feel defaults for Buttons. + * + * @param button the button for which to install the Look & Feel + */ + public void installDefaults(AbstractButton button) + { + super.installDefaults(button); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + button.setFont(defaults.getFont("Button.font")); + + if (button.getParent() instanceof JToolBar) + button.setBorder(MetalBorders.getToolbarButtonBorder()); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java new file mode 100644 index 0000000..eba21a4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java @@ -0,0 +1,136 @@ +/* MetalCheckBoxIcon.java -- An icon for JCheckBoxes in 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 java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; + +import java.io.Serializable; + +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.plaf.UIResource; + +/** + * An {@link Icon} implementation for {@link JCheckBox}es in the + * Metal Look & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalCheckBoxIcon + implements Icon, UIResource, Serializable +{ + + /** Used to paint the border of the icon. */ + MetalBorders.ButtonBorder border; + + /** + * Creates a new MetalCheckBoxIcon instance. + */ + public MetalCheckBoxIcon() + { + border = new MetalBorders.ButtonBorder(); + } + + /** + * Draws the check in the CheckBox. + * + * @param c the component to draw on + * @param g the Graphics context to draw with + * @param x the X position + * @param y the Y position + */ + protected void drawCheck(Component c, Graphics g, int x, int y) + { + g.setColor(Color.BLACK); + g.drawLine(3, 5, 3, 9); + g.drawLine(4, 5, 4, 9); + g.drawLine(5, 7, 9, 3); + g.drawLine(5, 8, 9, 4); + } + + /** + * Returns the size (both X and Y) of the checkbox icon. + * + * @return the size of the checkbox icon + */ + protected int getControlSize() + { + return 13; + } + + /** + * Returns the width of the icon in pixels. + * + * @return the width of the icon in pixels + */ + public int getIconWidth() + { + return getControlSize(); + } + + /** + * Returns the height of the icon in pixels. + * + * @return the height of the icon in pixels + */ + public int getIconHeight() + { + return getControlSize(); + } + + /** + * Paints the icon. This first paints the border of the CheckBox and + * if the CheckBox is selected it calls {@link #drawCheck} to draw + * the check. + * + * @param c the Component to draw on (gets casted to JCheckBox) + * @param g the Graphics context to draw with + * @param x the X position + * @param x the Y position + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + border.paintBorder(c, g, x, y, getIconWidth(), getIconHeight()); + JCheckBox cb = (JCheckBox) c; + if (cb.isSelected()) + drawCheck(c, g, x, y); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java new file mode 100644 index 0000000..d59e38c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java @@ -0,0 +1,74 @@ +/* MetalCheckBoxUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicCheckBoxUI; + +public class MetalCheckBoxUI + extends BasicCheckBoxUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JCheckBoxes. */ + private static MetalCheckBoxUI instance = null; + + /** + * Constructs a new instance of MetalCheckBoxUI. + */ + public MetalCheckBoxUI() + { + super(); + } + + /** + * Returns an instance of MetalCheckBoxUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalCheckBoxUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalCheckBoxUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java new file mode 100644 index 0000000..ce4fa7d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java @@ -0,0 +1,100 @@ +/* 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.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; + +import javax.swing.Icon; + +/** + * An icon used by the {@link MetalComboBoxUI} class. + */ +public class MetalComboBoxIcon implements Icon, Serializable { + + /** + * Creates a new icon. + */ + public MetalComboBoxIcon() + { + // nothing required. + } + + /** + * Returns the icon width, which for this icon is 10 pixels. + * + * @return 10. + */ + public int getIconWidth() + { + return 10; + } + + /** + * Returns the icon height, which for this icon is 5 pixels. + * + * @return 5. + */ + public int getIconHeight() + { + return 5; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the combo box (ignored here). + * @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) + { + // 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); + 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 new file mode 100644 index 0000000..28c279d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java @@ -0,0 +1,86 @@ +/* MetalComboBoxUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; + +public class MetalComboBoxUI + extends BasicComboBoxUI +{ + + /** The UI instances for JComboBoxes. */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalComboBoxUI. + */ + public MetalComboBoxUI() + { + super(); + } + + /** + * Returns an instance of MetalComboBoxUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalComboBoxUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalComboBoxUI instance; + if (o == null) + { + instance = new MetalComboBoxUI(); + instances.put(component, instance); + } + else + instance = (MetalComboBoxUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java new file mode 100644 index 0000000..0087054 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java @@ -0,0 +1,74 @@ +/* MetalDesktopIconUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicDesktopIconUI; + +public class MetalDesktopIconUI + extends BasicDesktopIconUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalDesktopIcons */ + private static MetalDesktopIconUI instance = null; + + /** + * Constructs a new instance of MetalDesktopIconUI. + */ + public MetalDesktopIconUI() + { + super(); + } + + /** + * Returns an instance of MetalDesktopIconUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalDesktopIconUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalDesktopIconUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java new file mode 100644 index 0000000..e770f47 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java @@ -0,0 +1,672 @@ +/* MetalIconFactory.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.io.Serializable; + +import javax.swing.Icon; +import javax.swing.JSlider; + +/** + * Creates icons for the {@link MetalLookAndFeel}. + */ +public class MetalIconFactory implements Serializable +{ + + /** A constant representing "dark". */ + public static final boolean DARK = false; + + /** A constant representing "light". */ + public static final boolean LIGHT = true; + + /** + * An icon representing a file (drawn as a piece of paper with the top-right + * corner turned down). + */ + public static class FileIcon16 implements Icon, Serializable + { + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the component. + * @param g the graphics context. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x, y, x + 9, y); + g.drawLine(x, y + 1, x, y + 15); + g.drawLine(x, y + 15, x + 12, y + 15); + g.drawLine(x + 12, y + 15, x + 12, y + 6); + g.drawLine(x + 12, y + 6, x + 9, y); + + g.drawLine(x + 7, y + 2, x + 11, y + 6); + g.drawLine(x + 8, y + 1, x + 9, y + 1); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 1, y + 1, x + 7, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + 14); + g.drawLine(x + 1, y + 14, x + 11, y + 14); + g.drawLine(x + 11, y + 14, x + 11, y + 7); + g.drawLine(x + 8, y + 2, x + 10, y + 4); + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 0; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 0; + } + + } + + /** + * An icon representing a folder. + */ + public static class FolderIcon16 implements Icon, Serializable + { + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the component. + * @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) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x, y + 3, x, y + 12); + g.drawLine(x, y + 12, x + 15, y + 12); + g.drawLine(x + 15, y + 12, x + 15, y + 2); + g.drawLine(x + 14, y + 3, x + 9, y + 3); + g.drawLine(x + 8, y + 2, x + 1, y + 2); + g.setColor(new Color(204, 204, 255)); + g.fillRect(x + 2, y + 4, 7, 8); + g.fillRect(x + 9, y + 5, 6, 7); + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 9, y + 2, x + 14, y + 2); + g.setColor(new Color(50, 50, 120)); + g.drawLine(x + 9, y + 1, x + 15, y + 1); + g.drawLine(x + 10, y, x + 15, y); + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 0; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 0; + } + + } + + /** + * The icon used to display the thumb control on a horizontally oriented + * {@link JSlider} component. + */ + private static class HorizontalSliderThumbIcon + implements Icon, Serializable + { + + /** + * Creates a new instance. + */ + public HorizontalSliderThumbIcon() + { + } + + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 15; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon, taking into account whether or not the component has + * the focus. + * + * @param c the component. + * @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) + { + boolean focus = false; + if (c != null) + focus = c.hasFocus(); + // TODO: pick up the colors from the look and feel + + // draw the outline + g.setColor(Color.black); + 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); + g.drawLine(x + 6, y + 14, x, y + 8); + 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); + 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); + g.drawLine(x + 5, y + 12, x + 9, y + 12); + 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); + + 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); + + // 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 + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 9, y + 5, x + 9, y + 5); + + 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); + + } + } + + /** + * The icon used to display the thumb control on a horizontally oriented + * {@link JSlider} component. + */ + private static class VerticalSliderThumbIcon implements Icon, Serializable + { + /** + * Creates a new instance. + */ + public VerticalSliderThumbIcon() + { + } + + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 15; + } + + /** + * Paints the icon taking into account whether the slider control has the + * focus or not. + * + * @param c the slider (must be a non-null instance of + * {@link JSlider}. + * @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) + { + boolean focus = false; + if (c != null) + focus = c.hasFocus(); + // TODO: pick up the colors from the look and feel + + // draw the outline + g.setColor(Color.black); + 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); + g.drawLine(x + 8, y + 14, x + 1, y + 14); + 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); + 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); + g.drawLine(x + 12, y + 5, x + 12, y + 9); + 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); + + g.drawLine(x + 4, y + 4, x + 4, y + 4); + g.drawLine(x + 4, y + 8, x + 4, y + 8); + + 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); + + // 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); + + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 5, y + 9, x + 5, y + 9); + + 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); + } + } + + /** + * A tree control icon. This icon can be in one of two states: expanded and + * collapsed. + */ + public static class TreeControlIcon implements Icon, Serializable + { + + /** ???. */ + protected boolean isLight; + + /** A flag that controls whether or not the icon is collapsed. */ + private boolean collapsed; + + /** + * Creates a new icon. + * + * @param isCollapsed a flag that controls whether the icon is in the + * collapsed state or the expanded state. + */ + public TreeControlIcon(boolean isCollapsed) + { + collapsed = isCollapsed; + } + + /** + * 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 at the location (x, y). + * + * @param c the component. + * @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) + { + x = x + 5; + y = y + 5; + if (collapsed) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x + 2, y, x + 5, y); + g.drawLine(x + 6, y + 1, x + 7, y + 2); + g.fillRect(x + 7, y + 3, 5, 2); + g.drawLine(x + 7, y + 5, x + 6, y + 6); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x, y + 2, x, y + 5); + g.drawLine(x + 1, y + 6, x + 1, y + 6); + g.drawLine(x + 2, y + 7, x + 5, y + 7); + g.fillRect(x + 3, y + 3, 2, 2); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 3, y + 2, x + 4, y + 2); + g.drawLine(x + 2, y + 3, x + 2, y + 4); + g.drawLine(x + 3, y + 5, x + 3, y + 5); + g.drawLine(x + 5, y + 3, x + 5, y + 3); + + g.setColor(new Color(153, 153, 204)); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 2, y + 5, x + 2, y + 5); + g.drawLine(x + 2, y + 6, x + 5, y + 6); + g.drawLine(x + 5, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 2, x + 6, y + 5); + + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 2, y + 1, x + 5, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 5); + } + else + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x + 2, y, x + 5, y); + g.drawLine(x + 6, y + 1, x + 7, y + 2); + g.drawLine(x + 7, y + 2, x + 7, y + 5); + g.fillRect(x + 3, y + 7, 2, 5); + g.drawLine(x + 7, y + 5, x + 6, y + 6); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x, y + 2, x, y + 5); + g.drawLine(x + 1, y + 6, x + 1, y + 6); + g.drawLine(x + 2, y + 7, x + 5, y + 7); + g.fillRect(x + 3, y + 3, 2, 2); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 3, y + 2, x + 4, y + 2); + g.drawLine(x + 2, y + 3, x + 2, y + 4); + g.drawLine(x + 3, y + 5, x + 3, y + 5); + g.drawLine(x + 5, y + 3, x + 5, y + 3); + + g.setColor(new Color(153, 153, 204)); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 2, y + 5, x + 2, y + 5); + g.drawLine(x + 2, y + 6, x + 5, y + 6); + g.drawLine(x + 5, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 2, x + 6, y + 5); + + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 2, y + 1, x + 5, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 5); + } + } + + /** + * Simply calls {@link #paintIcon(Component, Graphics, int, int)}. + * + * @param c the component. + * @param g the graphics device. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintMe(Component c, Graphics g, int x, int y) + { + paintIcon(c, g, x, y); + } + } + + /** + * A tree folder icon. + */ + public static class TreeFolderIcon extends FolderIcon16 + { + /** + * Creates a new instance. + */ + public TreeFolderIcon() + { + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 2; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return -1; + } + } + + /** + * A tree leaf icon. + */ + public static class TreeLeafIcon extends FileIcon16 + { + /** + * Creates a new instance. + */ + public TreeLeafIcon() + { + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 4; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 2; + } + } + + /** + * Creates a new instance. All the methods are static, so creating an + * instance isn't necessary. + */ + public MetalIconFactory() + { + } + + /** + * Returns the icon used to display the thumb for a horizontally oriented + * {@link JSlider}. + * + * @return The icon. + */ + public static Icon getHorizontalSliderThumbIcon() + { + return new HorizontalSliderThumbIcon(); + } + + /** + * Returns the icon used to display the thumb for a vertically oriented + * {@link JSlider}. + * + * @return The icon. + */ + public static Icon getVerticalSliderThumbIcon() + { + return new VerticalSliderThumbIcon(); + } + + /** + * Creates and returns a new tree folder icon. + * + * @return A new tree folder icon. + */ + public static Icon getTreeFolderIcon() + { + return new TreeFolderIcon(); + } + + /** + * Creates and returns a new tree leaf icon. + * + * @return A new tree leaf icon. + */ + public static Icon getTreeLeafIcon() + { + return new TreeLeafIcon(); + } + + /** + * Creates and returns a tree control icon. + * + * @param isCollapsed a flag that controls whether the icon is in the + * collapsed or expanded state. + * + * @return A tree control icon. + */ + public static Icon getTreeControlIcon(boolean isCollapsed) + { + return new TreeControlIcon(isCollapsed); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java new file mode 100644 index 0000000..1414351 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java @@ -0,0 +1,88 @@ +/* MetalInternalFrameUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicInternalFrameUI; + +public class MetalInternalFrameUI + extends BasicInternalFrameUI +{ + + /** The instances of MetalInternalFrameUI*/ + private static HashMap instances; + + /** + * Constructs a new instance of MetalInternalFrameUI. + */ + public MetalInternalFrameUI(JInternalFrame frame) + { + super(frame); + } + + /** + * Returns an instance of MetalInternalFrameUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalInternalFrameUI + */ + 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; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java new file mode 100644 index 0000000..cdd8612 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java @@ -0,0 +1,74 @@ +/* MetalLabelUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicLabelUI; + +public class MetalLabelUI + extends BasicLabelUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JLabels. */ + private static MetalLabelUI instance = null; + + /** + * Constructs a new instance of MetalLabelUI. + */ + public MetalLabelUI() + { + super(); + } + + /** + * Returns an instance of MetalLabelUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalLabelUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalLabelUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java new file mode 100644 index 0000000..46519fc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -0,0 +1,853 @@ +/* MetalLookAndFeel.java + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Insets; + +import javax.swing.ImageIcon; +import javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.IconUIResource; +import javax.swing.plaf.basic.BasicLookAndFeel; + +/** + * A custom look and feel that is designed to look similar across different + * operating systems. + */ +public class MetalLookAndFeel extends BasicLookAndFeel +{ + private static final long serialVersionUID = 6680646159193457980L; + + /** The current theme. */ + private static MetalTheme theme; + + /** The look and feel defaults. */ + private UIDefaults LAF_defaults; + + /** + * Creates a new instance of the Metal look and feel. + */ + public MetalLookAndFeel() + { + createDefaultTheme(); + } + + /** + * Sets the current theme to a new instance of {@link DefaultMetalTheme}. + */ + protected void createDefaultTheme() + { + setCurrentTheme(new DefaultMetalTheme()); + } + + /** + * Returns false to indicate that this look and feel does not + * attempt to emulate the look and feel of native applications on the host + * platform. + * + * @return false. + */ + public boolean isNativeLookAndFeel() + { + return false; + } + + /** + * Returns true to indicate that this look and feel is supported + * on all platforms. + * + * @return true. + */ + public boolean isSupportedLookAndFeel() + { + return true; + } + + /** + * Returns a string describing the look and feel. In this case, the method + * returns "Metal look and feel". + * + * @return A string describing the look and feel. + */ + public String getDescription() + { + return "Metal look and feel"; + } + + /** + * Returns the look and feel identifier. + * + * @return "MetalLookAndFeel". + */ + public String getID() + { + return "MetalLookAndFeel"; + } + + /** + * Returns the look and feel name. + * + * @return "MetalLookAndFeel". + */ + public String getName() + { + return "MetalLookAndFeel"; + } + + public UIDefaults getDefaults() + { + if (LAF_defaults == null) + { + LAF_defaults = super.getDefaults(); + + // add custom theme entries to the table + theme.addCustomEntriesToTable(LAF_defaults); + } + + // Returns the default values for this look and feel. + return LAF_defaults; + } + + /** + * Returns the accelerator foreground color from the installed theme. + * + * @return The accelerator foreground color. + */ + public static ColorUIResource getAcceleratorForeground() + { + return theme.getAcceleratorForeground(); + } + + /** + * Returns the accelerator selected foreground color from the installed + * theme. + * + * @return The accelerator selected foreground color. + */ + public static ColorUIResource getAcceleratorSelectedForeground() + { + return theme.getAcceleratorSelectedForeground(); + } + + /** + * Returns the color black from the installed theme. + * + * @return The color black. + */ + public static ColorUIResource getBlack() + { + return theme.getBlack(); + } + + /** + * Returns the control color from the installed theme. + * + * @return The control color. + */ + public static ColorUIResource getControl() + { + return theme.getControl(); + } + + /** + * Returns the color used for dark shadows on controls, from the installed + * theme. + * + * @return The color used for dark shadows on controls. + */ + public static ColorUIResource getControlDarkShadow() + { + return theme.getControlDarkShadow(); + } + + /** + * Returns the color used for disabled controls, from the installed theme. + * + * @return The color used for disabled controls. + */ + public static ColorUIResource getControlDisabled() + { + return theme.getControlDisabled(); + } + + /** + * Returns the color used to draw highlights for controls, from the installed + * theme. + * + * @return The color used to draw highlights for controls. + */ + public static ColorUIResource getControlHighlight() + { + return theme.getControlHighlight(); + } + + /** + * Returns the color used to display control info, from the installed + * theme. + * + * @return The color used to display control info. + */ + public static ColorUIResource getControlInfo() + { + return theme.getControlInfo(); + } + + /** + * Returns the color used to draw shadows for controls, from the installed + * theme. + * + * @return The color used to draw shadows for controls. + */ + public static ColorUIResource getControlShadow() + { + return theme.getControlShadow(); + } + + /** + * Returns the color used for text on controls, from the installed theme. + * + * @return The color used for text on controls. + */ + public static ColorUIResource getControlTextColor() + { + return theme.getControlTextColor(); + } + + /** + * Returns the font used for text on controls, from the installed theme. + * + * @return The font used for text on controls. + */ + public static FontUIResource getControlTextFont() + { + return theme.getControlTextFont(); + } + + /** + * Returns the color used for the desktop background, from the installed + * theme. + * + * @return The color used for the desktop background. + */ + public static ColorUIResource getDesktopColor() + { + return theme.getDesktopColor(); + } + + /** + * Returns the color used to draw focus highlights, from the installed + * theme. + * + * @return The color used to draw focus highlights. + */ + public static ColorUIResource getFocusColor() + { + return theme.getFocusColor(); + } + + /** + * Returns the color used to draw highlighted text, from the installed + * theme. + * + * @return The color used to draw highlighted text. + */ + public static ColorUIResource getHighlightedTextColor() + { + return theme.getHighlightedTextColor(); + } + + /** + * Returns the color used to draw text on inactive controls, from the + * installed theme. + * + * @return The color used to draw text on inactive controls. + */ + public static ColorUIResource getInactiveControlTextColor() + { + return theme.getInactiveControlTextColor(); + } + + /** + * Returns the color used to draw inactive system text, from the installed + * theme. + * + * @return The color used to draw inactive system text. + */ + public static ColorUIResource getInactiveSystemTextColor() + { + return theme.getInactiveSystemTextColor(); + } + + /** + * Returns the background color for menu items, from the installed theme. + * + * @return The background color for menu items. + * + * @see #getMenuSelectedBackground() + */ + public static ColorUIResource getMenuBackground() + { + return theme.getMenuBackground(); + } + + /** + * Returns the foreground color for disabled menu items, from the installed + * theme. + * + * @return The foreground color for disabled menu items. + * + * @see #getMenuForeground() + */ + public static ColorUIResource getMenuDisabledForeground() + { + return theme.getMenuDisabledForeground(); + } + + /** + * Returns the foreground color for menu items, from the installed theme. + * + * @return The foreground color for menu items. + * + * @see #getMenuDisabledForeground() + * @see #getMenuSelectedForeground() + */ + public static ColorUIResource getMenuForeground() + { + return theme.getMenuForeground(); + } + + /** + * Returns the background color for selected menu items, from the installed + * theme. + * + * @return The background color for selected menu items. + * + * @see #getMenuBackground() + */ + public static ColorUIResource getMenuSelectedBackground() + { + return theme.getMenuSelectedBackground(); + } + + /** + * Returns the foreground color for selected menu items, from the installed + * theme. + * + * @return The foreground color for selected menu items. + * + * @see #getMenuForeground() + */ + public static ColorUIResource getMenuSelectedForeground() + { + return theme.getMenuSelectedForeground(); + } + + /** + * Returns the font used for text in menus, from the installed theme. + * + * @return The font used for text in menus. + */ + public static FontUIResource getMenuTextFont() + { + return theme.getMenuTextFont(); + } + + /** + * Returns the primary color for controls, from the installed theme. + * + * @return The primary color for controls. + */ + public static ColorUIResource getPrimaryControl() + { + return theme.getPrimaryControl(); + } + + /** + * Returns the primary color for the dark shadow on controls, from the + * installed theme. + * + * @return The primary color for the dark shadow on controls. + */ + public static ColorUIResource getPrimaryControlDarkShadow() + { + return theme.getPrimaryControlDarkShadow(); + } + + /** + * Returns the primary color for the highlight on controls, from the + * installed theme. + * + * @return The primary color for the highlight on controls. + */ + public static ColorUIResource getPrimaryControlHighlight() + { + return theme.getPrimaryControlHighlight(); + } + + /** + * Returns the primary color for the information on controls, from the + * installed theme. + * + * @return The primary color for the information on controls. + */ + public static ColorUIResource getPrimaryControlInfo() + { + return theme.getPrimaryControlInfo(); + } + + /** + * Returns the primary color for the shadow on controls, from the installed + * theme. + * + * @return The primary color for the shadow on controls. + */ + public static ColorUIResource getPrimaryControlShadow() + { + return theme.getPrimaryControlShadow(); + } + + /** + * Returns the background color for separators, from the installed theme. + * + * @return The background color for separators. + */ + public static ColorUIResource getSeparatorBackground() + { + return theme.getSeparatorBackground(); + } + + /** + * Returns the foreground color for separators, from the installed theme. + * + * @return The foreground color for separators. + */ + public static ColorUIResource getSeparatorForeground() + { + return theme.getSeparatorForeground(); + } + + /** + * Returns the font used for sub text, from the installed theme. + * + * @return The font used for sub text. + */ + public static FontUIResource getSubTextFont() + { + return theme.getSubTextFont(); + } + + /** + * Returns the color used for system text, from the installed theme. + * + * @return The color used for system text. + */ + public static ColorUIResource getSystemTextColor() + { + return theme.getSystemTextColor(); + } + + /** + * Returns the font used for system text, from the installed theme. + * + * @return The font used for system text. + */ + public static FontUIResource getSystemTextFont() + { + return theme.getSystemTextFont(); + } + + /** + * Returns the color used to highlight text, from the installed theme. + * + * @return The color used to highlight text. + */ + public static ColorUIResource getTextHighlightColor() + { + return theme.getTextHighlightColor(); + } + + /** + * Returns the color used to display user text, from the installed theme. + * + * @return The color used to display user text. + */ + public static ColorUIResource getUserTextColor() + { + return theme.getUserTextColor(); + } + + /** + * Returns the font used for user text, obtained from the current theme. + * + * @return The font used for user text. + */ + public static FontUIResource getUserTextFont() + { + return theme.getUserTextFont(); + } + + /** + * Returns the color used for white, from the installed theme. + * + * @return The color used for white. + */ + public static ColorUIResource getWhite() + { + return theme.getWhite(); + } + + /** + * Returns the window background color, from the installed theme. + * + * @return The window background color. + */ + public static ColorUIResource getWindowBackground() + { + return theme.getWindowBackground(); + } + + /** + * Returns the window title background color, from the installed theme. + * + * @return The window title background color. + */ + public static ColorUIResource getWindowTitleBackground() + { + return theme.getWindowTitleBackground(); + } + + /** + * Returns the window title font from the current theme. + * + * @return The window title font. + * + * @see MetalTheme + */ + public static FontUIResource getWindowTitleFont() + { + return theme.getWindowTitleFont(); + } + + /** + * Returns the window title foreground color, from the installed theme. + * + * @return The window title foreground color. + */ + public static ColorUIResource getWindowTitleForeground() + { + return theme.getWindowTitleForeground(); + } + + /** + * Returns the background color for an inactive window title, from the + * installed theme. + * + * @return The background color for an inactive window title. + */ + public static ColorUIResource getWindowTitleInactiveBackground() + { + return theme.getWindowTitleInactiveBackground(); + } + + /** + * Returns the foreground color for an inactive window title, from the + * installed theme. + * + * @return The foreground color for an inactive window title. + */ + public static ColorUIResource getWindowTitleInactiveForeground() + { + return theme.getWindowTitleInactiveForeground(); + } + + /** + * Sets the current theme for the look and feel. + * + * @param theme the theme. + */ + public static void setCurrentTheme(MetalTheme theme) + { + MetalLookAndFeel.theme = theme; + } + + /** + * Sets the ComponentUI classes for all Swing components to the Metal + * implementations. + * + * In particular this sets the following keys: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
KeyValue
ButtonUI{@link MetalButtonUI}
CheckBoxUI{@link MetalCheckBoxUI}
ComboBoxUI{@link MetalComboBoxUI}
DesktopIconUI{@link MetalDesktopIconUI}
InternalFrameUI{@link MetalInternalFrameUI}
LabelUI{@link MetalLabelUI}
PopupMenuSeparatorUI{@link MetalPopupMenuSeparatorUI}
ProgressBarUI{@link MetalProgressBarUI}
RadioButtonUI{@link MetalRadioButtonUI}
RootPaneUI{@link MetalRootPaneUI}
ScrollBarUI{@link MetalScrollBarUI}
ScrollPaneUI{@link MetalScrollPaneUI}
SeparatorUI{@link MetalSeparatorUI}
SliderUI{@link MetalSliderUI}
SplitPaneUI{@link MetalSplitPaneUI}
TabbedPaneUI{@link MetalTabbedPaneUI}
TextFieldUI{@link MetalTextFieldUI}
ToggleButtonUI{@link MetalToggleButtonUI}
ToolBarUI{@link MetalToolBarUI}
ToolTipUI{@link MetalToolTipUI}
TreeUI{@link MetalTreeUI}
+ * + * @param defaults the UIDefaults where the class defaults are added + */ + protected void initClassDefaults(UIDefaults defaults) + { + super.initClassDefaults(defaults); + + // Variables + Object[] uiDefaults; + // Initialize Class Defaults + uiDefaults = new Object[] { + "ButtonUI", "javax.swing.plaf.metal.MetalButtonUI", + "CheckBoxUI", "javax.swing.plaf.metal.MetalCheckBoxUI", + "ComboBoxUI", "javax.swing.plaf.metal.MetalComboBoxUI", + "DesktopIconUI", "javax.swing.plaf.metal.MetalDesktopIconUI", + "InternalFrameUI", "javax.swing.plaf.metal.MetalInternalFrameUI", + "LabelUI", "javax.swing.plaf.metal.MetalLabelUI", + "PopupMenuSeparatorUI", + "javax.swing.plaf.metal.MetalPopupMenuSeparatorUI", + "ProgressBarUI", "javax.swing.plaf.metal.MetalProgressBarUI", + "RadioButtonUI", "javax.swing.plaf.metal.MetalRadioButtonUI", + "RootPaneUI", "javax.swing.plaf.metal.MetalRootPaneUI", + "ScrollBarUI", "javax.swing.plaf.metal.MetalScrollBarUI", + "ScrollPaneUI", "javax.swing.plaf.metal.MetalScrollPaneUI", + "SeparatorUI", "javax.swing.plaf.metal.MetalSeparatorUI", + "SliderUI", "javax.swing.plaf.metal.MetalSliderUI", + "SplitPaneUI", "javax.swing.plaf.metal.MetalSplitPaneUI", + "TabbedPaneUI", "javax.swing.plaf.metal.MetalTabbedPaneUI", + "TextFieldUI", "javax.swing.plaf.metal.MetalTextFieldUI", + "ToggleButtonUI", "javax.swing.plaf.metal.MetalToggleButtonUI", + "ToolBarUI", "javax.swing.plaf.metal.MetalToolBarUI", + "ToolTipUI", "javax.swing.plaf.metal.MetalToolTipUI", + "TreeUI", "javax.swing.plaf.metal.MetalTreeUI", + }; + // Add Class Defaults to UI Defaults table + defaults.putDefaults(uiDefaults); + } + + /** + * Initializes the component defaults for the Metal Look & Feel. + * + * In particular this sets the following keys (the colors are given + * as RGB hex values): + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
KeyValue
Button.background0xcccccc
Button.border{@link MetalBorders#getButtonBorder()}
Button.font{@link #getControlTextFont}
Button.marginnew java.awt.Insets(2, 14, 2, 14) + *
CheckBox.background0xcccccc
CheckBoxMenuItem.background0xcccccc
ToolBar.background0xcccccc
Panel.background0xcccccc
Slider.background0xcccccc
OptionPane.background0xcccccc
ProgressBar.background0xcccccc
TabbedPane.background0xcccccc
Label.background0xcccccc
Label.font{@link #getControlTextFont}
Menu.background0xcccccc
MenuBar.background0xcccccc
MenuItem.background0xcccccc
ScrollBar.background0xcccccc
PopupMenu.bordernew javax.swing.plaf.metal.MetalBorders.PopupMenuBorder()
+ * + * @param defaults the UIDefaults instance to which the values are added + */ + protected void initComponentDefaults(UIDefaults defaults) + { + super.initComponentDefaults(defaults); + Object[] myDefaults = new Object[] { + "Button.background", new ColorUIResource(getControl()), + "Button.border", MetalBorders.getButtonBorder(), + "Button.darkShadow", new ColorUIResource(getControlDarkShadow()), + "Button.disabledText", new ColorUIResource(getControlDisabled()), + "Button.focus", new ColorUIResource(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()), + "CheckBoxMenuItem.background", new ColorUIResource(getControl()), + "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()), + "Label.background", new ColorUIResource(getControl()), + "Label.font", getControlTextFont(), + "Label.disabledForeground", new ColorUIResource(getControlDisabled()), + "Label.foreground", new ColorUIResource(getSystemTextColor()), + "Menu.background", new ColorUIResource(getControl()), + "Menu.font", getControlTextFont(), + "MenuBar.background", new ColorUIResource(getControl()), + "MenuBar.font", getControlTextFont(), + "MenuItem.background", new ColorUIResource(getControl()), + "MenuItem.font", getControlTextFont(), + "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()), + + "SplitPane.darkShadow", + new ColorUIResource(getControlDarkShadow()), + "SplitPane.highlight", + new ColorUIResource(getControlHighlight()), + + "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(), + "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.leftChildIndent", new Integer(7), + "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.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() + }; + defaults.putDefaults(myDefaults); + } + + /** + * Initializes the system color defaults. + * + * In particular this sets the following keys: + * + * + * + * + * + * + * + *
KeyValueDescription
control0xccccccThe default color for components
+ */ + protected void initSystemColorDefaults(UIDefaults defaults) + { + super.initSystemColorDefaults(defaults); + Object[] uiDefaults; + uiDefaults = new Object[] { + "control", new ColorUIResource(getControl()) + }; + defaults.putDefaults(uiDefaults); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java new file mode 100644 index 0000000..ec9bf2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java @@ -0,0 +1,73 @@ +/* MetalPopupMenuSeparatorUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +public class MetalPopupMenuSeparatorUI + extends MetalSeparatorUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalPopupMenuSeparatorUIs */ + private static MetalPopupMenuSeparatorUI instance = null; + + /** + * Constructs a new instance of MetalPopupMenuSeparatorUI. + */ + public MetalPopupMenuSeparatorUI() + { + super(); + } + + /** + * Returns an instance of MetalPopupMenuSeparatorUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalPopupMenuSeparatorUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalPopupMenuSeparatorUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java new file mode 100644 index 0000000..96d1988 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java @@ -0,0 +1,74 @@ +/* MetalProgressBarUI.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 javax.swing.JComponent; +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; + + /** + * Constructs a new instance of MetalProgressBarUI. + */ + public MetalProgressBarUI() + { + super(); + } + + /** + * Returns an instance of MetalProgressBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalProgressBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalProgressBarUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java new file mode 100644 index 0000000..a668f91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java @@ -0,0 +1,74 @@ +/* MetalRadioButtonUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicRadioButtonUI; + +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; + + /** + * Constructs a new instance of MetalRadioButtonUI. + */ + public MetalRadioButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalRadioButtonUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalRadioButtonUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalRadioButtonUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java new file mode 100644 index 0000000..4196a4e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -0,0 +1,74 @@ +/* MetalRootPaneUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicRootPaneUI; + +public class MetalRootPaneUI + extends BasicRootPaneUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalRootPaneUIs */ + private static MetalRootPaneUI instance = null; + + /** + * Constructs a new instance of MetalRootPaneUI. + */ + public MetalRootPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalRootPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalRootPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalRootPaneUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java new file mode 100644 index 0000000..526dfb5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -0,0 +1,146 @@ +/* MetalScrollBarUI.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.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollBarUI; + +public class MetalScrollBarUI + extends BasicScrollBarUI +{ + + /** 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; + + /** + * Constructs a new instance of MetalScrollBarUI. + */ + public MetalScrollBarUI() + { + super(); + } + + /** + * Returns an instance of MetalScrollBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalScrollBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalScrollBarUI instance; + if (o == null) + { + instance = new MetalScrollBarUI(); + instances.put(component, instance); + } + else + instance = (MetalScrollBarUI) o; + + return instance; + } + + /** + * Paints the slider button of the ScrollBar. + * + * @param g the Graphics context to use + * @param c the JComponent on which we paint + * @param thumbBounds the rectangle that is the slider button + */ + 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); + + // draw the outer dark line + g.setColor(thumbDarkShadowColor); + g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1, + thumbBounds.height - 1); + + // draw the inner light line + 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); + + // 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); + + // 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. + * + * @return The minimum thumb size. + */ + protected Dimension getMinimumThumbSize() + { + return MIN_THUMB_SIZE; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java new file mode 100644 index 0000000..3e1198b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java @@ -0,0 +1,74 @@ +/* MetalScrollPaneUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollPaneUI; + +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. + */ + public MetalScrollPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalScrollPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalScrollPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalScrollPaneUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java new file mode 100644 index 0000000..6e78ccb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java @@ -0,0 +1,74 @@ +/* MetalSeparatorUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSeparatorUI; + +public class MetalSeparatorUI + extends BasicSeparatorUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalSeparatorUIs */ + private static MetalSeparatorUI instance = null; + + /** + * Constructs a new instance of MetalSeparatorUI. + */ + public MetalSeparatorUI() + { + super(); + } + + /** + * Returns an instance of MetalSeparatorUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSeparatorUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalSeparatorUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java new file mode 100644 index 0000000..a857d6a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java @@ -0,0 +1,87 @@ +/* MetalSliderUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSliderUI; + +public class MetalSliderUI + extends BasicSliderUI +{ + + /** The UI instances for MetalSliderUIs */ + private static HashMap instances; + + /** + * Constructs a new instance of MetalSliderUI. + */ + public MetalSliderUI() + { + super(null); + } + + /** + * Returns an instance of MetalSliderUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSliderUI + */ + 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; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java new file mode 100644 index 0000000..60e9c05 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java @@ -0,0 +1,84 @@ +/* MetalSplitPaneDivider.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 javax.swing.plaf.basic.BasicSplitPaneDivider; + +/** + * The divider that is used by the MetalSplitPaneUI. + * + * @author Roman Kennke (roman@kennke.org) + * + */ +class MetalSplitPaneDivider extends BasicSplitPaneDivider +{ + /** The dark color in the pattern. */ + Color dark; + + /** The light color in the pattern. */ + Color light; + + /** + * Creates a new instance of MetalSplitPaneDivider. + * + * @param ui the MetalSplitPaneUI that uses this divider + */ + public MetalSplitPaneDivider(MetalSplitPaneUI ui, Color light, Color dark) + { + super(ui); + this.light = light; + this.dark = dark; + } + + /** + * Paints the divider. + * + * @param g the Graphics context to use for painting + */ + public void paint(Graphics g) + { + //super.paint(g); + Dimension s = getSize(); + MetalUtils.fillMetalPattern(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 new file mode 100644 index 0000000..b7ea898 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java @@ -0,0 +1,106 @@ +/* MetalSplitPaneUI.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.util.HashMap; + +import javax.swing.JComponent; +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; + +public class MetalSplitPaneUI + extends BasicSplitPaneUI +{ + + /** The UI instances for MetalSplitPaneUIs */ + private static HashMap instances; + + /** + * Constructs a new instance of MetalSplitPaneUI. + */ + public MetalSplitPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalSplitPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSplitPaneUI + */ + 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; + } + + /** + * Returns the divider that is used by the JSplitPane. + * + * The divider returned by this method is a {@link BasicSplitPaneDivider} + * that is drawn using the Metal look. + * + * @return the default divider to use for JSplitPanes. + */ + public BasicSplitPaneDivider createDefaultDivider() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + Color light = defaults.getColor("SplitPane.highlight"); + Color dark = defaults.getColor("SplitPane.darkShadow"); + return new MetalSplitPaneDivider(this, light, dark); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java new file mode 100644 index 0000000..bf50f91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -0,0 +1,86 @@ +/* MetalTabbedPaneUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTabbedPaneUI; + +public class MetalTabbedPaneUI + extends BasicTabbedPaneUI +{ + + /** The shared UI instance for JTabbedPanes. */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTabbedPaneUI. + */ + public MetalTabbedPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalTabbedPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of 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; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java new file mode 100644 index 0000000..d6e50e1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java @@ -0,0 +1,86 @@ +/* MetalTextFieldUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTextFieldUI; + +public class MetalTextFieldUI + extends BasicTextFieldUI +{ + + /** The UI instances for MetalTextFieldUIs */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTextFieldUI. + */ + public MetalTextFieldUI() + { + super(); + } + + /** + * Returns an instance of MetalTextFieldUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalTextFieldUI + */ + 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; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java new file mode 100644 index 0000000..d5131af --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java @@ -0,0 +1,576 @@ +/* MetalTheme.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + + +package javax.swing.plaf.metal; + +import java.awt.Color; + +import javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; + +/** + * The base class for themes used by the {@link MetalLookAndFeel}. A default + * theme ({@link DefaultMetalTheme}) is provided, or you can create and use + * your own. + * + * @see MetalLookAndFeel#setCurrentTheme(MetalTheme) + */ +public abstract class MetalTheme +{ + private ColorUIResource BLACK = new ColorUIResource(Color.BLACK); + private ColorUIResource WHITE = new ColorUIResource(Color.WHITE); + + /** + * Default constructor. + */ + public MetalTheme() + { + // Do nothing here. + } + + /** + * Returns the name of the theme. + * + * @return The name of the theme. + */ + public abstract String getName(); + + /** + * Adds custom entries to the UI defaults table. This method is empty. + * + * @param table the table. + */ + public void addCustomEntriesToTable(UIDefaults table) + { + // Do nothing here. + // This method needs to be overridden to actually do something. + // It is called from MetalLookAndFeel.getDefaults(). + } + + /** + * Returns the accelerator foreground color. The default implementation + * returns the color from {@link #getPrimary1()}. + * + * @return The accelerator foreground color. + */ + public ColorUIResource getAcceleratorForeground() + { + return getPrimary1(); + } + + /** + * Returns the accelerator selected foreground color. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The accelerator selected foreground color. + */ + public ColorUIResource getAcceleratorSelectedForeground() + { + return getBlack(); + } + + /** + * Returns the control color. The default implementation returns the color + * from {@link #getSecondary3()}. + * + * @return The control color. + */ + public ColorUIResource getControl() + { + return getSecondary3(); + } + + /** + * Returns the color used for dark shadows on controls. The default + * implementation returns the color from {@link #getSecondary1()}. + * + * @return The color used for dark shadows on controls. + */ + public ColorUIResource getControlDarkShadow() + { + return getSecondary1(); + } + + /** + * Returns the color used for disabled controls. The default implementation + * returns the color from {@link #getSecondary1()}. + * + * @return The color used for disabled controls. + */ + public ColorUIResource getControlDisabled() + { + return getSecondary2(); + } + + /** + * Returns the color used to draw highlights for controls. The default + * implementation returns the color from {@link #getWhite()}. + * + * @return The color used to draw highlights for controls. + */ + public ColorUIResource getControlHighlight() + { + return getWhite(); + } + + /** + * Returns the color used to display control info. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The color used to display control info. + */ + public ColorUIResource getControlInfo() + { + return getBlack(); + } + + /** + * Returns the color used to draw shadows for controls. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The color used to draw shadows for controls. + */ + public ColorUIResource getControlShadow() + { + return getSecondary2(); + } + + /** + * Returns the color used for text on controls. The default implementation + * returns the color from {@link #getControlInfo()}. + * + * @return The color used for text on controls. + */ + public ColorUIResource getControlTextColor() + { + return getControlInfo(); + } + + /** + * Returns the color used for the desktop background. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The color used for the desktop background. + */ + public ColorUIResource getDesktopColor() + { + return getPrimary2(); + } + + /** + * Returns the color used to draw focus highlights. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The color used to draw focus highlights. + */ + public ColorUIResource getFocusColor() + { + return getPrimary2(); + } + + /** + * Returns the color used to draw highlighted text. The default + * implementation returns the color from {@link #getHighlightedTextColor()}. + * + * @return The color used to draw highlighted text. + */ + public ColorUIResource getHighlightedTextColor() + { + return getControlTextColor(); + } + + /** + * Returns the color used to draw text on inactive controls. The default + * implementation returns the color from {@link #getControlDisabled()}. + * + * @return The color used to draw text on inactive controls. + */ + public ColorUIResource getInactiveControlTextColor() + { + return getControlDisabled(); + } + + /** + * Returns the color used to draw inactive system text. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The color used to draw inactive system text. + */ + public ColorUIResource getInactiveSystemTextColor() + { + return getSecondary2(); + } + + /** + * Returns the background color for menu items. The default implementation + * returns the color from {@link #getSecondary3()}. + * + * @return The background color for menu items. + * + * @see #getMenuSelectedBackground() + */ + public ColorUIResource getMenuBackground() + { + return getSecondary3(); + } + + /** + * Returns the foreground color for disabled menu items. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The foreground color for disabled menu items. + * + * @see #getMenuForeground() + */ + public ColorUIResource getMenuDisabledForeground() + { + return getSecondary2(); + } + + /** + * Returns the foreground color for menu items. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The foreground color for menu items. + * + * @see #getMenuDisabledForeground() + * @see #getMenuSelectedForeground() + */ + public ColorUIResource getMenuForeground() + { + return getBlack(); + } + + /** + * Returns the background color for selected menu items. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The background color for selected menu items. + * + * @see #getMenuBackground() + */ + public ColorUIResource getMenuSelectedBackground() + { + return getPrimary2(); + } + + /** + * Returns the foreground color for selected menu items. The default + * implementation returns the value from {@link #getBlack()}. + * + * @return The foreground color for selected menu items. + * + * @see #getMenuForeground() + */ + public ColorUIResource getMenuSelectedForeground() + { + return getBlack(); + } + + /** + * Returns the primary color for controls. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The primary color for controls. + */ + public ColorUIResource getPrimaryControl() + { + return getPrimary3(); + } + + /** + * Returns the primary color for the dark shadow on controls. The default + * implementation returns the color from {@link #getPrimary1()}. + * + * @return The primary color for the dark shadow on controls. + */ + public ColorUIResource getPrimaryControlDarkShadow() + { + return getPrimary1(); + } + + /** + * Returns the primary color for the highlight on controls. The default + * implementation returns the color from {@link #getWhite()}. + * + * @return The primary color for the highlight on controls. + */ + public ColorUIResource getPrimaryControlHighlight() + { + return getWhite(); + } + + /** + * Returns the primary color for the information on controls. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The primary color for the information on controls. + */ + public ColorUIResource getPrimaryControlInfo() + { + return getBlack(); + } + + /** + * Returns the primary color for the shadow on controls. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The primary color for the shadow on controls. + */ + public ColorUIResource getPrimaryControlShadow() + { + return getPrimary2(); + } + + /** + * Returns the background color for separators. The default implementation + * returns the color from {@link #getWhite()}. + * + * @return The background color for separators. + */ + public ColorUIResource getSeparatorBackground() + { + return getWhite(); + } + + /** + * Returns the foreground color for separators. The default implementation + * returns the value from {@link #getPrimary1()}. + * + * @return The foreground color for separators. + */ + public ColorUIResource getSeparatorForeground() + { + return getPrimary1(); + } + + /** + * Returns the color used for system text. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The color used for system text. + */ + public ColorUIResource getSystemTextColor() + { + return getBlack(); + } + + /** + * Returns the color used to highlight text. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The color used to highlight text. + */ + public ColorUIResource getTextHighlightColor() + { + return getPrimary3(); + } + + /** + * Returns the color used to display user text. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The color used to display user text. + */ + public ColorUIResource getUserTextColor() + { + return getBlack(); + } + + /** + * Returns the window background color. The default implementation returns + * the color from {@link #getWhite()}. + * + * @return The window background color. + */ + public ColorUIResource getWindowBackground() + { + return getWhite(); + } + + /** + * Returns the window title background color. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The window title background color. + */ + public ColorUIResource getWindowTitleBackground() + { + return getPrimary3(); + } + + /** + * Returns the window title foreground color. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The window title foreground color. + */ + public ColorUIResource getWindowTitleForeground() + { + return getBlack(); + } + + /** + * Returns the background color for an inactive window title. The default + * implementation returns the color from {@link #getSecondary3()}. + * + * @return The background color for an inactive window title. + */ + public ColorUIResource getWindowTitleInactiveBackground() + { + return getSecondary3(); + } + + /** + * Returns the foreground color for an inactive window title. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The foreground color for an inactive window title. + */ + public ColorUIResource getWindowTitleInactiveForeground() + { + return getBlack(); + } + + /** + * Returns the color used for black. + * + * @return The color used for black. + */ + protected ColorUIResource getBlack() + { + return BLACK; + } + + /** + * Returns the color used for white. + * + * @return The color used for white. + */ + protected ColorUIResource getWhite() + { + return WHITE; + } + + /** + * Returns the first primary color for this theme. + * + * @return The first primary color. + */ + protected abstract ColorUIResource getPrimary1(); + + /** + * Returns the second primary color for this theme. + * + * @return The second primary color. + */ + protected abstract ColorUIResource getPrimary2(); + + /** + * Returns the third primary color for this theme. + * + * @return The third primary color. + */ + protected abstract ColorUIResource getPrimary3(); + + /** + * Returns the first secondary color for this theme. + * + * @return The first secondary color. + */ + protected abstract ColorUIResource getSecondary1(); + + /** + * Returns the second secondary color for this theme. + * + * @return The second secondary color. + */ + protected abstract ColorUIResource getSecondary2(); + + /** + * Returns the third secondary color for this theme. + * + * @return The third secondary color. + */ + protected abstract ColorUIResource getSecondary3(); + + /** + * Returns the font used for text on controls. + * + * @return The font used for text on controls. + */ + public abstract FontUIResource getControlTextFont(); + + /** + * Returns the font used for text in menus. + * + * @return The font used for text in menus. + */ + public abstract FontUIResource getMenuTextFont(); + + /** + * Returns the font used for sub text. + * + * @return The font used for sub text. + */ + public abstract FontUIResource getSubTextFont(); + + /** + * Returns the font used for system text. + * + * @return The font used for system text. + */ + public abstract FontUIResource getSystemTextFont(); + + /** + * Returns the font used for user text. + * + * @return The font used for user text. + */ + public abstract FontUIResource getUserTextFont(); + + /** + * Returns the font used for window titles. + * + * @return The font used for window titles. + */ + public abstract FontUIResource getWindowTitleFont(); + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java new file mode 100644 index 0000000..7913cdb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -0,0 +1,74 @@ +/* MetalToggleButtonUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToggleButtonUI; + +public class MetalToggleButtonUI + extends BasicToggleButtonUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToggleButtonUIs */ + private static MetalToggleButtonUI instance = null; + + /** + * Constructs a new instance of MetalToggleButtonUI. + */ + public MetalToggleButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalToggleButtonUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToggleButtonUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToggleButtonUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java new file mode 100644 index 0000000..39af001 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java @@ -0,0 +1,74 @@ +/* MetalToolBarUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToolBarUI; + +public class MetalToolBarUI + extends BasicToolBarUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToolBarUIs */ + private static MetalToolBarUI instance = null; + + /** + * Constructs a new instance of MetalToolBarUI. + */ + public MetalToolBarUI() + { + super(); + } + + /** + * Returns an instance of MetalToolBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToolBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToolBarUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java new file mode 100644 index 0000000..c88b653 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java @@ -0,0 +1,74 @@ +/* MetalToolTipUI.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 javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToolTipUI; + +public class MetalToolTipUI + extends BasicToolTipUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToolTipUIs */ + private static MetalToolTipUI instance = null; + + /** + * Constructs a new instance of MetalToolTipUI. + */ + public MetalToolTipUI() + { + super(); + } + + /** + * Returns an instance of MetalToolTipUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToolTipUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToolTipUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java new file mode 100644 index 0000000..d85d61c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java @@ -0,0 +1,86 @@ +/* MetalTreeUI.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.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTreeUI; + +public class MetalTreeUI + extends BasicTreeUI +{ + + /** The UI instances for MetalTreeUIs */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTreeUI. + */ + public MetalTreeUI() + { + super(); + } + + /** + * Returns an instance of MetalTreeUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalTreeUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalTreeUI instance; + if (o == null) + { + instance = new MetalTreeUI(); + instances.put(component, instance); + } + else + instance = (MetalTreeUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java new file mode 100644 index 0000000..a342ee0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -0,0 +1,87 @@ +/* Metaltils.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.Graphics; + +/** + * Some utility and helper methods for the Metal Look & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ +class MetalUtils +{ + + /** + * Fills a rectangle with the typical Metal pattern. + * + * @param g the Graphics 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 w 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, + Color light, Color dark) + { + int xOff = 0; + for (int mY = y; mY < (y + h); mY++) + { + // 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) + { + g.drawLine(mX, mY, mX, mY); + } + + // increase x offset + xOff++; + if (xOff > 3) + xOff = 0; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html new file mode 100644 index 0000000..2ea787b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/package.html @@ -0,0 +1,46 @@ + + + + +GNU Classpath - javax.swing.plaf.metal + + +

Provides a cross-platform look and feel known as "Metal".

+ + + diff --git a/libjava/classpath/javax/swing/plaf/package.html b/libjava/classpath/javax/swing/plaf/package.html new file mode 100644 index 0000000..c266074 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.plaf + + +

A base package for the "pluggable look and feel" (plaf) mechanism used by +the javax.swing classes.

+ + + diff --git a/libjava/classpath/javax/swing/table/AbstractTableModel.java b/libjava/classpath/javax/swing/table/AbstractTableModel.java new file mode 100644 index 0000000..3e9f6e9 --- /dev/null +++ b/libjava/classpath/javax/swing/table/AbstractTableModel.java @@ -0,0 +1,301 @@ +/* AbstractTableModel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +/** + * A base class that can be used to create implementations of the + * {@link TableModel} interface. + * + * @author Andrew Selkirk + */ +public abstract class AbstractTableModel implements TableModel, Serializable +{ + static final long serialVersionUID = -5798593159423650347L; + + /** + * Storage for the listeners registered with this model. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Creates a default instance. + */ + public AbstractTableModel() + { + // no setup required here + } + + /** + * Returns the name of the specified column. This method generates default + * names in a sequence (starting with column 0): A, B, C, ..., Z, AA, AB, + * AC, ..., AZ, BA, BB, BC, and so on. Subclasses may override this method + * to allow column names to be specified on some other basis. + * + * @param columnIndex the column index. + * + * @return The name of the column. + */ + public String getColumnName(int columnIndex) + { + StringBuffer buffer = new StringBuffer(); + while (columnIndex >= 0) + { + buffer.insert (0, (char) ('A' + columnIndex % 26)); + columnIndex = columnIndex / 26 - 1; + } + return buffer.toString(); + } + + /** + * Return the index of the specified column, or -1 if there is + * no column with the specified name. + * + * @param columnName the name of the column (null not permitted). + * + * @return The index of the column, -1 if not found. + * + * @see #getColumnName(int) + * @throws NullPointerException if columnName is + * null. + */ + public int findColumn(String columnName) + { + int count = getColumnCount(); + + for (int index = 0; index < count; index++) + { + String name = getColumnName(index); + + if (columnName.equals(name)) + return index; + } + + // Unable to locate. + return -1; + } + + /** + * Returns the Class for all Object instances + * in the specified column. + * + * @param columnIndex the column index. + * + * @return The class. + */ + public Class getColumnClass(int columnIndex) + { + return Object.class; + } + + /** + * Returns true if the specified cell is editable, and + * false if it is not. This implementation returns + * false for all arguments, subclasses should override the + * method if necessary. + * + * @param rowIndex the row index of the cell. + * @param columnIndex the column index of the cell. + * + * @return false. + */ + public boolean isCellEditable(int rowIndex, int columnIndex) + { + return false; + } + + /** + * Sets the value of the given cell. This implementation ignores all + * arguments and does nothing, subclasses should override the + * method if necessary. + * + * @param value the new value (null permitted). + * @param rowIndex the row index of the cell. + * @param columnIndex the column index of the cell. + */ + public void setValueAt(Object value, int rowIndex, int columnIndex) + { + // Do nothing... + } + + /** + * Adds a listener to the table model. The listener will receive notification + * of all changes to the table model. + * + * @param listener the listener. + */ + public void addTableModelListener(TableModelListener listener) + { + listenerList.add(TableModelListener.class, listener); + } + + /** + * Removes a listener from the table model so that it will no longer receive + * notification of changes to the table model. + * + * @param listener the listener to remove. + */ + public void removeTableModelListener(TableModelListener listener) + { + listenerList.remove(TableModelListener.class, listener); + } + + /** + * Returns an array containing the listeners that have been added to the + * table model. + * + * @return Array of {@link TableModelListener} objects. + * + * @since 1.4 + */ + public TableModelListener[] getTableModelListeners() + { + return (TableModelListener[]) + listenerList.getListeners(TableModelListener.class); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that the table data has changed. + */ + public void fireTableDataChanged() + { + fireTableChanged(new TableModelEvent(this, 0, Integer.MAX_VALUE)); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that the table structure has changed. + */ + public void fireTableStructureChanged() + { + fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW)); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that some rows have been inserted into the model. + * + * @param firstRow the index of the first row. + * @param lastRow the index of the last row. + */ + public void fireTableRowsInserted (int firstRow, int lastRow) + { + fireTableChanged(new TableModelEvent(this, firstRow, lastRow, + TableModelEvent.ALL_COLUMNS, + TableModelEvent.INSERT)); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that some rows have been updated. + * + * @param firstRow the index of the first row. + * @param lastRow the index of the last row. + */ + public void fireTableRowsUpdated (int firstRow, int lastRow) + { + fireTableChanged(new TableModelEvent(this, firstRow, lastRow, + TableModelEvent.ALL_COLUMNS, + TableModelEvent.UPDATE)); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that some rows have been deleted from the model. + * + * @param firstRow the index of the first row. + * @param lastRow the index of the last row. + */ + public void fireTableRowsDeleted(int firstRow, int lastRow) + { + fireTableChanged(new TableModelEvent(this, firstRow, lastRow, + TableModelEvent.ALL_COLUMNS, + TableModelEvent.DELETE)); + } + + /** + * Sends a {@link TableModelEvent} to all registered listeners to inform + * them that a single cell has been updated. + * + * @param row the row index. + * @param column the column index. + */ + public void fireTableCellUpdated (int row, int column) + { + fireTableChanged(new TableModelEvent(this, row, row, column)); + } + + /** + * Sends the specified event to all registered listeners. + * + * @param event the event to send. + */ + public void fireTableChanged(TableModelEvent event) + { + int index; + TableModelListener listener; + Object[] list = listenerList.getListenerList(); + + for (index = 0; index < list.length; index += 2) + { + listener = (TableModelListener) list [index + 1]; + listener.tableChanged (event); + } + } + + /** + * Returns an array of listeners of the given type that are registered with + * this model. + * + * @param listenerType the listener class. + * + * @return An array of listeners (possibly empty). + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } +} diff --git a/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java new file mode 100644 index 0000000..02e9fd7 --- /dev/null +++ b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java @@ -0,0 +1,234 @@ +/* DefaultTableCellRenderer.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * Class to display every cells. + */ +public class DefaultTableCellRenderer extends JLabel + implements TableCellRenderer, Serializable +{ + static final long serialVersionUID = 7878911414715528324L; + + protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0); + + public static class UIResource extends DefaultTableCellRenderer + implements javax.swing.plaf.UIResource + { + public UIResource() + { + } + } + + /** + * Creates a default table cell renderer with an empty border. + */ + public DefaultTableCellRenderer() + { + super(); + } + + /** + * Assign the unselected-foreground. + * + * @param c the color to assign + */ + public void setForeground(Color c) + { + super.setForeground(c); + } + + /** + * Assign the unselected-background. + * + * @param c the color to assign + */ + public void setBackground(Color c) + { + super.setBackground(c); + } + + /** + * Look and feel has changed. + * + *

Replaces the current UI object with the latest version from + * the UIManager.

+ */ + public void updateUI() + { + super.updateUI(); + } + + /** + * Get the string value of the object and pass it to setText(). + * + * @param table the JTable + * @param value the value of the object + * @param isSelected is the cell selected? + * @param hasFocus has the cell the focus? + * @param row the row to render + * @param column the cell to render + * + * @return this component (the default table cell renderer) + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, + boolean hasFocus, + int row, int column) + { + if (value != null) + super.setText(value.toString()); + + setOpaque(true); + + if (table == null) + return this; + + if (isSelected) + { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } + else + { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + + setEnabled(table.isEnabled()); + setFont(table.getFont()); + return this; + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ * + * @return always true + */ + public boolean isOpaque() + { + return true; + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ */ + public void validate() + { + // Does nothing. + } + + public void revalidate() + { + // Does nothing. + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ */ + public void repaint(long tm, int x, int y, int width, int height) + { + // Does nothing. + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ */ + public void repaint(Rectangle r) + { + // Does nothing. + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ */ + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + // Does nothing. + } + + /** + * Overriden for performance. + * + *

This method needs to be overridden in a subclass to actually + * do something.

+ */ + public void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) + { + // Does nothing. + } + + /** + * Sets the String for this cell. + * + * @param value the string value for this cell; if value is null it + * sets the text value to an empty string + */ + protected void setValue(Object value) + { + super.setText((value!=null) ? value.toString() : ""); + } +} diff --git a/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java b/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java new file mode 100644 index 0000000..1087177 --- /dev/null +++ b/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java @@ -0,0 +1,563 @@ +/* DefaultTableColumnModel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Vector; + +import javax.swing.DefaultListSelectionModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.EventListenerList; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.event.TableColumnModelListener; + +/** + * DefaultTableColumnModel + * @author Andrew Selkirk + * @version 1.0 + */ +public class DefaultTableColumnModel + implements TableColumnModel, PropertyChangeListener, ListSelectionListener, + Serializable +{ + private static final long serialVersionUID = 6580012493508960512L; + + /** + * Columns that this model keeps track of. + */ + protected Vector tableColumns; + + /** + * Selection Model that keeps track of columns selection + */ + protected ListSelectionModel selectionModel; + + /** + * Space between two columns. By default it is set to 1 + */ + protected int columnMargin; + + /** + * listenerList keeps track of all listeners registered with this model + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * changeEvent is fired when change occurs in one of the columns properties + */ + protected transient ChangeEvent changeEvent = new ChangeEvent(this); + + /** + * Indicates whether columns can be selected + */ + protected boolean columnSelectionAllowed; + + /** + * Total width of all the columns in this model + */ + protected int totalColumnWidth; + + /** + * Constructor DefaultTableColumnModel + */ + public DefaultTableColumnModel() + { + tableColumns = new Vector(); + setSelectionModel(createSelectionModel()); + columnMargin = 1; + columnSelectionAllowed = false; + } + + /** + * addColumn adds column to the model. This method fires ColumnAdded + * event to model's registered TableColumnModelListeners. + * + * @param col column to add + */ + public void addColumn(TableColumn col) + { + if (col == null) + throw new IllegalArgumentException("Null 'col' argument."); + tableColumns.add(col); + invalidateWidthCache(); + fireColumnAdded(new TableColumnModelEvent(this, 0, tableColumns.size() - 1)); + } + + /** + * removeColumn removes table column from the model. This method fires + * ColumnRemoved event to model's registered TableColumnModelListeners. + * + * @param col column to be removed + */ + public void removeColumn(TableColumn col) + { + int index = this.tableColumns.indexOf(col); + if (index < 0) + return; + fireColumnRemoved(new TableColumnModelEvent(this, index, 0)); + tableColumns.remove(col); + invalidateWidthCache(); + } + + /** + * moveColumn moves column at index i to index j. This method fires + * ColumnMoved event to model's registered TableColumnModelListeners. + * + * @param i index of the column that will be moved + * @param j index of column's new location + */ + public void moveColumn(int i, int j) + { + int columnCount = getColumnCount(); + if (i < 0 || i >= columnCount) + throw new IllegalArgumentException("Index 'i' out of range."); + if (j < 0 || j >= columnCount) + throw new IllegalArgumentException("Index 'j' out of range."); + Object column = tableColumns.remove(i); + tableColumns.add(j, column); + fireColumnAdded(new TableColumnModelEvent(this, i, j)); + } + + /** + * setColumnMargin sets margin of the columns. + * @param m new column margin + */ + public void setColumnMargin(int m) + { + columnMargin = m; + fireColumnMarginChanged(); + } + + /** + * getColumnCount returns number of columns in the model + * @return int number of columns in the model + */ + public int getColumnCount() + { + return tableColumns.size(); + } + + /** + * getColumns + * @return Enumeration + */ + public Enumeration getColumns() + { + return tableColumns.elements(); + } + + /** + * Returns the index of the {@link TableColumn} with the given identifier. + * + * @param identifier the identifier (null not permitted). + * + * @return The index of the {@link TableColumn} with the given identifier. + * + * @throws IllegalArgumentException if identifier is + * null or there is no column with that identifier. + */ + public int getColumnIndex(Object identifier) + { + if (identifier == null) + throw new IllegalArgumentException("Null identifier."); + int columnCount = tableColumns.size(); + for (int i = 0; i < columnCount; i++) + { + TableColumn tc = (TableColumn) tableColumns.get(i); + if (identifier.equals(tc.getIdentifier())) + return i; + } + throw new IllegalArgumentException("No TableColumn with that identifier."); + } + + /** + * getColumn returns column at the specified index + * @param i index of the column + * @return TableColumn column at the specified index + */ + public TableColumn getColumn(int i) + { + return (TableColumn) tableColumns.get(i); + } + + /** + * getColumnMargin returns column margin + * @return int column margin + */ + public int getColumnMargin() + { + return columnMargin; + } + + /** + * getColumnIndexAtX returns column that contains specified x-coordinate. + * @param x x-coordinate that column should contain + * @return int index of the column that contains specified x-coordinate relative + * to this column model + */ + public int getColumnIndexAtX(int x) + { + for (int i = 0; i < tableColumns.size(); ++i) + { + int w = ((TableColumn)tableColumns.get(i)).getWidth(); + if (0 <= x && x < w) + return i; + else + x -= w; + } + return -1; + } + + /** + * getTotalColumnWidth returns total width of all the columns including + * column's margins. + * + * @return total width of all the columns + */ + public int getTotalColumnWidth() + { + if (totalColumnWidth == -1) + recalcWidthCache(); + return totalColumnWidth; + } + + /** + * setSelectionModel sets selection model that will be used by this ColumnTableModel + * to keep track of currently selected columns + * + * @param model new selection model + * @exception IllegalArgumentException if model is null + */ + public void setSelectionModel(ListSelectionModel model) + { + if (model == null) + throw new IllegalArgumentException(); + + selectionModel = model; + selectionModel.addListSelectionListener(this); + } + + /** + * getSelectionModel returns selection model + * @return ListSelectionModel selection model + */ + public ListSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * setColumnSelectionAllowed sets whether column selection is allowed + * or not. + * + * @param flag true if column selection is allowed and false otherwise + */ + public void setColumnSelectionAllowed(boolean flag) + { + columnSelectionAllowed = flag; + } + + /** + * getColumnSelectionAllowed indicates whether column selection is + * allowed or not. + * + * @return boolean true if column selection is allowed and false otherwise. + */ + public boolean getColumnSelectionAllowed() + { + return columnSelectionAllowed; + } + + /** + * getSelectedColumns returns array containing indexes of currently + * selected columns + * + * @return int[] array containing indexes of currently selected columns + */ + public int[] getSelectedColumns() + { + // FIXME: Implementation of this method was taken from private method + // JTable.getSelections(), which is used in various places in JTable + // including selected row calculations and cannot be simply removed. + // This design should be improved to illuminate duplication of code. + + ListSelectionModel lsm = this.selectionModel; + int sz = getSelectedColumnCount(); + int [] ret = new int[sz]; + + int lo = lsm.getMinSelectionIndex(); + int hi = lsm.getMaxSelectionIndex(); + int j = 0; + java.util.ArrayList ls = new java.util.ArrayList(); + if (lo != -1 && hi != -1) + { + switch (lsm.getSelectionMode()) + { + case ListSelectionModel.SINGLE_SELECTION: + ret[0] = lo; + break; + + case ListSelectionModel.SINGLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + ret[j++] = i; + break; + + case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + if (lsm.isSelectedIndex(i)) + ret[j++] = i; + break; + } + } + return ret; + } + + /** + * getSelectedColumnCount returns number of currently selected columns + * @return int number of currently selected columns + */ + public int getSelectedColumnCount() + { + // FIXME: Implementation of this method was taken from private method + // JTable.countSelections(), which is used in various places in JTable + // including selected row calculations and cannot be simply removed. + // This design should be improved to illuminate duplication of code. + + ListSelectionModel lsm = this.selectionModel; + int lo = lsm.getMinSelectionIndex(); + int hi = lsm.getMaxSelectionIndex(); + int sum = 0; + + if (lo != -1 && hi != -1) + { + switch (lsm.getSelectionMode()) + { + case ListSelectionModel.SINGLE_SELECTION: + sum = 1; + break; + + case ListSelectionModel.SINGLE_INTERVAL_SELECTION: + sum = hi - lo + 1; + break; + + case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: + for (int i = lo; i <= hi; ++i) + if (lsm.isSelectedIndex(i)) + ++sum; + break; + } + } + + return sum; + } + + /** + * addColumnModelListener adds specified listener to the model's + * listener list + * + * @param listener the listener to add + */ + public void addColumnModelListener(TableColumnModelListener listener) + { + listenerList.add(TableColumnModelListener.class, listener); + } + + /** + * removeColumnModelListener removes specified listener from the model's + * listener list. + * + * @param listener the listener to remove + */ + public void removeColumnModelListener(TableColumnModelListener listener) + { + listenerList.remove(TableColumnModelListener.class, listener); + } + + /** + * @since 1.4 + */ + public TableColumnModelListener[] getColumnModelListeners() + { + return (TableColumnModelListener[]) + listenerList.getListeners(TableColumnModelListener.class); + } + + /** + * fireColumnAdded fires TableColumnModelEvent to registered + * TableColumnModelListeners to indicate that column was added + * + * @param e TableColumnModelEvent + */ + protected void fireColumnAdded(TableColumnModelEvent e) + { + TableColumnModelListener[] listeners = getColumnModelListeners(); + + for (int i=0; i< listeners.length; i++) + listeners[i].columnAdded(e); + } + + /** + * fireColumnAdded fires TableColumnModelEvent to registered + * TableColumnModelListeners to indicate that column was removed + * + * @param e TableColumnModelEvent + */ + protected void fireColumnRemoved(TableColumnModelEvent e) + { + TableColumnModelListener[] listeners = getColumnModelListeners(); + + for (int i=0; i< listeners.length; i++) + listeners[i].columnRemoved(e); + } + + /** + * fireColumnAdded fires TableColumnModelEvent to registered + * TableColumnModelListeners to indicate that column was moved + * + * @param e TableColumnModelEvent + */ + protected void fireColumnMoved(TableColumnModelEvent e) + { + TableColumnModelListener[] listeners = getColumnModelListeners(); + + for (int i=0; i< listeners.length; i++) + listeners[i].columnMoved(e); + } + + /** + * fireColumnSelectionChanged fires TableColumnModelEvent to model's + * registered TableColumnModelListeners to indicate that different column + * was selected. + * + * @param evt ListSelectionEvent + */ + protected void fireColumnSelectionChanged(ListSelectionEvent evt) + { + EventListener [] listeners = getListeners(TableColumnModelListener.class); + for (int i = 0; i < listeners.length; ++i) + ((TableColumnModelListener)listeners[i]).columnSelectionChanged(evt); + } + + /** + * fireColumnMarginChanged fires TableColumnModelEvent to model's + * registered TableColumnModelListeners to indicate that column margin + * was changed. + */ + protected void fireColumnMarginChanged() + { + EventListener [] listeners = getListeners(TableColumnModelListener.class); + for (int i = 0; i < listeners.length; ++i) + ((TableColumnModelListener)listeners[i]).columnMarginChanged(changeEvent); + } + + /** + * getListeners returns currently registered listeners with this model. + * @param listenerType type of listeners to return + * + * @return EventListener[] array of model's listeners of the specified type + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * propertyChange handles changes occuring in the properties of the + * model's columns. + * + * @param evt PropertyChangeEvent + */ + public void propertyChange(PropertyChangeEvent evt) + { + if (evt.getPropertyName().equals(TableColumn.COLUMN_WIDTH_PROPERTY)) + invalidateWidthCache(); + } + + /** + * valueChanged handles changes in the selectionModel. + * @param e ListSelectionEvent + */ + public void valueChanged(ListSelectionEvent e) + { + fireColumnSelectionChanged(e); + } + + /** + * createSelectionModel creates selection model that will keep track + * of currently selected column(s) + * + * @return ListSelectionModel selection model of the columns + */ + protected ListSelectionModel createSelectionModel() + { + return new DefaultListSelectionModel(); + } + + /** + * recalcWidthCache calculates total width of the columns. + * If the current cache of the total width is in invalidated state, + * then width is recalculated. Otherwise nothing is done. + */ + protected void recalcWidthCache() + { + if (totalColumnWidth == -1) + { + totalColumnWidth = 0; + for (int i = 0; i < tableColumns.size(); ++i) + { + totalColumnWidth += ((TableColumn)tableColumns.get(i)).getWidth(); + } + } + } + + /** + * invalidateWidthCache + */ + private void invalidateWidthCache() + { + totalColumnWidth = -1; + } +} diff --git a/libjava/classpath/javax/swing/table/DefaultTableModel.java b/libjava/classpath/javax/swing/table/DefaultTableModel.java new file mode 100644 index 0000000..6844f2a --- /dev/null +++ b/libjava/classpath/javax/swing/table/DefaultTableModel.java @@ -0,0 +1,588 @@ +/* DefaultTableModel.java -- + Copyright (C) 2002, 2004, 2005, Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.io.Serializable; +import java.util.Vector; + +import javax.swing.event.TableModelEvent; + +/** + * A two dimensional data structure used to store Object + * instances, usually for display in a JTable component. + * + * @author Andrew Selkirk + */ +public class DefaultTableModel extends AbstractTableModel + implements Serializable +{ + static final long serialVersionUID = 6680042567037222321L; + + /** + * Storage for the rows in the table (each row is itself + * a Vector). + */ + protected Vector dataVector; + + /** + * Storage for the column identifiers. + */ + protected Vector columnIdentifiers; + + /** + * Creates an empty table with zero rows and zero columns. + */ + public DefaultTableModel() + { + this(0, 0); + } + + /** + * Creates a new table with the specified number of rows and columns. + * All cells in the table are initially empty (set to null). + * + * @param numRows the number of rows. + * @param numColumns the number of columns. + */ + public DefaultTableModel(int numRows, int numColumns) + { + Vector defaultNames = new Vector(numColumns); + Vector data = new Vector(numRows); + for (int i = 0; i < numColumns; i++) + { + defaultNames.add(super.getColumnName(i)); + } + for (int r = 0; r < numRows; r++) + { + Vector tmp = new Vector(numColumns); + tmp.setSize(numColumns); + data.add(tmp); + } + setDataVector(data, defaultNames); + } + + /** + * Creates a new table with the specified column names and number of + * rows. The number of columns is determined by the number of column + * names supplied. + * + * @param columnNames the column names. + * @param numRows the number of rows. + */ + public DefaultTableModel(Vector columnNames, int numRows) + { + if (numRows < 0) + throw new IllegalArgumentException("numRows < 0"); + Vector data = new Vector(); + int numColumns = 0; + + if (columnNames != null) + numColumns = columnNames.size(); + + while (0 < numRows--) + { + Vector rowData = new Vector(); + rowData.setSize(numColumns); + data.add(rowData); + } + setDataVector(data, columnNames); + } + + /** + * Creates a new table with the specified column names and row count. + * + * @param columnNames the column names. + * @param numRows the number of rows. + */ + public DefaultTableModel(Object[] columnNames, int numRows) + { + this(convertToVector(columnNames), numRows); + } + + /** + * Creates a new table with the specified data values and column names. + * + * @param data the data values. + * @param columnNames the column names. + */ + public DefaultTableModel(Vector data, Vector columnNames) + { + setDataVector(data, columnNames); + } + + /** + * Creates a new table with the specified data values and column names. + * + * @param data the data values. + * @param columnNames the column names. + */ + public DefaultTableModel(Object[][] data, Object[] columnNames) + { + this(convertToVector(data), convertToVector(columnNames)); + } + + /** + * Returns the vector containing the row data for the table. + * + * @return The data vector. + */ + public Vector getDataVector() + { + return dataVector; + } + + /** + * Sets the data and column identifiers for the table. The data vector + * contains a Vector for each row in the table - if the + * number of objects in each row does not match the number of column + * names specified, the row data is truncated or expanded (by adding + * null values) as required. + * + * @param data the data for the table (a vector of row vectors). + * @param columnNames the column names. + * + * @throws NullPointerException if either argument is null. + */ + public void setDataVector(Vector data, Vector columnNames) + { + if (data == null) + dataVector = new Vector(); + else + dataVector = data; + setColumnIdentifiers(columnNames); + } + + /** + * Sets the data and column identifiers for the table. + * + * @param data the data for the table. + * @param columnNames the column names. + * + * @throws NullPointerException if either argument is null. + */ + public void setDataVector(Object[][] data, Object[] columnNames) + { + setDataVector(convertToVector(data), + convertToVector(columnNames)); + } + + /** + * Sends the specified event to all registered listeners. + * This method is equivalent to + * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. + * + * @param event the event. + */ + public void newDataAvailable(TableModelEvent event) + { + fireTableChanged(event); + } + + /** + * Sends the specified event to all registered listeners. + * This method is equivalent to + * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. + * + * @param event the event. + */ + public void newRowsAdded(TableModelEvent event) + { + fireTableChanged(event); + } + + /** + * Sends the specified event to all registered listeners. + * This method is equivalent to + * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. + * + * @param event the event. + */ + public void rowsRemoved(TableModelEvent event) + { + fireTableChanged(event); + } + + /** + * Sets the column identifiers, updates the data rows (truncating + * or padding each row with null values) to match the + * number of columns, and sends a {@link TableModelEvent} to all + * registered listeners. + * + * @param columnIdentifiers the column identifiers. + */ + public void setColumnIdentifiers(Vector columnIdentifiers) + { + this.columnIdentifiers = columnIdentifiers; + setColumnCount((columnIdentifiers == null ? 0 : columnIdentifiers.size())); + } + + /** + * Sets the column identifiers, updates the data rows (truncating + * or padding each row with null values) to match the + * number of columns, and sends a {@link TableModelEvent} to all + * registered listeners. + * + * @param columnIdentifiers the column identifiers. + */ + public void setColumnIdentifiers(Object[] columnIdentifiers) + { + setColumnIdentifiers(convertToVector(columnIdentifiers)); + } + + /** + * This method is obsolete, use {@link #setRowCount(int)} instead. + * + * @param numRows the number of rows. + */ + public void setNumRows(int numRows) + { + setRowCount(numRows); + } + + /** + * Sets the number of rows in the table. If rowCount is less + * than the current number of rows in the table, rows are discarded. + * If rowCount is greater than the current number of rows in + * the table, new (empty) rows are added. + * + * @param rowCount the row count. + */ + public void setRowCount(int rowCount) + { + int existingRowCount = dataVector.size(); + if (rowCount < existingRowCount) + { + dataVector.setSize(rowCount); + fireTableRowsDeleted(rowCount,existingRowCount-1); + } + else + { + int rowsToAdd = rowCount - existingRowCount; + for (int i = 0; i < rowsToAdd; i++) + { + Vector tmp = new Vector(); + tmp.setSize(columnIdentifiers.size()); + dataVector.add(tmp); + } + fireTableRowsInserted(existingRowCount,rowCount-1); + } + } + + /** + * Sets the number of columns in the table. Existing rows are truncated + * or padded with null values to match the new column count. + * A {@link TableModelEvent} is sent to all registered listeners. + * + * @param columnCount the column count. + */ + public void setColumnCount(int columnCount) + { + for (int i = 0; i < dataVector.size(); ++i) + { + ((Vector) dataVector.get(i)).setSize(columnCount); + } + if (columnIdentifiers != null) + columnIdentifiers.setSize(columnCount); + fireTableStructureChanged(); + } + + /** + * Adds a column with the specified name to the table. All cell values + * for the column are initially set to null. + * + * @param columnName the column name (null permitted). + */ + public void addColumn(Object columnName) + { + addColumn(columnName, (Object[]) null); + } + + /** + * Adds a column with the specified name and data values to the table. + * + * @param columnName the column name (null permitted). + * @param columnData the column data. + */ + public void addColumn(Object columnName, Vector columnData) + { + Object[] dataArray = null; + if (columnData != null) + { + int rowCount = dataVector.size(); + if (columnData.size() < rowCount) + columnData.setSize(rowCount); + dataArray = columnData.toArray(); + } + addColumn(columnName, dataArray); + } + + /** + * Adds a column with the specified name and data values to the table. + * + * @param columnName the column name (null permitted). + * @param columnData the column data. + */ + public void addColumn(Object columnName, Object[] columnData) { + if (columnData != null) + { + // check columnData array for cases where the number of items + // doesn't match the number of rows in the existing table + if (columnData.length > dataVector.size()) + { + int rowsToAdd = columnData.length - dataVector.size(); + for (int i = 0; i < rowsToAdd; i++) + { + Vector tmp = new Vector(); + tmp.setSize(columnIdentifiers.size()); + dataVector.add(tmp); + } + } + else if (columnData.length < dataVector.size()) + { + Object[] tmp = new Object[dataVector.size()]; + System.arraycopy(columnData, 0, tmp, 0, columnData.length); + columnData = tmp; + } + } + for (int i = 0; i < dataVector.size(); ++i) + { + ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]); + } + columnIdentifiers.add(columnName); + fireTableStructureChanged(); + } + + /** + * Adds a new row containing the specified data to the table and sends a + * {@link TableModelEvent} to all registered listeners. + * + * @param rowData the row data (null permitted). + */ + public void addRow(Vector rowData) { + int rowIndex = dataVector.size(); + dataVector.add(rowData); + newRowsAdded(new TableModelEvent( + this, rowIndex, rowIndex, -1, TableModelEvent.INSERT) + ); + } + + /** + * Adds a new row containing the specified data to the table and sends a + * {@link TableModelEvent} to all registered listeners. + * + * @param rowData the row data (null permitted). + */ + public void addRow(Object[] rowData) { + addRow(convertToVector(rowData)); + } + + /** + * Inserts a new row into the table. + * + * @param row the row index. + * @param rowData the row data. + */ + public void insertRow(int row, Vector rowData) { + dataVector.add(row, rowData); + fireTableRowsInserted(row,row); + } + + /** + * Inserts a new row into the table. + * + * @param row the row index. + * @param rowData the row data. + */ + public void insertRow(int row, Object[] rowData) { + insertRow(row, convertToVector(rowData)); + } + + /** + * Moves the rows from startIndex to endIndex + * (inclusive) to the specified row. + * + * @param startIndex the start row. + * @param endIndex the end row. + * @param toIndex the row to move to. + */ + public void moveRow(int startIndex, int endIndex, int toIndex) { + Vector removed = new Vector(); + for (int i = endIndex; i >= startIndex; i--) + { + removed.add(this.dataVector.remove(i)); + } + for (int i = 0; i <= endIndex - startIndex; i++) + { + dataVector.insertElementAt(removed.get(i), toIndex); + } + int firstRow = Math.min(startIndex, toIndex); + int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex)); + fireTableRowsUpdated(firstRow, lastRow); + } + + /** + * Removes a row from the table and sends a {@link TableModelEvent} to + * all registered listeners. + * + * @param row the row index. + */ + public void removeRow(int row) { + dataVector.remove(row); + fireTableRowsDeleted(row,row); + } + + /** + * Returns the number of rows in the model. + * + * @return The row count. + */ + public int getRowCount() { + return dataVector.size(); + } + + /** + * Returns the number of columns in the model. + * + * @return The column count. + */ + public int getColumnCount() { + return (columnIdentifiers == null ? 0 : columnIdentifiers.size()); + } + + /** + * Returns the name of the specified column. + * + * @param column the column index. + * + * @return The column name. + */ + public String getColumnName(int column) { + String result = ""; + if (columnIdentifiers == null) + result = super.getColumnName(column); + else + { + if (column < getColumnCount()) + { + Object id = columnIdentifiers.get(column); + if (id != null) + result = id.toString(); + else + result = super.getColumnName(column); + } + else + result = super.getColumnName(column); + } + return result; + } + + /** + * Returns true if the specified cell can be modified, and + * false otherwise. For this implementation, the method + * always returns true. + * + * @param row the row index. + * @param column the column index. + * + * @return true in all cases. + */ + public boolean isCellEditable(int row, int column) { + return true; + } + + /** + * Returns the value at the specified cell in the table. + * + * @param row the row index. + * @param column the column index. + * + * @return The value (Object, possibly null) at + * the specified cell in the table. + */ + public Object getValueAt(int row, int column) { + return ((Vector) dataVector.get(row)).get(column); + } + + /** + * Sets the value for the specified cell in the table and sends a + * {@link TableModelEvent} to all registered listeners. + * + * @param value the value (Object, null permitted). + * @param row the row index. + * @param column the column index. + */ + public void setValueAt(Object value, int row, int column) { + ((Vector) dataVector.get(row)).set(column, value); + fireTableCellUpdated(row,column); + } + + /** + * Converts the data array to a Vector. + * + * @param data the data array (null permitted). + * + * @return A vector (or null if the data array + * is null). + */ + protected static Vector convertToVector(Object[] data) { + if (data == null) + return null; + Vector vector = new Vector(data.length); + for (int i = 0; i < data.length; i++) + vector.add(data[i]); + return vector; + } + + /** + * Converts the data array to a Vector of rows. + * + * @param data the data array (null permitted). + * + * @return A vector (or null if the data array + * is null. + */ + protected static Vector convertToVector(Object[][] data) { + if (data == null) + return null; + Vector vector = new Vector(data.length); + for (int i = 0; i < data.length; i++) + vector.add(convertToVector(data[i])); + return vector; + } +} diff --git a/libjava/classpath/javax/swing/table/JTableHeader.java b/libjava/classpath/javax/swing/table/JTableHeader.java new file mode 100644 index 0000000..45586da --- /dev/null +++ b/libjava/classpath/javax/swing/table/JTableHeader.java @@ -0,0 +1,668 @@ +/* JTableHeader.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +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.util.Locale; + +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.AccessibleStateSet; +import javax.accessibility.AccessibleText; +import javax.accessibility.AccessibleValue; +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.UIManager; +import javax.swing.plaf.TableHeaderUI; + +public class JTableHeader extends JComponent +{ + protected class AccessibleJTableHeader extends AccessibleJComponent + { + protected class AccessibleJTableHeaderEntry extends AccessibleContext + implements Accessible, AccessibleComponent + { + public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t) + { + throw new Error("not implemented"); + } + + public void addFocusListener(FocusListener l) + { + throw new Error("not implemented"); + } + + public void addPropertyChangeListener(PropertyChangeListener l) + { + throw new Error("not implemented"); + } + + public boolean contains(Point p) + { + throw new Error("not implemented"); + } + + public AccessibleAction getAccessibleAction() + { + throw new Error("not implemented"); + } + + public Accessible getAccessibleAt(Point p) + { + throw new Error("not implemented"); + } + + public Accessible getAccessibleChild(int i) + { + throw new Error("not implemented"); + } + + public int getAccessibleChildrenCount() + { + throw new Error("not implemented"); + } + + public AccessibleComponent getAccessibleComponent() + { + throw new Error("not implemented"); + } + + public AccessibleContext getAccessibleContext() + { + throw new Error("not implemented"); + } + + public String getAccessibleDescription() + { + throw new Error("not implemented"); + } + + public int getAccessibleIndexInParent() + { + throw new Error("not implemented"); + } + + public String getAccessibleName() + { + throw new Error("not implemented"); + } + + public AccessibleRole getAccessibleRole() + { + throw new Error("not implemented"); + } + + public AccessibleSelection getAccessibleSelection() + { + throw new Error("not implemented"); + } + + public AccessibleStateSet getAccessibleStateSet() + { + throw new Error("not implemented"); + } + + public AccessibleText getAccessibleText() + { + throw new Error("not implemented"); + } + + public AccessibleValue getAccessibleValue() + { + throw new Error("not implemented"); + } + + public Color getBackground() + { + throw new Error("not implemented"); + } + + public Rectangle getBounds() + { + throw new Error("not implemented"); + } + + public Cursor getCursor() + { + throw new Error("not implemented"); + } + + public Font getFont() + { + throw new Error("not implemented"); + } + + public FontMetrics getFontMetrics(Font f) + { + throw new Error("not implemented"); + } + + public Color getForeground() + { + throw new Error("not implemented"); + } + + public Locale getLocale() + { + throw new Error("not implemented"); + } + + public Point getLocation() + { + throw new Error("not implemented"); + } + + public Point getLocationOnScreen() + { + throw new Error("not implemented"); + } + + public Dimension getSize() + { + throw new Error("not implemented"); + } + + public boolean isEnabled() + { + throw new Error("not implemented"); + } + + public boolean isFocusTraversable() + { + throw new Error("not implemented"); + } + + public boolean isShowing() + { + throw new Error("not implemented"); + } + + public boolean isVisible() + { + throw new Error("not implemented"); + } + + public void removeFocusListener(FocusListener l) + { + throw new Error("not implemented"); + } + + public void removePropertyChangeListener(PropertyChangeListener l) + { + throw new Error("not implemented"); + } + + public void requestFocus() + { + throw new Error("not implemented"); + } + + public void setAccessibleDescription(String s) + { + throw new Error("not implemented"); + } + + public void setAccessibleName(String s) + { + throw new Error("not implemented"); + } + + public void setBackground(Color c) + { + throw new Error("not implemented"); + } + + public void setBounds(Rectangle r) + { + throw new Error("not implemented"); + } + + public void setCursor(Cursor c) + { + throw new Error("not implemented"); + } + + public void setEnabled(boolean b) + { + throw new Error("not implemented"); + } + + public void setFont(Font f) + { + throw new Error("not implemented"); + } + + public void setForeground(Color c) + { + throw new Error("not implemented"); + } + + public void setLocation(Point p) + { + throw new Error("not implemented"); + } + + public void setSize(Dimension d) + { + throw new Error("not implemented"); + } + + public void setVisible(boolean b) + { + throw new Error("not implemented"); + } + }; + } + + private static final long serialVersionUID = 5144633983372967710L; + + /** + * The accessibleContext property. + */ + AccessibleContext accessibleContext; + + /** + * The columnModel property. + */ + protected TableColumnModel columnModel; + + /** + * The draggedColumn property. + */ + protected TableColumn draggedColumn; + + /** + * The draggedDistance property. + */ + protected int draggedDistance; + + /** + * The opaque property. + */ + boolean opaque; + + /** + * The reorderingAllowed property. + */ + protected boolean reorderingAllowed; + + /** + * The resizingAllowed property. + */ + protected boolean resizingAllowed = true; + + /** + * The resizingColumn property. + */ + protected TableColumn resizingColumn; + + /** + * The table property. + */ + protected JTable table; + + /** + * The updateTableInRealTime property. + */ + protected boolean updateTableInRealTime; + + TableCellRenderer cellRenderer; + + /** + * Creates a new default instance. + */ + public JTableHeader() + { + this(null); + } + + /** + * Creates a new header. If cm is null, a new + * table column model is created by calling + * {@link #createDefaultColumnModel()}. + * + * @param cm the table column model (null permitted). + */ + 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(); + updateUI(); + } + + /** + * Creates a default table column model. + * + * @return A default table column model. + */ + protected TableColumnModel createDefaultColumnModel() + { + return new DefaultTableColumnModel(); + } + + /** + * Get the value of the {@link #accessibleContext} property. + * + * @return The current value of the property + */ + public AccessibleContext getAccessibleContext() + { + return accessibleContext; + } + + /** + * Get the value of the {@link #columnModel} property. + * + * @return The current value of the property + */ + public TableColumnModel getColumnModel() + { + return columnModel; + } + + /** + * Get the value of the {@link #draggedColumn} property. + * + * @return The current value of the property + */ + public TableColumn getDraggedColumn() + { + return draggedColumn; + } + + /** + * Get the value of the {@link #draggedDistance} property. + * + * @return The current value of the property + */ + public int getDraggedDistance() + { + return draggedDistance; + } + + /** + * Get the value of the {@link #reorderingAllowed} property. + * + * @return The current value of the property + */ + public boolean getReorderingAllowed() + { + return reorderingAllowed; + } + + /** + * Get the value of the {@link #resizingAllowed} property. + * + * @return The current value of the property + */ + public boolean getResizingAllowed() + { + return resizingAllowed; + } + + /** + * Get the value of the {@link #resizingColumn} property. + * + * @return The current value of the property + */ + public TableColumn getResizingColumn() + { + return resizingColumn; + } + + /** + * Get the value of the {@link #table} property. + * + * @return The current value of the property + */ + public JTable getTable() + { + return table; + } + + /** + * Get the value of the {@link #updateTableInRealTime} property. + * + * @return The current value of the property + */ + public boolean getUpdateTableInRealTime() + { + return updateTableInRealTime; + } + + /** + * Get the value of the {@link #opaque} property. + * + * @return The current value of the property + */ + public boolean isOpaque() + { + return opaque; + } + + /** + * Set the value of the {@link #columnModel} property. + * + * @param c The new value of the property + */ + public void setColumnModel(TableColumnModel c) + { + columnModel = c; + } + + /** + * Set the value of the {@link #draggedColumn} property. + * + * @param d The new value of the property + */ + public void setDraggedColumn(TableColumn d) + { + draggedColumn = d; + } + + /** + * Set the value of the {@link #draggedDistance} property. + * + * @param d The new value of the property + */ + public void setDraggedDistance(int d) + { + draggedDistance = d; + } + + /** + * Set the value of the {@link #opaque} property. + * + * @param o The new value of the property + */ + public void setOpaque(boolean o) + { + opaque = o; + } + + /** + * Set the value of the {@link #reorderingAllowed} property. + * + * @param r The new value of the property + */ + public void setReorderingAllowed(boolean r) + { + reorderingAllowed = r; + } + + /** + * Set the value of the {@link #resizingAllowed} property. + * + * @param r The new value of the property + */ + public void setResizingAllowed(boolean r) + { + resizingAllowed = r; + } + + /** + * Set the value of the {@link #resizingColumn} property. + * + * @param r The new value of the property + */ + public void setResizingColumn(TableColumn r) + { + resizingColumn = r; + } + + /** + * Set the value of the {@link #table} property. + * + * @param t The new value of the property + */ + public void setTable(JTable t) + { + table = t; + } + + /** + * Set the value of the {@link #updateTableInRealTime} property. + * + * @param u The new value of the property + */ + public void setUpdateTableInRealTime(boolean u) + { + updateTableInRealTime = u; + } + + /** + * Creates a default renderer. + * + * @return A default renderer. + */ + protected TableCellRenderer createDefaultRenderer() + { + return new DefaultTableCellRenderer(); + } + + /** + * Returns the default table cell renderer. + * + * @return The default table cell renderer. + */ + public TableCellRenderer getDefaultRenderer() + { + return cellRenderer; + } + + /** + * Sets the default table cell renderer. + * + * @param cellRenderer the renderer. + */ + public void setDefaultRenderer(TableCellRenderer cellRenderer) + { + this.cellRenderer = cellRenderer; + } + + public Rectangle getHeaderRect(int column) + { + Rectangle r = getTable().getCellRect(-1, column, true); + r.height = getHeight(); + return r; + } + + protected String paramString() + { + return "JTableHeader"; + } + + // UI support + + public String getUIClassID() + { + return "TableHeaderUI"; + } + + public TableHeaderUI getUI() + { + return (TableHeaderUI) ui; + } + + public void setUI(TableHeaderUI u) + { + super.setUI(u); + } + + public void updateUI() + { + setUI((TableHeaderUI) UIManager.getUI(this)); + } + + /** + * Returns the index of the column at the specified point. + * + * @param point the point. + * + * @return The column index, or -1. + */ + public int columnAtPoint(Point point) + { + if (getBounds().contains(point)) + return columnModel.getColumnIndexAtX(point.x); + + return -1; + } +} diff --git a/libjava/classpath/javax/swing/table/TableCellEditor.java b/libjava/classpath/javax/swing/table/TableCellEditor.java new file mode 100644 index 0000000..b355311 --- /dev/null +++ b/libjava/classpath/javax/swing/table/TableCellEditor.java @@ -0,0 +1,65 @@ +/* TableCellEditor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.awt.Component; + +import javax.swing.CellEditor; +import javax.swing.JTable; + +/** + * TableCellEditor public interface + * @author Andrew Selkirk + */ +public interface TableCellEditor extends CellEditor { + + /** + * Get table cell editor component + * @param table JTable + * @param value Value of cell + * @param isSelected Cell selected + * @param row Row of cell + * @param column Column of cell + * @returns Component + */ + Component getTableCellEditorComponent(JTable table, + Object value, boolean isSelected, int row, int column); + + +} // TableCellEditor diff --git a/libjava/classpath/javax/swing/table/TableCellRenderer.java b/libjava/classpath/javax/swing/table/TableCellRenderer.java new file mode 100644 index 0000000..639b4b9 --- /dev/null +++ b/libjava/classpath/javax/swing/table/TableCellRenderer.java @@ -0,0 +1,66 @@ +/* TableCellRenderer.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.awt.Component; + +import javax.swing.JTable; + +/** + * TableCellRenderer public interface + * @author Andrew Selkirk + */ +public interface TableCellRenderer { + + /** + * Get table cell renderer component + * @param table JTable + * @param value Value of cell + * @param isSelected Cell selected + * @param hasFocus Cell has focus + * @param row Row of cell + * @param column Column of cell + * @returns Component + */ + Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, + int row, int column); + + +} // TableCellRenderer diff --git a/libjava/classpath/javax/swing/table/TableColumn.java b/libjava/classpath/javax/swing/table/TableColumn.java new file mode 100644 index 0000000..9c36bb0 --- /dev/null +++ b/libjava/classpath/javax/swing/table/TableColumn.java @@ -0,0 +1,573 @@ +/* TableColumn.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.Serializable; + +import javax.swing.event.SwingPropertyChangeSupport; + +/** + * Represents the attributes of a column in a table, including the column index, + * width, minimum width, preferred width and maximum width. + * + * @author Andrew Selkirk + * @version 1.0 + */ +public class TableColumn + implements Serializable +{ + static final long serialVersionUID = -6113660025878112608L; + + /** + * The name for the columnWidth property. Note that the typo + * in the name value is deliberate, to match the specification. + */ + public static final String COLUMN_WIDTH_PROPERTY = "columWidth"; + + /** + * The name for the headerValue property. + */ + public static final String HEADER_VALUE_PROPERTY = "headerValue"; + + /** + * The name for the headerRenderer property. + */ + public static final String HEADER_RENDERER_PROPERTY = "headerRenderer"; + + /** + * The name for the cellRenderer property. + */ + public static final String CELL_RENDERER_PROPERTY = "cellRenderer"; + + /** + * The index of the corresponding column in the table model. + */ + protected int modelIndex; + + /** + * The identifier for the column. + */ + protected Object identifier; + + /** + * The width. + */ + protected int width; + + /** + * The minimum width. + */ + protected int minWidth = 15; + + /** + * The preferred width. + */ + private int preferredWidth; + + /** + * The maximum width. + */ + protected int maxWidth = Integer.MAX_VALUE; + + /** + * headerRenderer + */ + protected TableCellRenderer headerRenderer; + + /** + * The header value. + */ + protected Object headerValue; + + /** + * cellRenderer + */ + protected TableCellRenderer cellRenderer; + + /** + * cellEditor + */ + protected TableCellEditor cellEditor; + + /** + * isResizable + */ + protected boolean isResizable = true; + + /** + * resizedPostingDisableCount + * + * @deprecated 1.3 + */ + protected transient int resizedPostingDisableCount; + + /** + * changeSupport + */ + private SwingPropertyChangeSupport changeSupport = + new SwingPropertyChangeSupport(this); + + /** + * Creates a new TableColumn that maps to column 0 in the + * related table model. The default width is 75 units. + */ + public TableColumn() + { + this(0, 75, null, null); + } + + /** + * Creates a new TableColumn that maps to the specified column + * in the related table model. The default width is 75 units. + * + * @param modelIndex the index of the column in the model + */ + public TableColumn(int modelIndex) + { + this(modelIndex, 75, null, null); + } + + /** + * Creates a new TableColumn that maps to the specified column + * in the related table model, and has the specified width. + * + * @param modelIndex the index of the column in the model + * @param width the width + */ + public TableColumn(int modelIndex, int width) + { + this(modelIndex, width, null, null); + } + + /** + * Creates a new TableColumn that maps to the specified column + * in the related table model, and has the specified width, + * cellRenderer and cellEditor. + * + * @param modelIndex the index of the column in the model + * @param width the width + * @param cellRenderer the cell renderer (null permitted). + * @param cellEditor the cell editor (null permitted). + */ + public TableColumn(int modelIndex, int width, + TableCellRenderer cellRenderer, TableCellEditor cellEditor) + { + this.modelIndex = modelIndex; + this.width = width; + this.preferredWidth = width; + this.cellRenderer = cellRenderer; + this.cellEditor = cellEditor; + this.headerValue = null; + this.identifier = null; + } + + /** + * firePropertyChange + * + * @param property the name of the property + * @param oldValue the old value + * @param newValue the new value + */ + private void firePropertyChange(String property, Object oldValue, + Object newValue) + { + changeSupport.firePropertyChange(property, oldValue, newValue); + } + + /** + * firePropertyChange + * + * @param property the name of the property + * @param oldValue the old value + * @param newValue the new value + */ + private void firePropertyChange(String property, int oldValue, int newValue) + { + firePropertyChange(property, new Integer(oldValue), new Integer(newValue)); + } + + /** + * firePropertyChange + * + * @param property the name of the property + * @param oldValue the old value + * @param newValue the new value + */ + private void firePropertyChange(String property, boolean oldValue, + boolean newValue) + { + firePropertyChange(property, Boolean.valueOf(oldValue), + Boolean.valueOf(newValue)); + } + + /** + * Sets the index of the column in the related {@link TableModel} that this + * TableColumn maps to. + * + * @param modelIndex the column index in the model. + */ + public void setModelIndex(int modelIndex) + { + this.modelIndex = modelIndex; + } + + /** + * Returns the index of the column in the related {@link TableModel} that + * this TableColumn maps to. + * + * @return the model index + */ + public int getModelIndex() + { + return modelIndex; + } + + /** + * Sets the identifier for the column. + * + * @param identifier the identifier + */ + public void setIdentifier(Object identifier) + { + this.identifier = identifier; + } + + /** + * Returns the identifier for the column, or {@link #getHeaderValue()} if the + * identifier is null. + * + * @return The identifier (or {@link #getHeaderValue()} if the identifier is + * null). + */ + public Object getIdentifier() + { + if (identifier == null) + return getHeaderValue(); + return identifier; + } + + /** + * Sets the header value and sends a {@link PropertyChangeEvent} to all + * registered listeners. The header value property uses the name + * {@link #HEADER_VALUE_PROPERTY}. + * + * @param headerValue the value of the header + */ + public void setHeaderValue(Object headerValue) + { + if (this.headerValue == headerValue) + return; + + Object oldValue = this.headerValue; + this.headerValue = headerValue; + firePropertyChange(HEADER_VALUE_PROPERTY, oldValue, headerValue); + } + + /** + * Returns the header value. + * + * @return the value of the header + */ + public Object getHeaderValue() + { + return headerValue; + } + + /** + * setHeaderRenderer + * + * @param renderer the renderer to use + */ + public void setHeaderRenderer(TableCellRenderer renderer) + { + if (headerRenderer == renderer) + return; + + TableCellRenderer oldRenderer = headerRenderer; + headerRenderer = renderer; + firePropertyChange(HEADER_RENDERER_PROPERTY, + oldRenderer, headerRenderer); + } + + /** + * getHeaderRenderer + * @return TableCellRenderer + */ + public TableCellRenderer getHeaderRenderer() + { + return headerRenderer; + } + + /** + * Sets the renderer for cells in this column and sends a + * {@link PropertyChangeEvent} to all registered listeners. + * + * @param renderer the cell renderer (null permitted). + */ + public void setCellRenderer(TableCellRenderer renderer) + { + if (cellRenderer == renderer) + return; + + TableCellRenderer oldRenderer = cellRenderer; + cellRenderer = renderer; + firePropertyChange(CELL_RENDERER_PROPERTY, + oldRenderer, cellRenderer); + } + + /** + * Returns the renderer for the table cells in this column. + * + * @return The cell renderer. + */ + public TableCellRenderer getCellRenderer() + { + return cellRenderer; + } + + /** + * setCellEditor + * + * @param cellEditor the cell editor + */ + public void setCellEditor(TableCellEditor cellEditor) + { + this.cellEditor = cellEditor; + } + + /** + * getCellEditor + * + * @return the cell editor + */ + public TableCellEditor getCellEditor() + { + return cellEditor; + } + + /** + * setWidth + * + * @param newWidth the width + */ + public void setWidth(int newWidth) + { + int oldWidth = width; + + if (newWidth < minWidth) + width = minWidth; + else if (newWidth > maxWidth) + width = maxWidth; + else + width = newWidth; + + if (width == oldWidth) + return; + + firePropertyChange(COLUMN_WIDTH_PROPERTY, oldWidth, width); + } + + /** + * getWidth + * + * @return int + */ + public int getWidth() + { + return width; + } + + /** + * setPreferredWidth + * + * @param preferredWidth the preferred width + */ + public void setPreferredWidth(int preferredWidth) + { + if (preferredWidth < minWidth) + this.preferredWidth = minWidth; + else if (preferredWidth > maxWidth) + this.preferredWidth = maxWidth; + else + this.preferredWidth = preferredWidth; + } + + /** + * getPreferredWidth + * + * @return the preferred width + */ + public int getPreferredWidth() + { + return preferredWidth; + } + + /** + * Sets the minimum width for the column and, if necessary, updates the + * width and preferredWidth. + * + * @param minWidth the minimum width + */ + public void setMinWidth(int minWidth) + { + this.minWidth = minWidth; + setWidth(getWidth()); + setPreferredWidth(getPreferredWidth()); + } + + /** + * Returns the TableColumn's minimum width. + * + * @return The minimum width. + */ + public int getMinWidth() + { + return minWidth; + } + + /** + * Sets the maximum width and, if necessary, updates the width + * and preferredWidth. + * + * @param maxWidth the maximum width + */ + public void setMaxWidth(int maxWidth) + { + this.maxWidth = maxWidth; + setWidth(getWidth()); + setPreferredWidth(getPreferredWidth()); + } + + /** + * Returns the maximum width. + * + * @return The maximum width. + */ + public int getMaxWidth() + { + return maxWidth; + } + + /** + * setResizable + * + * @param isResizable true if this column is resizable, + * false otherwise + */ + public void setResizable(boolean isResizable) + { + this.isResizable = isResizable; + } + + /** + * getResizable + * + * @return true if this column is resizable, + * false otherwise + */ + public boolean getResizable() + { + return isResizable; + } + + /** + * sizeWidthToFit + */ + public void sizeWidthToFit() + { + // TODO + } + + /** + * This method is empty, unused and deprecated. + * @deprecated 1.3 + */ + public void disableResizedPosting() + { + // Does nothing + } + + /** + * This method is empty, unused and deprecated. + * @deprecated 1.3 + */ + public void enableResizedPosting() + { + // Does nothing + } + + /** + * Adds a property change listener. + * + * @param listener the listener to add + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * removePropertyChangeListener + * @param listener the listener to remove + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns the property change listeners for this TableColumn. + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return changeSupport.getPropertyChangeListeners(); + } + + /** + * createDefaultHeaderRenderer + * @return TableCellRenderer + */ + protected TableCellRenderer createDefaultHeaderRenderer() + { + return new DefaultTableCellRenderer(); + } +} diff --git a/libjava/classpath/javax/swing/table/TableColumnModel.java b/libjava/classpath/javax/swing/table/TableColumnModel.java new file mode 100644 index 0000000..76a1456 --- /dev/null +++ b/libjava/classpath/javax/swing/table/TableColumnModel.java @@ -0,0 +1,187 @@ +/* TableColumnModel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.table; + +import java.util.Enumeration; + +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.event.TableColumnModelListener; + +/** + * The interface used by {@link JTable} to access the columns in the table + * view. + * + * @author Andrew Selkirk + */ +public interface TableColumnModel +{ + /** + * Adds a column to the model. + * + * @param column the new column (null not permitted). + * + * @throws IllegalArgumentException if column is + * null. + */ + void addColumn(TableColumn column); + + /** + * Removes a column from the model. If column is not defined + * in the model, this method does nothing. + * + * @param column TableColumn + */ + void removeColumn(TableColumn column); + + /** + * Moves a column. + * + * @param columnIndex Index of column to move + * @param newIndex New index of column + */ + void moveColumn(int columnIndex, int newIndex); + + /** + * setColumnMargin + * @param margin Margin of column + */ + void setColumnMargin(int margin); + + /** + * Returns the number of columns in the model. + * + * @return The column count + */ + int getColumnCount(); + + /** + * getColumns + * @return Enumeration of columns + */ + Enumeration getColumns(); + + /** + * Returns the index of the {@link TableColumn} with the given identifier. + * + * @param identifier the identifier (null not permitted). + * + * @return The index of the {@link TableColumn} with the given identifier. + * + * @throws IllegalArgumentException if identifier is + * null or there is no column with that identifier. + */ + int getColumnIndex(Object columnIdentifier); + + /** + * Returns the TableColumn at the specified index. + * + * @param columnIndex the column index. + * + * @return The table column. + */ + TableColumn getColumn(int columnIndex); + + /** + * Returns the column margin. + * + * @return The column margin. + */ + int getColumnMargin(); + + /** + * getColumnIndexAtX + * @return Column index as position x + */ + int getColumnIndexAtX(int xPosition); + + /** + * getTotalColumnWidth + * @return Total column width + */ + int getTotalColumnWidth(); + + /** + * setColumnSelectionAllowed + * @param value Set column selection + */ + void setColumnSelectionAllowed(boolean value); + + /** + * getColumnSelectionAllowed + * @return true if column selection allowed, false otherwise + */ + boolean getColumnSelectionAllowed(); + + /** + * getSelectedColumns + * @return Selected columns + */ + int[] getSelectedColumns(); + + /** + * getSelectedColumnCount + * @return Count of selected columns + */ + int getSelectedColumnCount(); + + /** + * setSelectionModel + * @param model ListSelectionModel + */ + void setSelectionModel(ListSelectionModel model); + + /** + * getSelectionModel + * @param column TableColumn + */ + ListSelectionModel getSelectionModel(); + + /** + * addColumnModelListener + * @param listener TableColumnModelListener + */ + void addColumnModelListener(TableColumnModelListener listener); + + /** + * removeColumnModelListener + * @param listener TableColumnModelListener + */ + void removeColumnModelListener(TableColumnModelListener listener); +} diff --git a/libjava/classpath/javax/swing/table/TableModel.java b/libjava/classpath/javax/swing/table/TableModel.java new file mode 100644 index 0000000..016ae17 --- /dev/null +++ b/libjava/classpath/javax/swing/table/TableModel.java @@ -0,0 +1,134 @@ +/* TableModel.java -- + Copyright (C) 2002, 2005, Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.table; + +import javax.swing.event.TableModelListener; + +/** + * A TableModel is a two dimensional data structure that + * can store arbitrary Object instances, usually for the + * purpose of display in a {@link javax.swing.JTable} component. Individual + * objects can be accessed by specifying the row index and column index for + * the object. Each column in the model has a name associated with it. + *

+ * The {@link DefaultTableModel} class provides one implementation of + * this interface. + * + * @author Andrew Selkirk + */ +public interface TableModel +{ + /** + * Returns the number of rows in the model. + * + * @return The row count. + */ + int getRowCount(); + + /** + * Returns the number of columns in the model. + * + * @return The column count + */ + int getColumnCount(); + + /** + * Returns the name of a column in the model. + * + * @param columnIndex the column index. + * + * @return The column name. + */ + String getColumnName(int columnIndex); + + /** + * Returns the Class for all Object instances + * in the specified column. + * + * @param columnIndex the column index. + * + * @return The class. + */ + Class getColumnClass(int columnIndex); + + /** + * Returns true if the cell is editable, and false + * otherwise. + * + * @param rowIndex the row index. + * @param columnIndex the column index. + * + * @return true if editable, false otherwise. + */ + boolean isCellEditable(int rowIndex, int columnIndex); + + /** + * Returns the value (Object) at a particular cell in the + * table. + * + * @param rowIndex the row index. + * @param columnIndex the column index. + * + * @return The value at the specified cell. + */ + Object getValueAt(int rowIndex, int columnIndex); + + /** + * Sets the value at a particular cell in the table. + * + * @param aValue the value (null permitted). + * @param rowIndex the row index. + * @param columnIndex the column index. + */ + void setValueAt(Object aValue, int rowIndex, int columnIndex); + + /** + * Adds a listener to the model. The listener will receive notification + * of updates to the model. + * + * @param listener the listener. + */ + void addTableModelListener(TableModelListener listener); + + /** + * Removes a listener from the model. + * + * @param listener the listener. + */ + void removeTableModelListener(TableModelListener listener); +} diff --git a/libjava/classpath/javax/swing/table/package.html b/libjava/classpath/javax/swing/table/package.html new file mode 100644 index 0000000..84e6f1a --- /dev/null +++ b/libjava/classpath/javax/swing/table/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.table + + +

Interfaces and classes that support the {@link javax.swing.JTable} +component.

+ + + diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java new file mode 100644 index 0000000..c3a3d70 --- /dev/null +++ b/libjava/classpath/javax/swing/text/AbstractDocument.java @@ -0,0 +1,912 @@ +/* AbstractDocument.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.io.PrintStream; +import java.io.Serializable; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.EventListenerList; +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.tree.TreeNode; +import javax.swing.undo.AbstractUndoableEdit; +import javax.swing.undo.CompoundEdit; +import javax.swing.undo.UndoableEdit; + +public abstract class AbstractDocument + implements Document, Serializable +{ + private static final long serialVersionUID = -116069779446114664L; + + protected static final String BAD_LOCATION = "document location failure"; + + public static final String BidiElementName = "bidi level"; + public static final String ContentElementName = "content"; + public static final String ParagraphElementName = "paragraph"; + public static final String SectionElementName = "section"; + public static final String ElementNameAttribute = "$ename"; + + Content content; + AttributeContext context; + DocumentFilter documentFilter; + + /** The documents properties. */ + Dictionary properties; + + protected EventListenerList listenerList = new EventListenerList(); + + protected AbstractDocument(Content doc) + { + this(doc, StyleContext.getDefaultStyleContext()); + } + + protected AbstractDocument(Content doc, AttributeContext ctx) + { + content = doc; + context = ctx; + } + + // These still need to be implemented by a derived class: + public abstract Element getParagraphElement(int pos); + + public abstract Element getDefaultRootElement(); + + protected Element createBranchElement(Element parent, + AttributeSet attributes) + { + return new BranchElement(parent, attributes); + } + + protected Element createLeafElement(Element parent, AttributeSet attributes, + int start, int end) + { + return new LeafElement(parent, attributes, start, end); + } + + public Position createPosition(final int offset) throws BadLocationException + { + if (offset < 0 || offset > getLength()) + throw new BadLocationException(getText(0, getLength()), offset); + + return new Position() + { + public int getOffset() + { + return offset; + } + }; + } + + protected void fireChangedUpdate(DocumentEvent event) + { + DocumentListener[] listeners = getDocumentListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].changedUpdate(event); + } + + protected void fireInsertUpdate(DocumentEvent event) + { + DocumentListener[] listeners = getDocumentListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].insertUpdate(event); + } + + protected void fireRemoveUpdate(DocumentEvent event) + { + DocumentListener[] listeners = getDocumentListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].removeUpdate(event); + } + + protected void fireUndoableEditUpdate(UndoableEditEvent event) + { + UndoableEditListener[] listeners = getUndoableEditListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].undoableEditHappened(event); + } + + public int getAsynchronousLoadPriority() + { + return 0; + } + + protected AttributeContext getAttributeContext() + { + return context; + } + + public Element getBidiRootElement() + { + return null; + } + + protected Content getContent() + { + return content; + } + + protected Thread getCurrentWriter() + { + return null; + } + + public Dictionary getDocumentProperties() + { + // FIXME: make me thread-safe + if (properties == null) + properties = new Hashtable(); + + return properties; + } + + public Position getEndPosition() + { + return new Position() + { + public int getOffset() + { + return getLength(); + } + }; + } + + public int getLength() + { + return content.length() - 1; + } + + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + public Object getProperty(Object key) + { + // FIXME: make me thread-safe + Object value = null; + if (properties != null) + value = properties.get(key); + + return value; + } + + public Element[] getRootElements() + { + Element[] elements = new Element[1]; + elements[0] = getDefaultRootElement(); + return elements; + } + + public Position getStartPosition() + { + return new Position() + { + public int getOffset() + { + return 0; + } + }; + } + + public String getText(int offset, int length) throws BadLocationException + { + return content.getString(offset, length); + } + + public void getText(int offset, int length, Segment segment) + throws BadLocationException + { + content.getChars(offset, length, segment); + } + + public void insertString(int offset, String text, AttributeSet attributes) + throws BadLocationException + { + // 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); + insertUpdate(event, attributes); + fireInsertUpdate(event); + } + + protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) + { + } + + protected void postRemoveUpdate(DefaultDocumentEvent chng) + { + } + + public void putProperty(Object key, Object value) + { + // FIXME: make me thread-safe + if (properties == null) + properties = new Hashtable(); + + properties.put(key, value); + } + + public void readLock() + { + } + + public void readUnlock() + { + } + + public void remove(int offset, int length) throws BadLocationException + { + DefaultDocumentEvent event = + new DefaultDocumentEvent(offset, length, + DocumentEvent.EventType.REMOVE); + removeUpdate(event); + content.remove(offset, length); + postRemoveUpdate(event); + fireRemoveUpdate(event); + } + + /** + * Replaces some text in the document. + * + * @since 1.4 + */ + public void replace(int offset, int length, String text, + AttributeSet attributes) + throws BadLocationException + { + remove(offset, length); + insertString(offset, text, attributes); + } + + /** + * Adds a DocumentListener object to this document. + * + * @param listener the listener to add + */ + public void addDocumentListener(DocumentListener listener) + { + listenerList.add(DocumentListener.class, listener); + } + + /** + * Removes a DocumentListener object from this document. + * + * @param listener the listener to remove + */ + public void removeDocumentListener(DocumentListener listener) + { + listenerList.remove(DocumentListener.class, listener); + } + + /** + * Returns add added DocumentListener objects. + * + * @return an array of listeners + */ + public DocumentListener[] getDocumentListeners() + { + return (DocumentListener[]) getListeners(DocumentListener.class); + } + + /** + * Adds a UndoableEditListener object to this document. + * + * @param listener the listener to add + */ + public void addUndoableEditListener(UndoableEditListener listener) + { + listenerList.add(UndoableEditListener.class, listener); + } + + /** + * Removes a UndoableEditListener object from this document. + * + * @param listener the listener to remove + */ + public void removeUndoableEditListener(UndoableEditListener listener) + { + listenerList.remove(UndoableEditListener.class, listener); + } + + /** + * Returns add added UndoableEditListener objects. + * + * @return an array of listeners + */ + public UndoableEditListener[] getUndoableEditListeners() + { + return (UndoableEditListener[]) getListeners(UndoableEditListener.class); + } + + protected void removeUpdate(DefaultDocumentEvent chng) + { + } + + public void render(Runnable r) + { + } + + public void setAsynchronousLoadPriority(int p) + { + } + + public void setDocumentProperties(Dictionary x) + { + // FIXME: make me thread-safe + properties = x; + } + + protected void writeLock() + { + } + + protected void writeUnlock() + { + } + + /** + * @since 1.4 + */ + public DocumentFilter getDocumentFilter() + { + return documentFilter; + } + + /** + * @since 1.4 + */ + public void setDocumentFilter(DocumentFilter filter) + { + this.documentFilter = filter; + } + + public void dump(PrintStream out) + { + ((AbstractElement) getDefaultRootElement()).dump(out, 0); + } + + public interface AttributeContext + { + AttributeSet addAttribute(AttributeSet old, Object name, Object value); + + AttributeSet addAttributes(AttributeSet old, AttributeSet attributes); + + AttributeSet getEmptySet(); + + void reclaim(AttributeSet attributes); + + AttributeSet removeAttribute(AttributeSet old, Object name); + + AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes); + + AttributeSet removeAttributes(AttributeSet old, Enumeration names); + } + + public interface Content + { + Position createPosition(int offset) throws BadLocationException; + + int length(); + + UndoableEdit insertString(int where, String str) + throws BadLocationException; + + UndoableEdit remove(int where, int nitems) throws BadLocationException; + + String getString(int where, int len) throws BadLocationException; + + void getChars(int where, int len, Segment txt) throws BadLocationException; + } + + public abstract class AbstractElement + implements Element, MutableAttributeSet, TreeNode, Serializable + { + private static final long serialVersionUID = 1265312733007397733L; + int count; + int offset; + + AttributeSet attributes; + + Element element_parent; + + TreeNode tree_parent; + Vector tree_children; + + public AbstractElement(Element p, AttributeSet s) + { + element_parent = p; + attributes = s; + } + + // TreeNode implementation + + public abstract Enumeration children(); + + public abstract boolean getAllowsChildren(); + + public TreeNode getChildAt(int index) + { + return (TreeNode) tree_children.get(index); + } + + public int getChildCount() + { + return tree_children.size(); + } + + public int getIndex(TreeNode node) + { + return tree_children.indexOf(node); + } + + public TreeNode getParent() + { + return tree_parent; + } + + public abstract boolean isLeaf(); + + + // MutableAttributeSet support + + public void addAttribute(Object name, Object value) + { + attributes = getAttributeContext().addAttribute(attributes, name, value); + } + + public void addAttributes(AttributeSet attrs) + { + attributes = getAttributeContext().addAttributes(attributes, attrs); + } + + public void removeAttribute(Object name) + { + attributes = getAttributeContext().removeAttribute(attributes, name); + } + + public void removeAttributes(AttributeSet attrs) + { + attributes = getAttributeContext().removeAttributes(attributes, attrs); + } + + public void removeAttributes(Enumeration names) + { + attributes = getAttributeContext().removeAttributes(attributes, names); + } + + public void setResolveParent(AttributeSet parent) + { + attributes = getAttributeContext().addAttribute(attributes, ResolveAttribute, parent); + } + + + // AttributeSet interface support + + public boolean containsAttribute(Object name, Object value) + { + return attributes.containsAttribute(name, value); + } + + public boolean containsAttributes(AttributeSet attrs) + { + return attributes.containsAttributes(attrs); + } + + public AttributeSet copyAttributes() + { + return attributes.copyAttributes(); + } + + public Object getAttribute(Object key) + { + return attributes.getAttribute(key); + } + + public int getAttributeCount() + { + return attributes.getAttributeCount(); + } + + public Enumeration getAttributeNames() + { + return attributes.getAttributeNames(); + } + + public AttributeSet getResolveParent() + { + return attributes.getResolveParent(); + } + + public boolean isDefined(Object attrName) + { + return attributes.isDefined(attrName); + } + + public boolean isEqual(AttributeSet attrs) + { + return attributes.isEqual(attrs); + } + + // Element interface support + + public AttributeSet getAttributes() + { + return attributes; + } + + public Document getDocument() + { + return AbstractDocument.this; + } + + public abstract Element getElement(int index); + + public String getName() + { + return (String) getAttribute(NameAttribute); + } + + public Element getParentElement() + { + return element_parent; + } + + public abstract int getEndOffset(); + + public abstract int getElementCount(); + + public abstract int getElementIndex(int offset); + + public abstract int getStartOffset(); + + private void dumpElement(PrintStream stream, String indent, Element element) + { + 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) + { + } + System.out.println(indent + " [" + + start + "," + + end + "][" + + text + "]"); + } + else + { + for (int i = 0; i < element.getElementCount(); ++i) + dumpElement(stream, indent + " ", element.getElement(i)); + } + } + + public void dump(PrintStream stream, int indent) + { + String indentStr = ""; + for (int i = 0; i < indent; ++i) + indentStr += " "; + dumpElement(stream, indentStr, this); + } + } + + public class BranchElement extends AbstractElement + { + private static final long serialVersionUID = -8595176318868717313L; + + private Element[] children = new Element[0]; + + public BranchElement(Element parent, AttributeSet attributes) + { + super(parent, attributes); + } + + public Enumeration children() + { + if (children.length == 0) + return null; + + Vector tmp = new Vector(); + + for (int index = 0; index < children.length; ++index) + tmp.add(children[index]); + + return tmp.elements(); + } + + public boolean getAllowsChildren() + { + return true; + } + + public Element getElement(int index) + { + if (index < 0 || index >= children.length) + return null; + + return children[index]; + } + + public int getElementCount() + { + return children.length; + } + + public int getElementIndex(int offset) + { + // XXX: There is surely a better algorithm + // as beginning from first element each time. + for (int index = 0; index < children.length; ++index) + { + Element elem = children[index]; + + if ((elem.getStartOffset() <= offset) + && (offset < elem.getEndOffset())) + return index; + } + + return 0; + } + + public int getEndOffset() + { + return children[children.length - 1].getEndOffset(); + } + + public String getName() + { + return ParagraphElementName; + } + + public int getStartOffset() + { + return children[0].getStartOffset(); + } + + public boolean isLeaf() + { + return false; + } + + public Element positionToElement(int position) + { + // XXX: There is surely a better algorithm + // as beginning from first element each time. + for (int index = 0; index < children.length; ++index) + { + Element elem = children[index]; + + if ((elem.getStartOffset() <= position) + && (position < elem.getEndOffset())) + return elem; + } + + return null; + } + + public void replace(int offset, int length, Element[] elements) + { + Element[] target = new Element[children.length - length + + elements.length]; + System.arraycopy(children, 0, target, 0, offset); + System.arraycopy(elements, 0, target, offset, elements.length); + System.arraycopy(children, offset + length, target, + offset + elements.length, + children.length - offset - length); + children = target; + } + + public String toString() + { + return ("BranchElement(" + getName() + ") " + + getStartOffset() + "," + getEndOffset() + "\n"); + } + } + + public class DefaultDocumentEvent extends CompoundEdit + implements DocumentEvent + { + private static final long serialVersionUID = -7406103236022413522L; + + private int offset; + private int length; + private DocumentEvent.EventType type; + + public DefaultDocumentEvent(int offset, int length, + DocumentEvent.EventType type) + { + this.offset = offset; + this.length = length; + this.type = type; + } + + public Document getDocument() + { + return AbstractDocument.this; + } + + public int getLength() + { + return length; + } + + public int getOffset() + { + return offset; + } + + public DocumentEvent.EventType getType() + { + return type; + } + + public DocumentEvent.ElementChange getChange(Element elem) + { + return null; + } + } + + public static class ElementEdit extends AbstractUndoableEdit + implements DocumentEvent.ElementChange + { + private static final long serialVersionUID = -1216620962142928304L; + + private Element elem; + private int index; + private Element[] removed; + private Element[] added; + + public ElementEdit(Element elem, int index, + Element[] removed, Element[] added) + { + this.elem = elem; + this.index = index; + this.removed = removed; + this.added = added; + } + + public Element[] getChildrenAdded() + { + return added; + } + + public Element[] getChildrenRemoved() + { + return removed; + } + + public Element getElement() + { + return elem; + } + + public int getIndex() + { + return index; + } + } + + public class LeafElement extends AbstractElement + { + private static final long serialVersionUID = 5115368706941283802L; + int start; + int end; + + public LeafElement(Element parent, AttributeSet attributes, int start, + int end) + { + super(parent, attributes); + this.start = start; + this.end = end; + } + + public Enumeration children() + { + return null; + } + + public boolean getAllowsChildren() + { + return false; + } + + public Element getElement(int index) + { + return null; + } + + public int getElementCount() + { + return 0; + } + + public int getElementIndex(int offset) + { + return -1; + } + + public int getEndOffset() + { + return end; + } + + public String getName() + { + return ContentElementName; + } + + public int getStartOffset() + { + return start; + } + + public boolean isLeaf() + { + return true; + } + + public String toString() + { + return ("LeafElement(" + getName() + ") " + + getStartOffset() + "," + getEndOffset() + "\n"); + } + } +} diff --git a/libjava/classpath/javax/swing/text/AttributeSet.java b/libjava/classpath/javax/swing/text/AttributeSet.java new file mode 100644 index 0000000..87e7b98 --- /dev/null +++ b/libjava/classpath/javax/swing/text/AttributeSet.java @@ -0,0 +1,72 @@ +/* AttributeSet.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.util.Enumeration; + +public interface AttributeSet +{ + static interface CharacterAttribute + { + } + + static interface ColorAttribute + { + } + + static interface FontAttribute + { + } + + static interface ParagraphAttribute + { + } + + Object NameAttribute = StyleConstants.NameAttribute; + Object ResolveAttribute = StyleConstants.ResolveAttribute; + + boolean containsAttribute(Object name, Object value); + boolean containsAttributes(AttributeSet attributes); + AttributeSet copyAttributes(); + Object getAttribute(Object key); + int getAttributeCount(); + Enumeration getAttributeNames(); + AttributeSet getResolveParent(); + boolean isDefined(Object attrName); + boolean isEqual(AttributeSet attr); +} diff --git a/libjava/classpath/javax/swing/text/BadLocationException.java b/libjava/classpath/javax/swing/text/BadLocationException.java new file mode 100644 index 0000000..e1a2ebc --- /dev/null +++ b/libjava/classpath/javax/swing/text/BadLocationException.java @@ -0,0 +1,65 @@ +/* BadLocationException.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +public class BadLocationException extends Exception +{ + private static final long serialVersionUID = -7712259886815656766L; + + int offset; + + /** + * Constructs a BadLocationException + * + * @param str A string indicating what was wrong with the arguments + * @param offset Offset within the document that was requested >= 0 + */ + public BadLocationException(String str, int offset) + { + super(str); + this.offset = offset; + } + + /** + * Returns the offset into the document that was not legal + */ + public int offsetRequested() + { + return offset; + } +} diff --git a/libjava/classpath/javax/swing/text/Caret.java b/libjava/classpath/javax/swing/text/Caret.java new file mode 100644 index 0000000..46072ef --- /dev/null +++ b/libjava/classpath/javax/swing/text/Caret.java @@ -0,0 +1,81 @@ +/* Caret.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Graphics; +import java.awt.Point; + +import javax.swing.event.ChangeListener; + +public interface Caret +{ + void addChangeListener(ChangeListener l); + + void deinstall(JTextComponent c); + + int getBlinkRate(); + + int getDot(); + + Point getMagicCaretPosition(); + + int getMark(); + + void install(JTextComponent c); + + boolean isSelectionVisible(); + + boolean isVisible(); + + void moveDot(int dot); + + void paint(Graphics g); + + void removeChangeListener(ChangeListener l); + + void setBlinkRate(int rate); + + void setDot(int dot); + + void setMagicCaretPosition(Point p); + + void setSelectionVisible(boolean v); + + void setVisible(boolean v); +} diff --git a/libjava/classpath/javax/swing/text/ChangedCharSetException.java b/libjava/classpath/javax/swing/text/ChangedCharSetException.java new file mode 100644 index 0000000..7fba29a --- /dev/null +++ b/libjava/classpath/javax/swing/text/ChangedCharSetException.java @@ -0,0 +1,100 @@ +/* ChangedCharSetException.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.io.IOException; +import java.io.Serializable; + +/** + * The exception is thrown when the document charset is changed. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class ChangedCharSetException + extends IOException + implements Serializable +{ + /** + * Use serialVersionUID for interoperability. + * This value corresponds the version 1.4. + */ + private static final long serialVersionUID = 9119851554465432389L; + + /** + * The char set specification. + */ + private final String m_charSetSpec; + + /** + * The char set key. + */ + private final boolean m_charSetKey; + + /** + * Constructs a new char set exception with two additional parameters, + * defining the circumstances under that the exception was raised. + */ + public ChangedCharSetException(String charSetSpec, boolean charSetKey) + { + m_charSetSpec = charSetSpec; + m_charSetKey = charSetKey; + } + + /** + * Get the value of the first parameter, previously passed to the + * constructor. + * + * @return the value of the first parameter + */ + public String getCharSetSpec() + { + return m_charSetSpec; + } + + /** + * Get the value of the second parameter, previously passed to the + * constructor. + * + * @return the value of the second parameter + */ + public boolean keyEqualsCharSet() + { + return m_charSetKey; + } +} diff --git a/libjava/classpath/javax/swing/text/ComponentView.java b/libjava/classpath/javax/swing/text/ComponentView.java new file mode 100644 index 0000000..744d537 --- /dev/null +++ b/libjava/classpath/javax/swing/text/ComponentView.java @@ -0,0 +1,103 @@ +/* ComponentView.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Shape; + +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) + { + } + + public void setParent(View p) + { + } + + public void setSize(float width, float height) + { + } + + public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) + { + return 0; + } +} diff --git a/libjava/classpath/javax/swing/text/DateFormatter.java b/libjava/classpath/javax/swing/text/DateFormatter.java new file mode 100644 index 0000000..0e20b77 --- /dev/null +++ b/libjava/classpath/javax/swing/text/DateFormatter.java @@ -0,0 +1,85 @@ +/* DateFormatter.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.text.DateFormat; + +/** + * DateFormatter is an {@link InternationalFormatter} + * that implements value to string and string to value conversion via + * an instance of {@link DateFormat}. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class DateFormatter extends InternationalFormatter +{ + + /** The serialVersoinUID. */ + private static final long serialVersionUID = 5423279572591848797L; + + /** + * Creates a new instance using the default {@link DateFormat} object + * returned by {@link DateFormat#getDateInstance}. + */ + public DateFormatter() + { + this(DateFormat.getDateInstance()); + } + + /** + * Creates a new instance of DateFormatter using the + * specified DateFormat + * + * @param format the DateFormat to use + */ + public DateFormatter(DateFormat format) + { + super(); + setFormat(format); + } + + /** + * Sets the format that is used by this DateFormatter. + * + * @param format the DateFormat to use + */ + public void setFormat(DateFormat format) + { + super.setFormat(format); + } +} diff --git a/libjava/classpath/javax/swing/text/DefaultCaret.java b/libjava/classpath/javax/swing/text/DefaultCaret.java new file mode 100644 index 0000000..b57b365 --- /dev/null +++ b/libjava/classpath/javax/swing/text/DefaultCaret.java @@ -0,0 +1,315 @@ +/* DefaultCaret.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +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.util.EventListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + + +public class DefaultCaret extends Rectangle + implements Caret, FocusListener, MouseListener, MouseMotionListener +{ + private static final long serialVersionUID = 228155774675466193L; + + protected ChangeEvent changeEvent = new ChangeEvent(this); + protected EventListenerList listenerList = new EventListenerList(); + + private JTextComponent textComponent; + + private boolean selectionVisible = true; + private int blinkRate = 500; + private int dot = 0; + private int mark = 0; + private Point magicCaretPosition = null; + private boolean visible = true; + private Object highlightEntry; + + public void mouseDragged(MouseEvent event) + { + } + + public void mouseMoved(MouseEvent event) + { + } + + public void mouseClicked(MouseEvent event) + { + } + + public void mouseEntered(MouseEvent event) + { + } + + public void mouseExited(MouseEvent event) + { + } + + public void mousePressed(MouseEvent event) + { + } + + public void mouseReleased(MouseEvent event) + { + } + + public void focusGained(FocusEvent event) + { + } + + public void focusLost(FocusEvent event) + { + } + + protected void moveCaret(MouseEvent event) + { + } + + protected void positionCaret(MouseEvent event) + { + } + + public void deinstall(JTextComponent c) + { + textComponent.removeFocusListener(this); + textComponent.removeMouseListener(this); + textComponent.removeMouseMotionListener(this); + textComponent = null; + } + + public void install(JTextComponent c) + { + textComponent = c; + textComponent.addFocusListener(this); + textComponent.addMouseListener(this); + textComponent.addMouseMotionListener(this); + repaint(); + } + + public void setMagicCaretPosition(Point p) + { + magicCaretPosition = p; + } + + public Point getMagicCaretPosition() + { + return magicCaretPosition; + } + + public int getMark() + { + return mark; + } + + private void handleHighlight() + { + Highlighter highlighter = textComponent.getHighlighter(); + + if (highlighter == null) + return; + + int p0 = Math.min(dot, mark); + int p1 = Math.max(dot, mark); + + if (selectionVisible && p0 != p1) + { + try + { + if (highlightEntry == null) + highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter()); + else + highlighter.changeHighlight(highlightEntry, p0, p1); + } + catch (BadLocationException e) + { + // This should never happen. + throw new InternalError(); + } + } + else + { + if (highlightEntry != null) + { + highlighter.removeHighlight(highlightEntry); + highlightEntry = null; + } + } + } + + public void setSelectionVisible(boolean v) + { + if (selectionVisible == v) + return; + + selectionVisible = v; + handleHighlight(); + repaint(); + } + + public boolean isSelectionVisible() + { + return selectionVisible; + } + + protected final void repaint() + { + if (textComponent != null) + textComponent.repaint(); + } + + public void paint(Graphics g) + { + if (textComponent == null) + return; + + int dot = getDot(); + Rectangle rect = null; + + try + { + rect = textComponent.modelToView(dot); + } + catch (BadLocationException e) + { + // This should never happen as dot should be always valid. + return; + } + + if (rect == null) + return; + + // First we need to delete the old caret. + // FIXME: Implement deleting of old caret. + + // 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); + } + } + + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) getListeners(ChangeListener.class); + } + + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].stateChanged(changeEvent); + } + + protected final JTextComponent getComponent() + { + return textComponent; + } + + public int getBlinkRate() + { + return blinkRate; + } + + public void setBlinkRate(int rate) + { + blinkRate = rate; + } + + public int getDot() + { + return dot; + } + + public void moveDot(int dot) + { + this.dot = dot; + handleHighlight(); + repaint(); + } + + public void setDot(int dot) + { + this.dot = dot; + this.mark = dot; + handleHighlight(); + repaint(); + } + + public boolean isVisible() + { + return visible; + } + + public void setVisible(boolean v) + { + visible = v; + repaint(); + } + + protected Highlighter.HighlightPainter getSelectionPainter() + { + return DefaultHighlighter.DefaultPainter; + } +} diff --git a/libjava/classpath/javax/swing/text/DefaultEditorKit.java b/libjava/classpath/javax/swing/text/DefaultEditorKit.java new file mode 100644 index 0000000..aa2fbe85 --- /dev/null +++ b/libjava/classpath/javax/swing/text/DefaultEditorKit.java @@ -0,0 +1,418 @@ +/* DefaultEditorKit.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; + +import javax.swing.Action; + +public class DefaultEditorKit extends EditorKit +{ + public static class BeepAction + extends TextAction + { + public BeepAction() + { + super(beepAction); + } + + public void actionPerformed(ActionEvent event) + { + Toolkit.getDefaultToolkit().beep(); + } + } + + public static class CopyAction + extends TextAction + { + public CopyAction() + { + super(copyAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class CutAction + extends TextAction + { + public CutAction() + { + super(cutAction); + } + + public void actionPerformed(ActionEvent event) + { + } + } + + /** + * This action is executed as default action when a KEY_TYPED + * event is received and no keymap entry exists for that. The purpose + * of this action is to filter out a couple of characters. This includes + * the control characters and characters with the ALT-modifier. + * + * If an event does not get filtered, it is inserted into the document + * of the text component. If there is some text selected in the text component, + * this text will be replaced. + */ + public static class DefaultKeyTypedAction + extends TextAction + { + public DefaultKeyTypedAction() + { + super(defaultKeyTypedAction); + } + + public void actionPerformed(ActionEvent event) + { + // first we filter the following events: + // - control characters + // - key events with the ALT modifier (FIXME: filter that too!) + char c = event.getActionCommand().charAt(0); + if (Character.isISOControl(c)) + return; + + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + 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) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + } + + /** + * This action inserts a newline character into the document + * of the text component. This is typically triggered by hitting + * ENTER on the keyboard. + */ + public static class InsertBreakAction + extends TextAction + { + public InsertBreakAction() + { + super(insertBreakAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + t.replaceSelection("\n"); + } + } + + public static class InsertContentAction + extends TextAction + { + public InsertContentAction() + { + super(insertContentAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class InsertTabAction + extends TextAction + { + public InsertTabAction() + { + super(insertTabAction); + } + + public void actionPerformed(ActionEvent event) + { + } + } + + public static class PasteAction + extends TextAction + { + public PasteAction() + { + super(pasteAction); + } + + public void actionPerformed(ActionEvent event) + { + } + } + + private static final long serialVersionUID = 9017245433028523428L; + + public static final String backwardAction = "caret-backward"; + public static final String beepAction = "beep"; + public static final String beginAction = "caret-begin"; + public static final String beginLineAction = "caret-begin-line"; + public static final String beginParagraphAction = "caret-begin-paragraph"; + public static final String beginWordAction = "caret-begin-word"; + public static final String copyAction = "copy-to-clipboard"; + public static final String cutAction = "cut-to-clipboard"; + public static final String defaultKeyTypedAction = "default-typed"; + public static final String deleteNextCharAction = "delete-next"; + public static final String deletePrevCharAction = "delete-previous"; + public static final String downAction = "caret-down"; + public static final String endAction = "caret-end"; + public static final String endLineAction = "caret-end-line"; + public static final String EndOfLineStringProperty = "__EndOfLine__"; + public static final String endParagraphAction = "caret-end-paragraph"; + public static final String endWordAction = "caret-end-word"; + public static final String forwardAction = "caret-forward"; + public static final String insertBreakAction = "insert-break"; + public static final String insertContentAction = "insert-content"; + public static final String insertTabAction = "insert-tab"; + public static final String nextWordAction = "caret-next-word"; + public static final String pageDownAction = "page-down"; + public static final String pageUpAction = "page-up"; + public static final String pasteAction = "paste-from-clipboard"; + public static final String previousWordAction = "caret-previous-word"; + public static final String readOnlyAction = "set-read-only"; + public static final String selectAllAction = "select-all"; + public static final String selectionBackwardAction = "selection-backward"; + public static final String selectionBeginAction = "selection-begin"; + public static final String selectionBeginLineAction = "selection-begin-line"; + public static final String selectionBeginParagraphAction = + "selection-begin-paragraph"; + public static final String selectionBeginWordAction = "selection-begin-word"; + public static final String selectionDownAction = "selection-down"; + public static final String selectionEndAction = "selection-end"; + public static final String selectionEndLineAction = "selection-end-line"; + public static final String selectionEndParagraphAction = + "selection-end-paragraph"; + public static final String selectionEndWordAction = "selection-end-word"; + public static final String selectionForwardAction = "selection-forward"; + public static final String selectionNextWordAction = "selection-next-word"; + public static final String selectionPreviousWordAction = + "selection-previous-word"; + public static final String selectionUpAction = "selection-up"; + public static final String selectLineAction = "select-line"; + public static final String selectParagraphAction = "select-paragraph"; + public static final String selectWordAction = "select-word"; + public static final String upAction = "caret-up"; + public static final String writableAction = "set-writable"; + + public DefaultEditorKit() + { + } + + private static Action[] defaultActions = + new Action[] { + new BeepAction(), + new CopyAction(), + new CutAction(), + new DefaultKeyTypedAction(), + new InsertBreakAction(), + new InsertContentAction(), + new InsertTabAction(), + new PasteAction(), + new TextAction(deleteNextCharAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getCaret().getDot(); + if (pos < t.getDocument().getEndPosition().getOffset()) + { + t.getDocument().remove(t.getCaret().getDot(), 1); + } + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + }, + new TextAction(deletePrevCharAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getCaret().getDot(); + if (pos > t.getDocument().getStartPosition().getOffset()) + { + t.getDocument().remove(pos - 1, 1); + t.getCaret().setDot(pos - 1); + } + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + }, + new TextAction(backwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().setDot(Math.max(t.getCaret().getDot() - 1, + t.getDocument().getStartPosition().getOffset())); + } + } + }, + new TextAction(forwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1, + t.getDocument().getEndPosition().getOffset())); + } + } + }, + new TextAction(selectionBackwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().moveDot(Math.max(t.getCaret().getDot() - 1, + t.getDocument().getStartPosition().getOffset())); + } + } + }, + new TextAction(selectionForwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().moveDot(Math.min(t.getCaret().getDot() + 1, + t.getDocument().getEndPosition().getOffset())); + } + } + }, + }; + + public Caret createCaret() + { + return new DefaultCaret(); + } + + public Document createDefaultDocument() + { + return new PlainDocument(); + } + + public Action[] getActions() + { + return defaultActions; + } + + public String getContentType() + { + return "text/plain"; + } + + public ViewFactory getViewFactory() + { + return null; + } + + public void read(InputStream in, Document document, int offset) + throws BadLocationException, IOException + { + read(new InputStreamReader(in), document, offset); + } + + public void read(Reader in, Document document, int offset) + throws BadLocationException, IOException + { + BufferedReader reader = new BufferedReader(in); + + String line; + StringBuffer content = new StringBuffer(); + + while ((line = reader.readLine()) != null) + { + content.append(line); + content.append("\n"); + } + + document.insertString(offset, content.toString(), + SimpleAttributeSet.EMPTY); + } + + public void write(OutputStream out, Document document, int offset, int len) + throws BadLocationException, IOException + { + write(new OutputStreamWriter(out), document, offset, len); + } + + public void write(Writer out, Document document, int offset, int len) + throws BadLocationException, IOException + { + } +} diff --git a/libjava/classpath/javax/swing/text/DefaultFormatter.java b/libjava/classpath/javax/swing/text/DefaultFormatter.java new file mode 100644 index 0000000..c97d907 --- /dev/null +++ b/libjava/classpath/javax/swing/text/DefaultFormatter.java @@ -0,0 +1,429 @@ +/* DefaultFormatter.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.io.Serializable; +import java.lang.reflect.Constructor; +import java.text.ParseException; + +import javax.swing.JFormattedTextField; + +/** + * The DefaultFormatter is a concrete formatter for use in + * {@link JFormattedTextField}s. + * + * It can format arbitrary values by invoking + * their {@link Object#toString} method. + * + * In order to convert a String back to + * a value, the value class must provide a single argument constructor that + * takes a String object as argument value. If no such constructor is found, + * the String itself is passed back by #stringToValue. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class DefaultFormatter + extends JFormattedTextField.AbstractFormatter + implements Cloneable, Serializable +{ + + /** + * A {@link DocumentFilter} that intercepts modification of the + * JFormattedTextField's Document and commits the value depending + * on the value of the commitsOnValidEdit property. + * + */ + // FIXME: Handle allowsInvalid and overwriteMode properties + private class FormatterDocumentFilter + extends DocumentFilter + { + /** + * Invoked when text is removed from a text component. + * + * @param bypass the FilterBypass to use to mutate the document + * @param offset the start position of the modification + * @param length the length of the removed text + * + * @throws BadLocationException if offset or lenght are invalid in + * the Document + */ + public void remove(DocumentFilter.FilterBypass bypass, int offset, + int length) + throws BadLocationException + { + super.remove(bypass, offset, length); + checkValidInput(); + commitIfAllowed(); + } + + /** + * Invoked when text is inserted into a text component. + * + * @param bypass the FilterBypass to use to mutate the document + * @param offset the start position of the modification + * @param text the inserted text + * @param attributes the attributes of the inserted text + * + * @throws BadLocationException if offset or lenght are invalid in + * the Document + */ + public void insertString(DocumentFilter.FilterBypass bypass, int offset, + String text, AttributeSet attributes) + throws BadLocationException + { + if (overwriteMode == true) + replace(bypass, offset, text.length(), text, attributes); + else + super.insertString(bypass, offset, text, attributes); + checkValidInput(); + commitIfAllowed(); + } + + /** + * Invoked when text is replaced in a text component. + * + * @param bypass the FilterBypass to use to mutate the document + * @param offset the start position of the modification + * @param length the length of the removed text + * @param text the inserted text + * @param attributes the attributes of the inserted text + * + * @throws BadLocationException if offset or lenght are invalid in + * the Document + */ + public void replace(DocumentFilter.FilterBypass bypass, int offset, + int length, String text, AttributeSet attributes) + throws BadLocationException + { + super.replace(bypass, offset, length, text, attributes); + checkValidInput(); + commitIfAllowed(); + } + + /** + * Commits the value to the JTextTextField if the property + * commitsOnValidEdit is set to true. + */ + private void commitIfAllowed() + { + if (commitsOnValidEdit == true) + try + { + getFormattedTextField().commitEdit(); + } + catch (ParseException ex) + { + // ignore invalid edits + } + } + + /** + * Checks if the value in the input field is valid. If the + * property allowsInvalid is set to false, 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() + { + JFormattedTextField ftf = getFormattedTextField(); + try + { + Object newval = stringToValue(ftf.getText()); + } + catch (ParseException ex) + { + if (!allowsInvalid) + { + // roll back the input if invalid edits are not allowed + try + { + ftf.setText(valueToString(ftf.getValue())); + } + catch (ParseException pe) + { + // if that happens, something serious must be wrong + throw new AssertionError("values must be parseable"); + } + } + } + } + } + + /** The serialVersoinUID. */ + private static final long serialVersionUID = -7369196326612908900L; + + /** + * Indicates if the value should be committed after every + * valid modification of the Document. + */ + boolean commitsOnValidEdit; + + /** + * If true newly inserted characters overwrite existing + * values, otherwise insertion is done the normal way. + */ + boolean overwriteMode; + + /** + * If true invalid edits are allowed for a limited + * time. + */ + boolean allowsInvalid; + + /** + * The class that is used for values. + */ + Class valueClass; + + /** + * Creates a new instance of DefaultFormatter. + */ + public DefaultFormatter() + { + commitsOnValidEdit = true; + overwriteMode = true; + allowsInvalid = true; + valueClass = Object.class; + } + + /** + * Installs the formatter on the specified {@link JFormattedTextField}. + * + * This method does the following things: + * + * + * This method is typically not overridden by subclasses. Instead override + * one of the mentioned methods in order to customize behaviour. + * + * @param ftf the {@link JFormattedTextField} in which this formatter + * is installed + */ + public void install(JFormattedTextField ftf) + { + super.install(ftf); + } + + /** + * Returns true if the value should be committed after + * each valid modification of the input field, false if + * it should never be committed by this formatter. + * + * @return the state of the commitsOnValidEdit property + * + * @see #setCommitsOnValidEdit + */ + public boolean getCommitsOnValidEdit() + { + return commitsOnValidEdit; + } + + /** + * Sets the value of the commitsOnValidEdit property. + * + * @param commitsOnValidEdit the new state of the + * commitsOnValidEdit property + * + * @see #getCommitsOnValidEdit + */ + public void setCommitsOnValidEdit(boolean commitsOnValidEdit) + { + this.commitsOnValidEdit = commitsOnValidEdit; + } + + /** + * Returns the value of the overwriteMode property. + * If that is set to true then newly inserted characters + * overwrite existing values, otherwise the characters are inserted like + * normal. The default is true. + * + * @return the value of the overwriteMode property + */ + public boolean getOverwriteMode() + { + return overwriteMode; + } + + /** + * Sets the value of the overwriteMode property. + * + * If that is set to true then newly inserted characters + * overwrite existing values, otherwise the characters are inserted like + * normal. The default is true. + * + * @param overwriteMode the new value for the overwriteMode + * property + */ + public void setOverwriteMode(boolean overwriteMode) + { + this.overwriteMode = overwriteMode; + } + + /** + * Returns whether or not invalid edits are allowed or not. If invalid + * edits are allowed, the JFormattedTextField may temporarily contain invalid + * characters. + * + * @return the value of the allowsInvalid property + */ + public boolean getAllowsInvalid() + { + return allowsInvalid; + } + + /** + * Sets the value of the allowsInvalid property. + * + * @param allowsInvalid the new value for the property + * + * @see #getAllowsInvalid() + */ + public void setAllowsInvalid(boolean allowsInvalid) + { + this.allowsInvalid = allowsInvalid; + } + + /** + * Returns the class that is used for values. When Strings are converted + * back to values, this class is used to create new value objects. + * + * @return the class that is used for values + */ + public Class getValueClass() + { + return valueClass; + } + + /** + * Sets the class that is used for values. + * + * @param valueClass the class that is used for values + * + * @see #getValueClass() + */ + public void setValueClass(Class valueClass) + { + this.valueClass = valueClass; + } + + /** + * Converts a String (from the JFormattedTextField input) to a value. + * In order to achieve this, the formatter tries to instantiate an object + * of the class returned by #getValueClass() using a single argument + * constructor that takes a String argument. If such a constructor cannot + * be found, the String itself is returned. + * + * @param string the string to convert + * + * @return the value for the string + * + * @throws ParseException if the string cannot be converted into + * a value object (e.g. invalid input) + */ + public Object stringToValue(String string) + throws ParseException + { + Object value = string; + Class valueClass = getValueClass(); + if (valueClass == null) + valueClass = getFormattedTextField().getValue().getClass(); + if (valueClass != null) + try + { + Constructor constr = valueClass.getConstructor + (new Class[]{String.class}); + value = constr.newInstance(new Object[]{ string }); + } + catch (NoSuchMethodException ex) + { + // leave value as string + } + catch (Exception ex) + { + throw new ParseException(string, 0); + } + return value; + } + + /** + * Converts a value object into a String. This is done by invoking the + * {@link Object#toString()} method on the value. + * + * @param value the value to be converted + * + * @return the string representation of the value + * + * @throws ParseException if the value cannot be converted + */ + public String valueToString(Object value) + throws ParseException + { + return value.toString(); + } + + /** + * Creates and returns a clone of this DefaultFormatter. + * + * @return a clone of this object + * + * @throws CloneNotSupportedException not thrown here + */ + public Object clone() + throws CloneNotSupportedException + { + return super.clone(); + } + + /** + * Returns the DocumentFilter that is used to restrict input. + * + * @return the DocumentFilter that is used to restrict input + */ + protected DocumentFilter getDocumentFilter() + { + return new FormatterDocumentFilter(); + } +} diff --git a/libjava/classpath/javax/swing/text/DefaultHighlighter.java b/libjava/classpath/javax/swing/text/DefaultHighlighter.java new file mode 100644 index 0000000..c8d874c --- /dev/null +++ b/libjava/classpath/javax/swing/text/DefaultHighlighter.java @@ -0,0 +1,257 @@ +/* DefaultHighlighter.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.Vector; + +public class DefaultHighlighter extends LayeredHighlighter +{ + public static class DefaultHighlightPainter + extends LayerPainter + { + private Color color; + + public DefaultHighlightPainter(Color c) + { + super(); + color = c; + } + + public Color getColor() + { + return color; + } + + private void paintHighlight(Graphics g, Rectangle rect) + { + g.fillRect(rect.x, rect.y, rect.width, rect.height); + } + + public void paint(Graphics g, int p0, int p1, Shape bounds, + JTextComponent c) + { + Rectangle r0 = null; + Rectangle r1 = null; + Rectangle rect = bounds.getBounds(); + + try + { + r0 = c.modelToView(p0); + r1 = c.modelToView(p1); + } + catch (BadLocationException e) + { + // This should never occur. + return; + } + + if (r0 == null || r1 == null) + return; + + if (color == null) + g.setColor(c.getSelectionColor()); + else + g.setColor(color); + + // Check if only one line to highlight. + if (r0.y == r1.y) + { + r0.width = r1.x - r0.x; + paintHighlight(g, r0); + return; + } + + // First line, from p0 to end-of-line. + r0.width = rect.x + rect.width - r0.x; + paintHighlight(g, r0); + + // FIXME: All the full lines in between, if any (assumes that all lines + // have the same height -- not a good assumption with JEditorPane/JTextPane). + r0.y += r0.height; + r0.x = rect.x; + + while (r0.y < r1.y) + { + paintHighlight(g, r0); + r0.y += r0.height; + } + + // Last line, from beginnin-of-line to p1. + paintHighlight(g, r1); + } + + public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds, + JTextComponent c, View view) + { + throw new InternalError(); + } + } + + private class HighlightEntry + { + int p0; + int p1; + Highlighter.HighlightPainter painter; + + public HighlightEntry(int p0, int p1, Highlighter.HighlightPainter painter) + { + this.p0 = p0; + this.p1 = p1; + this.painter = painter; + } + + public int getStartPosition() + { + return p0; + } + + public int getEndPosition() + { + return p1; + } + + public Highlighter.HighlightPainter getPainter() + { + return painter; + } + } + + /** + * @specnote final as of 1.4 + */ + public static final LayeredHighlighter.LayerPainter DefaultPainter = + new DefaultHighlightPainter(null); + + private JTextComponent textComponent; + private Vector highlights = new Vector(); + private boolean drawsLayeredHighlights = true; + + public DefaultHighlighter() + { + } + + public boolean getDrawsLayeredHighlights() + { + return drawsLayeredHighlights; + } + + public void setDrawsLayeredHighlights(boolean newValue) + { + drawsLayeredHighlights = newValue; + } + + private void checkPositions(int p0, int p1) + throws BadLocationException + { + if (p0 < 0) + throw new BadLocationException("DefaultHighlighter", p0); + + if (p1 < p0) + throw new BadLocationException("DefaultHighlighter", p1); + } + + public void install(JTextComponent c) + { + textComponent = c; + removeAllHighlights(); + } + + public void deinstall(JTextComponent c) + { + textComponent = null; + } + + public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter painter) + throws BadLocationException + { + checkPositions(p0, p1); + HighlightEntry entry = new HighlightEntry(p0, p1, painter); + highlights.add(entry); + return entry; + } + + public void removeHighlight(Object tag) + { + highlights.remove(tag); + } + + public void removeAllHighlights() + { + highlights.clear(); + } + + public Highlighter.Highlight[] getHighlights() + { + return null; + } + + public void changeHighlight(Object tag, int p0, int p1) + throws BadLocationException + { + checkPositions(p0, p1); + HighlightEntry entry = (HighlightEntry) tag; + entry.p0 = p0; + entry.p1 = p1; + } + + public void paintLayeredHighlights(Graphics g, int p0, int p1, + Shape viewBounds, JTextComponent editor, + View view) + { + } + + public void paint(Graphics g) + { + // Check if there are any highlights. + if (highlights.size() == 0) + return; + + Shape bounds = textComponent.getBounds(); + + for (int index = 0; index < highlights.size(); ++index) + { + HighlightEntry entry = (HighlightEntry) highlights.get(index); + entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent); + } + } +} diff --git a/libjava/classpath/javax/swing/text/DefaultStyledDocument.java b/libjava/classpath/javax/swing/text/DefaultStyledDocument.java new file mode 100644 index 0000000..6fe206a --- /dev/null +++ b/libjava/classpath/javax/swing/text/DefaultStyledDocument.java @@ -0,0 +1,202 @@ +/* DefaultStyledDocument.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Font; +import java.io.Serializable; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public class DefaultStyledDocument extends AbstractDocument + implements StyledDocument +{ + public class ElementBuffer + implements Serializable + { + private Element root; + + public ElementBuffer(Element root) + { + this.root = root; + } + + public Element getRootElement() + { + return root; + } + } + + public static final int BUFFER_SIZE_DEFAULT = 4096; + + protected DefaultStyledDocument.ElementBuffer buffer; + + public DefaultStyledDocument() + { + this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext()); + } + + public DefaultStyledDocument(StyleContext context) + { + this(new GapContent(BUFFER_SIZE_DEFAULT), context); + } + + public DefaultStyledDocument(AbstractDocument.Content content, + StyleContext context) + { + super(content, context); + buffer = new ElementBuffer(createDefaultRoot()); + setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE)); + } + + public Style addStyle(String nm, Style parent) + { + StyleContext context = (StyleContext) getAttributeContext(); + return context.addStyle(nm, parent); + } + + protected AbstractDocument.AbstractElement createDefaultRoot() + { + Element[] tmp; + BranchElement section = new BranchElement(null, null); + + BranchElement paragraph = new BranchElement(section, null); + tmp = new Element[1]; + tmp[0] = paragraph; + section.replace(0, 0, tmp); + + LeafElement leaf = new LeafElement(paragraph, null, 0, 1); + tmp = new Element[1]; + tmp[0] = leaf; + paragraph.replace(0, 0, tmp); + + return section; + } + + public Element getCharacterElement(int position) + { + Element element = getDefaultRootElement(); + + while (! element.isLeaf()) + { + int index = element.getElementIndex(position); + element = element.getElement(index); + } + + return element; + } + + public Color getBackground(AttributeSet attributes) + { + StyleContext context = (StyleContext) getAttributeContext(); + return context.getBackground(attributes); + } + + public Element getDefaultRootElement() + { + return buffer.getRootElement(); + } + + public Font getFont(AttributeSet attributes) + { + StyleContext context = (StyleContext) getAttributeContext(); + return context.getFont(attributes); + } + + public Color getForeground(AttributeSet attributes) + { + StyleContext context = (StyleContext) getAttributeContext(); + return context.getForeground(attributes); + } + + public Style getLogicalStyle(int position) + { + Element paragraph = getParagraphElement(position); + AttributeSet attributes = paragraph.getAttributes(); + return (Style) attributes.getResolveParent(); + } + + public Element getParagraphElement(int position) + { + Element element = getCharacterElement(position); + return element.getParentElement(); + } + + public Style getStyle(String nm) + { + StyleContext context = (StyleContext) getAttributeContext(); + return context.getStyle(nm); + } + + public void removeStyle(String nm) + { + StyleContext context = (StyleContext) getAttributeContext(); + context.removeStyle(nm); + } + + public void setCharacterAttributes(int offset, int length, + AttributeSet attributes, + boolean replace) + { + // FIXME: Implement me. + throw new Error("not implemented"); + } + + public void setLogicalStyle(int position, Style style) + { + Element el = getParagraphElement(position); + if (el instanceof AbstractElement) + { + AbstractElement ael = (AbstractElement) el; + ael.setResolveParent(style); + } + else + throw new AssertionError("paragraph elements are expected to be" + + "instances of javax.swing.text.AbstractDocument.AbstractElement"); + } + + public void setParagraphAttributes(int offset, int length, + AttributeSet attributes, + boolean replace) + { + // FIXME: Implement me. + throw new Error("not implemented"); + } +} diff --git a/libjava/classpath/javax/swing/text/Document.java b/libjava/classpath/javax/swing/text/Document.java new file mode 100644 index 0000000..f23767f --- /dev/null +++ b/libjava/classpath/javax/swing/text/Document.java @@ -0,0 +1,221 @@ +/* Document.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import javax.swing.event.DocumentListener; +import javax.swing.event.UndoableEditListener; + +/** + * A Document is the model that backs up all text components in Swing. + * This interface supports different kinds of implementations, from + * simple plain text model up to complex styled HTML or RTF models. + */ +public interface Document +{ + /** + * The key for the property that describes the source of a document. + */ + String StreamDescriptionProperty = "stream"; + + /** + * The key for the property that is the title of a document. + */ + String TitleProperty = "title"; + + /** + * Adds a {@link DocumentListener} to this document. + * + * @param listener the DocumentListener to add + */ + void addDocumentListener(DocumentListener listener); + + /** + * Adds an {@link UndoableEditListener} to this document. + * + * @param listener the UndoableEditListener to add + */ + void addUndoableEditListener(UndoableEditListener listener); + + /** + * Creates a mark in the character content at the specified offset. + * + * @param offs the offset where to place the mark + * + * @return the created Position object + * + * @throws BadLocationException of the specified offset is not a valid + * position in the documents content + */ + Position createPosition(int offs) + throws BadLocationException; + + /** + * Returns the default root element. Views should be using this element + * unless other mechanisms for assigning views to element structure is + * provided. + * + * @return the default root element + */ + Element getDefaultRootElement(); + + /** + * Returns the position that marks the end of the document. + * + * @return the position that marks the end of the document + */ + Position getEndPosition(); + + /** + * Returns the length of the document content. + * + * @return the length of the document content + */ + int getLength(); + + /** + * Returns a document property with the specified key. + * + * @param key the (non-null) key for the property to fetch + * + * @return the property for key or null if no such property + * is stored + */ + Object getProperty(Object key); + + /** + * Returns the root elements of the document content. + * + * @return the root elements of the document content + */ + Element[] getRootElements(); + + /** + * Returns the position that marks the beginning of the document + * content. + * + * @return the start position + */ + Position getStartPosition(); + + /** + * Returns the textual content starting at offset with + * a length of length. + * + * @param offset the beginning of the text fragment to fetch + * @param length the length of the text fragment to fetch + * + * @return the text fragment starting at offset with + * a length of length + * + * @throws BadLocationException if offset or length + * are no valid locations in the document content + */ + String getText(int offset, int length) + throws BadLocationException; + + /** + * Fetch the textual content starting at offset with + * a length of length and store it in txt. + * + * @param offset the beginning of the text fragment to fetch + * @param length the length of the text fragment to fetch + * @param txt the Segment where to store the text fragment + * + * @throws BadLocationException if offset or length + * are no valid locations in the document content + */ + void getText(int offset, int length, Segment txt) + throws BadLocationException; + + /** + * Inserts a piece of text with an AttributeSet at the specified + * offset. + * + * @param offset the location where to insert the content + * @param str the textual content to insert + * @param a the Attributes associated with the piece of text + * + * @throws BadLocationException if offset + * is not a valid location in the document content + */ + void insertString(int offset, String str, AttributeSet a) + throws BadLocationException; + + /** + * Sets a document property. + * + * @param key the key of the property + * @param value the value of the property + */ + void putProperty(Object key, Object value); + + /** + * Removes a piece of content. + * + * @param offs the location of the fragment to remove + * @param len the length of the fragment to remove + * + * @throws BadLocationException if offs or len + * are no valid locations in the document content + */ + void remove(int offs, int len) + throws BadLocationException; + + /** + * Removes a DocumentListener from this Document. + * + * @param listener the DocumentListener to remove + */ + void removeDocumentListener(DocumentListener listener); + + /** + * Removes an UndoableEditListener from this Document. + * + * @param listener the UndoableEditListener to remove + */ + void removeUndoableEditListener(UndoableEditListener listener); + + /** + * This allows the Document to be rendered safely. It is made sure that + * the Runnable can read the document without any changes while reading. + * The Runnable is not allowed to change the Document itself. + * + * @param r the Runnable that renders the Document + */ + void render(Runnable r); +} diff --git a/libjava/classpath/javax/swing/text/DocumentFilter.java b/libjava/classpath/javax/swing/text/DocumentFilter.java new file mode 100644 index 0000000..f86f41c --- /dev/null +++ b/libjava/classpath/javax/swing/text/DocumentFilter.java @@ -0,0 +1,83 @@ +/* DocumentFilter.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +public class DocumentFilter +{ + public abstract static class FilterBypass + { + public FilterBypass() + { + // Do nothing here. + } + + public abstract Document getDocument(); + + public abstract void insertString(int offset, String string, + AttributeSet attr) + throws BadLocationException; + + public abstract void remove(int offset, int length) + throws BadLocationException; + + public abstract void replace(int offset, int length, String string, + AttributeSet attrs) + throws BadLocationException; + } + + public void insertString(DocumentFilter.FilterBypass fb, int offset, + String string, AttributeSet attr) + throws BadLocationException + { + fb.insertString(offset, string, attr); + } + + public void remove(DocumentFilter.FilterBypass fb, int offset, int length) + throws BadLocationException + { + fb.remove(offset, length); + } + + public void replace(DocumentFilter.FilterBypass fb, int offset, int length, + String text, AttributeSet attr) + throws BadLocationException + { + fb.replace(offset, length, text, attr); + } +} diff --git a/libjava/classpath/javax/swing/text/EditorKit.java b/libjava/classpath/javax/swing/text/EditorKit.java new file mode 100644 index 0000000..bd51a86 --- /dev/null +++ b/libjava/classpath/javax/swing/text/EditorKit.java @@ -0,0 +1,96 @@ +/* EditorKit.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Serializable; +import java.io.Writer; + +import javax.swing.Action; +import javax.swing.JEditorPane; + +public abstract class EditorKit + implements Cloneable, Serializable +{ + private static final long serialVersionUID = -5044124649345887822L; + + public EditorKit() + { + } + + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + return null; + } + } + + /** + * Called when the kit is being removed from the JEditorPane. + */ + public void deinstall(JEditorPane c) + { + } + + public void install(JEditorPane c) + { + } + + public abstract Caret createCaret(); + public abstract Document createDefaultDocument(); + public abstract Action[] getActions(); + public abstract String getContentType(); + public abstract ViewFactory getViewFactory(); + public abstract void read(InputStream in, Document doc, int pos) + throws BadLocationException, IOException; + public abstract void read(Reader in, Document doc, int pos) + throws BadLocationException, IOException; + public abstract void write(OutputStream out, Document doc, int pos, int len) + throws BadLocationException, IOException; + public abstract void write(Writer out, Document doc, int pos, int len) + throws BadLocationException, IOException; +} diff --git a/libjava/classpath/javax/swing/text/Element.java b/libjava/classpath/javax/swing/text/Element.java new file mode 100644 index 0000000..eb53ee9 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Element.java @@ -0,0 +1,54 @@ +/* Element.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + + + +public interface Element +{ + AttributeSet getAttributes(); + Document getDocument(); + Element getElement(int index); + int getElementCount(); + int getElementIndex(int offset); + int getEndOffset(); + String getName(); + Element getParentElement(); + int getStartOffset(); + boolean isLeaf(); + } diff --git a/libjava/classpath/javax/swing/text/FieldView.java b/libjava/classpath/javax/swing/text/FieldView.java new file mode 100644 index 0000000..4d5c51c --- /dev/null +++ b/libjava/classpath/javax/swing/text/FieldView.java @@ -0,0 +1,176 @@ +/* FieldView.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; + +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; + +public class FieldView extends PlainView +{ + public FieldView(Element elem) + { + super(elem); + } + + protected FontMetrics getFontMetrics() + { + Component container = getContainer(); + return container.getFontMetrics(container.getFont()); + } + + /** + * Vertically centers the single line of text within the + * bounds of the input shape. The returned Rectangle is centered + * vertically within shape and has a height of the + * preferred span along the Y axis. Horizontal adjustment is done according + * to the horizontalAligment property of the component that is rendered. + * + * @param shape the shape within which the line is beeing centered + */ + protected Shape adjustAllocation(Shape shape) + { + Rectangle rectIn = shape.getBounds(); + // vertical adjustment + int height = (int) getPreferredSpan(Y_AXIS); + int y = rectIn.y + (rectIn.height - height) / 2; + // horizontal adjustment + JTextField textField = (JTextField) getContainer(); + int halign = textField.getHorizontalAlignment(); + int width = (int) getPreferredSpan(X_AXIS); + int x; + ComponentOrientation orientation = textField.getComponentOrientation(); + switch (halign) + { + case JTextField.CENTER: + x = rectIn.x + (rectIn.width - width) / 2; + break; + case JTextField.RIGHT: + x = rectIn.x + (rectIn.width - width); + break; + case JTextField.TRAILING: + if (orientation.isLeftToRight()) + x = rectIn.x + (rectIn.width - width); + else + x = rectIn.x; + break; + case JTextField.LEADING: + if (orientation.isLeftToRight()) + x = rectIn.x; + else + x = rectIn.x + (rectIn.width - width); + break; + case JTextField.LEFT: + default: + x = rectIn.x; + break; + } + return new Rectangle(x, y, width, height); + } + + public float getPreferredSpan(int axis) + { + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException(); + + FontMetrics fm = getFontMetrics(); + + if (axis == Y_AXIS) + return fm.getHeight(); + + String text; + Element elem = getElement(); + + try + { + text = elem.getDocument().getText(elem.getStartOffset(), + elem.getEndOffset()); + } + catch (BadLocationException e) + { + // This should never happen. + text = ""; + } + + return fm.stringWidth(text); + } + + public int getResizeWeight(int axis) + { + return axis = axis == X_AXIS ? 1 : 0; + } + + public Shape modelToView(int pos, Shape a, Position.Bias bias) + throws BadLocationException + { + Shape newAlloc = adjustAllocation(a); + return super.modelToView(pos, newAlloc, bias); + } + + public void paint(Graphics g, Shape s) + { + Shape newAlloc = adjustAllocation(s); + super.paint(g, newAlloc); + } + + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Shape newAlloc = adjustAllocation(shape); + super.insertUpdate(ev, newAlloc, vf); + } + + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Shape newAlloc = adjustAllocation(shape); + super.removeUpdate(ev, newAlloc, vf); + } + + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Shape newAlloc = adjustAllocation(shape); + super.removeUpdate(ev, newAlloc, vf); + } + +} diff --git a/libjava/classpath/javax/swing/text/GapContent.java b/libjava/classpath/javax/swing/text/GapContent.java new file mode 100644 index 0000000..1bbef8f --- /dev/null +++ b/libjava/classpath/javax/swing/text/GapContent.java @@ -0,0 +1,356 @@ +/* GapContent.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.io.Serializable; + +import javax.swing.undo.UndoableEdit; + +/** + * This implementation of {@link AbstractDocument.Content} uses a gapped + * buffer. This takes advantage of the fact that text area content is + * mostly inserted sequentially. The buffer is a char array that maintains + * a gap at the current insertion point. If characters a inserted at + * gap boundaries, the cost is minimal (simple array access). The array only + * has to be shifted around when the insertion point moves (then the gap also + * moves and one array copy is necessary) or when the gap is filled up and + * the buffer has to be enlarged. + * + * TODO: Implement UndoableEdit support stuff + */ +public class GapContent + implements AbstractDocument.Content, Serializable +{ + private static final long serialVersionUID = 8374645204155842629L; + + /** + * 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; + + /** + * The text buffer. + */ + char[] buffer; + + /** + * The index of the first character of the gap. + */ + int gapStart; + + /** + * The index of the character after the last character of the gap. + */ + int gapEnd; + + /** + * Creates a new GapContent object. + */ + public GapContent() + { + this(DEFAULT_BUFSIZE); + } + + /** + * Creates a new GapContent object with a specified initial size. + * + * @param size the initial size of the buffer + */ + public GapContent(int size) + { + buffer = (char[]) allocateArray(size); + gapStart = 0; + gapEnd = size - 1; + buffer[size - 1] = '\n'; + } + + /** + * Allocates an array of the specified length that can then be used as + * buffer. + * + * @param size the size of the array to be allocated + * + * @return the allocated array + */ + protected Object allocateArray(int size) + { + return new char[size]; + } + + /** + * Returns the length of the allocated buffer array. + * + * @return the length of the allocated buffer array + */ + protected int getArrayLength() + { + return buffer.length; + } + + /** + * Returns the length of the content. + * + * @return the length of the content + */ + public int length() + { + return buffer.length - (gapEnd - gapStart); + } + + /** + * Inserts a string at the specified position. + * + * @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 + * null is returned) + * + * @throws BadLocationException if where is not a valid location + * in the buffer + */ + public UndoableEdit insertString(int where, String str) + throws BadLocationException + { + // check arguments + int length = length(); + int strLen = str.length(); + + if (where >= length) + throw new BadLocationException("the where argument cannot be greater" + + " than the content length", where); + + // check if the gap is big enough to hold the string + if ((gapEnd - gapStart) < strLen) + // make room for this string and some more + shiftEnd(strLen + DEFAULT_BUFSIZE); + + // are we at the gap boundary? + if (where != gapStart) + shiftGap(where); + + // now we can simple copy the string into the gap and adjust the + // gap boundaries + System.arraycopy(str.toCharArray(), 0, buffer, gapStart, strLen); + gapStart += strLen; + return null; + } + + /** + * Removes a piece of content at th specified position. + * + * @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 + * null is returned) + * + * @throws BadLocationException if where is not a valid location + * in the buffer + */ + public UndoableEdit remove(int where, int nitems) + throws BadLocationException + { + // check arguments + int length = length(); + + if (where >= length) + throw new BadLocationException("the where argument cannot be greater" + + " than the content length", where); + if ((where + nitems) > length) + throw new BadLocationException("where + nitems cannot be greater" + + " than the content length", + where + nitems); + + // check if we are at the gap boundary + if (where != gapStart) + shiftGap(where); + + // now we simply have to enlarge the gap + gapEnd += nitems; + return null; + } + + /** + * Returns a piece of content as String. + * + * @param where the start location of the fragment + * @param len the length of the fragment + * + * @throws BadLocationException if where or + * where + len are no valid locations in the buffer + */ + public String getString(int where, int len) throws BadLocationException + { + Segment seg = new Segment(); + getChars(where, len, seg); + return new String(seg.array, seg.offset, seg.count); + } + + /** + * Fetches a piece of content and stores it in a {@link Segment} object. + * + * If the requested piece of text spans the gap, the content is copied + * into a new array. If it doesn't then it is contiguous and the + * actual content store is returned. + * + * @param where the start location of the fragment + * @param len the length of the fragment + * @param txt the Segment object to store the fragment in + * + * @throws BadLocationException if where or + * where + len are no valid locations in the buffer + */ + public void getChars(int where, int len, Segment txt) + throws BadLocationException + { + // check arguments + int length = length(); + if (where >= length) + throw new BadLocationException("the where argument cannot be greater" + + " than the content length", where); + if ((where + len) > length) + throw new BadLocationException("len plus where cannot be greater" + + " than the content length", + len + where); + + // check if requested segment is contiguous + if ((where < gapStart) && ((gapStart - where) < len)) + { + // requested segment is not contiguous -> copy the pieces together + char[] copy = new char[len]; + int lenFirst = gapStart - where; // the length of the first segment + System.arraycopy(buffer, where, copy, 0, lenFirst); + System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst); + txt.array = copy; + txt.offset = 0; + txt.count = len; + } + else + { + // requested segment is contiguous -> we can simply return the + // actual content + txt.array = buffer; + if (where < gapStart) + txt.offset = where; + else + txt.offset = where + (gapEnd - gapStart); + txt.count = len; + } + } + + /** + * Creates and returns a mark at the specified position. + * + * @param offset the position at which to create the mark + * + * @return the create Position object for the mark + * + * @throws BadLocationException if the offset is not a valid position in + * the buffer + */ + public Position createPosition(final int offset) throws BadLocationException + { + return new Position() + { + int off = offset; + + public int getOffset() + { + return off; + } + }; + } + + /** + * Enlarges the gap. This allocates a new bigger buffer array, copy the + * segment before the gap as it is and the segment after the gap at + * the end of the new buffer array. This does change the gapEnd mark + * but not the gapStart mark. + * + * @param newSize the new size of the gap + */ + protected void shiftEnd(int newSize) + { + char[] newBuf = (char[]) allocateArray(length() + newSize); + System.arraycopy(buffer, 0, newBuf, 0, gapStart); + System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, + buffer.length - gapEnd); + gapEnd = gapStart + newSize; + buffer = newBuf; + } + + /** + * Shifts the gap to the specified position. + * + * @param newGapStart the new start position of the gap + */ + protected void shiftGap(int newGapStart) + { + int newGapEnd = newGapStart + (gapEnd - gapStart); + + if (newGapStart == gapStart) + return; + else if (newGapStart < gapStart) + { + System.arraycopy(buffer, newGapStart, buffer, newGapEnd, + gapStart - newGapStart); + gapStart = newGapStart; + gapEnd = newGapEnd; + } + else + { + System.arraycopy(buffer, gapEnd, buffer, gapStart, + newGapStart - gapStart); + gapStart = newGapStart; + gapEnd = newGapEnd; + } + } + + /** + * Returns the allocated buffer array. + * + * @return the allocated buffer array + */ + protected Object getArray() + { + return buffer; + } +} diff --git a/libjava/classpath/javax/swing/text/Highlighter.java b/libjava/classpath/javax/swing/text/Highlighter.java new file mode 100644 index 0000000..91f3b79 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Highlighter.java @@ -0,0 +1,79 @@ +/* Highlighter.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Graphics; +import java.awt.Shape; + + +public interface Highlighter +{ + public interface Highlight + { + int getEndOffset(); + + int getStartOffset(); + + HighlightPainter getPainter(); + } + + public interface HighlightPainter + { + void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c); + } + + void install(JTextComponent c); + + void deinstall(JTextComponent c); + + Object addHighlight(int p0, int p1, HighlightPainter p) + throws BadLocationException; + + void removeAllHighlights(); + + void removeHighlight(Object tag); + + void changeHighlight(Object tag, int p0, int p1) + throws BadLocationException; + + Highlight[] getHighlights(); + + void paint(Graphics g); +} + diff --git a/libjava/classpath/javax/swing/text/InternationalFormatter.java b/libjava/classpath/javax/swing/text/InternationalFormatter.java new file mode 100644 index 0000000..531a4c1 --- /dev/null +++ b/libjava/classpath/javax/swing/text/InternationalFormatter.java @@ -0,0 +1,354 @@ +/* InternationalFormatter.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.text.AttributedCharacterIterator; +import java.text.Format; +import java.text.ParseException; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.swing.Action; +import javax.swing.JFormattedTextField; + +/** + * This extends {@link DefaultFormatter} so that the value to string + * conversion is done via a {@link Format} object. This allows + * various additional formats to be handled by JFormattedField. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class InternationalFormatter + extends DefaultFormatter +{ + + /** The serialVersoinUID. */ + private static final long serialVersionUID = 6941977820906408656L; + + /** The format that handles value to string conversion. */ + Format format; + + /** The minimal permissable value. */ + Comparable minimum; + + /** The maximal permissable value. */ + Comparable maximum; + + /** + * Creates a new InternationalFormatter with no Format specified. + */ + public InternationalFormatter() + { + super(); + minimum = null; + maximum = null; + format = null; + } + + /** + * Creates a new InternationalFormatter that uses the specified + * Format object for value to string conversion. + * + * @param format the Format object to use for value to string conversion + */ + public InternationalFormatter(Format format) + { + this(); + setFormat(format); + } + + /** + * Sets the Format object that is used to convert values to strings. + * + * @param format the Format to use for value to string conversion + * + * @see Format + */ + public void setFormat(Format format) + { + this.format = format; + } + + /** + * Returns the currently used Format object that is used to format + * the JFormattedField. + * + * @return the current Format + */ + public Format getFormat() + { + return format; + } + + /** + * Sets the minimum value that is allowed by this Formatter. The minimum + * value is given as an object that implements the {@link Comparable} + * interface. + * + * If minValue is null, then the Formatter has no restrictions + * at the lower end. + * + * If value class is not yet specified and minValue is not + * null, then valueClass is set to the class of the minimum + * value. + * + * @param minValue the minimum permissable value + * + * @see Comparable + */ + public void setMinimum(Comparable minValue) + { + minimum = minValue; + if (valueClass == null && minValue != null) + valueClass = minValue.getClass(); + } + + /** + * Returns the minimal value that is allowed by this Formatter. + * + * A null value means that there is no restriction. + * + * @return the minimal value that is allowed by this Formatter or + * null if there is no restriction + */ + public Comparable getMinimum() + { + return minimum; + } + + /** + * Sets the maximum value that is allowed by this Formatter. The maximum + * value is given as an object that implements the {@link Comparable} + * interface. + * + * If maxValue is null, then the Formatter has no restrictions + * at the upper end. + * + * If value class is not yet specified and maxValue is not + * null, then valueClass is set to the class of the maximum + * value. + * + * @param maxValue the maximum permissable value + * + * @see Comparable + */ + public void setMaximum(Comparable maxValue) + { + maximum = maxValue; + if (valueClass == null && maxValue != null) + valueClass = maxValue.getClass(); + } + + /** + * Returns the maximal value that is allowed by this Formatter. + * + * A null value means that there is no restriction. + * + * @return the maximal value that is allowed by this Formatter or + * null if there is no restriction + */ + public Comparable getMaximum() + { + return maximum; + } + + /** + * Installs the formatter on the specified {@link JFormattedTextField}. + * + * This method does the following things: + * + * + * This method is typically not overridden by subclasses. Instead override + * one of the mentioned methods in order to customize behaviour. + * + * @param ftf the {@link JFormattedTextField} in which this formatter + * is installed + */ + public void install(JFormattedTextField ftf) + { + super.install(ftf); + } + + /** + * Converts a value object into a String. This is done by invoking + * {@link Format#format} on the specified Format object. + * If no format is set, then {@link DefaultFormatter#valueToString(Object)} + * is called as a fallback. + * + * @param value the value to be converted + * + * @return the string representation of the value + * + * @throws ParseException if the value cannot be converted + */ + public String valueToString(Object value) + throws ParseException + { + if (format != null) + return format.format(value); + else + return super.valueToString(value); + } + + /** + * Converts a String (from the JFormattedTextField input) to a value. + * This is achieved by invoking {@link Format#parseObject(String)} on + * the specified Format object. + * + * This implementation differs slightly from {@link DefaultFormatter}, + * it does: + *
    + *
  1. Convert the string to an Object using the + * Formatter.
  2. + *
  3. If a valueClass has been set, this object is passed to + * {@link DefaultFormatter#stringToValue(String)} so that the value + * has the correct type. This may or may not work correctly, depending on + * the implementation of toString() in the value class and if the class + * implements a constructor that takes one String as argument.
  4. + *
  5. If no {@link ParseException} has been thrown so far, we check if the + * value exceeds either minimum or maximum if + * one of those has been specified and throw a ParseException + * if it does.
  6. + *
  7. Return the value.
  8. + *
+ * + * If no format has been specified, then + * {@link DefaultFormatter#stringToValue(String)} is invoked as fallback. + * + * @param string the string to convert + * + * @return the value for the string + * + * @throws ParseException if the string cannot be converted into + * a value object (e.g. invalid input) + */ + public Object stringToValue(String string) + throws ParseException + { + if (format != null) + { + Object o = format.parseObject(string); + + // If a value class has been set, call super in order to get + // the class right. That is what the JDK API docs suggest, so we do + // it that way. + if (valueClass != null) + o = super.stringToValue(o.toString()); + + // Check for minimum and maximum bounds + if (minimum != null && minimum.compareTo(o) > 0) + throw new ParseException("The value may not be less than the" + + " specified minimum", 0); + if (maximum != null && minimum.compareTo(o) < 0) + throw new ParseException("The value may not be greater than the" + + " specified maximum", 0); + return o; + } + else + return super.stringToValue(string); + } + + /** + * Returns the {@link Format.Field} constants that are associated with + * the specified position in the text. + * + * If offset is not a valid location in the input field, + * an empty array of fields is returned. + * + * @param offset the position in the text from which we want to fetch + * the fields constants + * + * @return the field values associated with the specified position in + * the text + */ + public Format.Field[] getFields(int offset) + { + // TODO: don't know if this is correct + AttributedCharacterIterator aci = format.formatToCharacterIterator + (getFormattedTextField().getValue()); + aci.setIndex(offset); + Map atts = aci.getAttributes(); + Set keys = atts.keySet(); + Format.Field[] fields = new Format.Field[keys.size()]; + int index = 0; + for (Iterator i = keys.iterator(); i.hasNext(); index++) + fields[index] = (Format.Field) i.next(); + return fields; + } + + /** + * This creates and returns a clone of this Formatter. + * + * @return a clone of this formatter + * + * @throws CloneNotSupportedException not thrown here, since cloning is + * supported + * XXX - FIXME - Whole method disabled as workaround for gcj bug #22060. + public Object clone() + throws CloneNotSupportedException + { + // TODO: it has to be considered, if we should return a deep or shallow + // clone here. for now we return a shallow clone + Object clone = super.clone(); + return clone; + } + */ + + /** + * Returns the Actions that are supported by this Formatter. + * + * @specnote the JDK API docs say here: If + * getSupportsIncrement returns true, this returns two + * Actions suitable for incrementing/decrementing the value. + * The questsion is, which method getSupportsIncrement? + * There is no such method in the whole API! So we just call + * super.getActions here. + */ + public Action[] getActions() + { + return super.getActions(); + } +} diff --git a/libjava/classpath/javax/swing/text/JTextComponent.java b/libjava/classpath/javax/swing/text/JTextComponent.java new file mode 100644 index 0000000..f2ef4d7 --- /dev/null +++ b/libjava/classpath/javax/swing/text/JTextComponent.java @@ -0,0 +1,1674 @@ +/* JTextComponent.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.AWTEvent; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +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.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.Enumeration; +import java.util.Hashtable; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleText; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +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; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.InputMapUIResource; +import javax.swing.plaf.TextUI; + +public abstract class JTextComponent extends JComponent + implements Scrollable, Accessible +{ + /** + * AccessibleJTextComponent + */ + public class AccessibleJTextComponent extends AccessibleJComponent + implements AccessibleText, CaretListener, DocumentListener + { + private static final long serialVersionUID = 7664188944091413696L; + + /** + * Constructor AccessibleJTextComponent + * @param component TODO + */ + public AccessibleJTextComponent() + { + } + + /** + * getCaretPosition + * @return int + */ + public int getCaretPosition() + { + return 0; // TODO + } + + /** + * getSelectedText + * @return String + */ + public String getSelectedText() + { + return null; // TODO + } + + /** + * getSelectionStart + * @return int + */ + public int getSelectionStart() + { + return 0; // TODO + } + + /** + * getSelectionEnd + * @return int + */ + public int getSelectionEnd() + { + return 0; // TODO + } + + /** + * caretUpdate + * @param value0 TODO + */ + public void caretUpdate(CaretEvent value0) + { + // TODO + } + + /** + * getAccessibleStateSet + * @return AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; // TODO + } + + /** + * getAccessibleRole + * @return AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return null; // TODO + } + + /** + * getAccessibleText + * @return AccessibleText + */ + public AccessibleText getAccessibleText() + { + return null; // TODO + } + + /** + * insertUpdate + * @param value0 TODO + */ + public void insertUpdate(DocumentEvent value0) + { + // TODO + } + + /** + * removeUpdate + * @param value0 TODO + */ + public void removeUpdate(DocumentEvent value0) + { + // TODO + } + + /** + * changedUpdate + * @param value0 TODO + */ + public void changedUpdate(DocumentEvent value0) + { + // TODO + } + + /** + * getIndexAtPoint + * @param value0 TODO + * @return int + */ + public int getIndexAtPoint(Point value0) + { + return 0; // TODO + } + + /** + * getRootEditorRect + * @return Rectangle + */ + Rectangle getRootEditorRect() + { + return null; + } + + /** + * getCharacterBounds + * @param value0 TODO + * @return Rectangle + */ + public Rectangle getCharacterBounds(int value0) + { + return null; // TODO + } + + /** + * getCharCount + * @return int + */ + public int getCharCount() + { + return 0; // TODO + } + + /** + * getCharacterAttribute + * @param value0 TODO + * @return AttributeSet + */ + public AttributeSet getCharacterAttribute(int value0) + { + return null; // TODO + } + + /** + * getAtIndex + * @param value0 TODO + * @param value1 TODO + * @return String + */ + public String getAtIndex(int value0, int value1) + { + return null; // TODO + } + + /** + * getAfterIndex + * @param value0 TODO + * @param value1 TODO + * @return String + */ + public String getAfterIndex(int value0, int value1) + { + return null; // TODO + } + + /** + * getBeforeIndex + * @param value0 TODO + * @param value1 TODO + * @return String + */ + public String getBeforeIndex(int value0, int value1) + { + return null; // TODO + } + } + + public static class KeyBinding + { + public KeyStroke key; + public String actionName; + + /** + * Creates a new KeyBinding instance. + * + * @param key a KeyStroke value + * @param actionName a String value + */ + public KeyBinding(KeyStroke key, String actionName) + { + this.key = key; + this.actionName = actionName; + } + } + + /** + * 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 this + * report, a pair of private classes wraps a {@link + * javax.swing.text.Keymap} in the new {@link InputMap} / {@link + * ActionMap} interfaces, such that old Keymap-using code can make use of + * the new framework. + * + *

A little bit of experimentation with these classes reveals the following + * structure: + * + *

+ */ + + private class KeymapWrapper extends InputMap + { + Keymap map; + + public KeymapWrapper(Keymap k) + { + map = k; + } + + public int size() + { + return map.getBoundKeyStrokes().length + super.size(); + } + + public Object get(KeyStroke ks) + { + Action mapped = null; + Keymap m = map; + while(mapped == null && m != null) + { + mapped = m.getAction(ks); + if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED) + mapped = m.getDefaultAction(); + if (mapped == null) + m = m.getResolveParent(); + } + + if (mapped == null) + return super.get(ks); + else + return mapped; + } + + public KeyStroke[] keys() + { + KeyStroke[] superKeys = super.keys(); + KeyStroke[] mapKeys = map.getBoundKeyStrokes(); + KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + public KeyStroke[] allKeys() + { + KeyStroke[] superKeys = super.allKeys(); + KeyStroke[] mapKeys = map.getBoundKeyStrokes(); + KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + } + + private class KeymapActionMap extends ActionMap + { + Keymap map; + + public KeymapActionMap(Keymap k) + { + map = k; + } + + public Action get(Object cmd) + { + if (cmd instanceof Action) + return (Action) cmd; + else + return super.get(cmd); + } + + public int size() + { + return map.getBoundKeyStrokes().length + super.size(); + } + + public Object[] keys() + { + Object[] superKeys = super.keys(); + Object[] mapKeys = map.getBoundKeyStrokes(); + Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + public Object[] allKeys() + { + Object[] superKeys = super.allKeys(); + Object[] mapKeys = map.getBoundKeyStrokes(); + Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + } + + static class DefaultKeymap implements Keymap + { + String name; + Keymap parent; + Hashtable map; + Action defaultAction; + + public DefaultKeymap(String name) + { + this.name = name; + this.map = new Hashtable(); + } + + public void addActionForKeyStroke(KeyStroke key, Action a) + { + map.put(key, a); + } + + /** + * Looks up a KeyStroke either in the current map or the parent Keymap; + * does not return the default action if lookup fails. + * + * @param key The KeyStroke to look up an Action for. + * + * @return The mapping for key, or null + * if no mapping exists in this Keymap or any of its parents. + */ + public Action getAction(KeyStroke key) + { + if (map.containsKey(key)) + return (Action) map.get(key); + else if (parent != null) + return parent.getAction(key); + else + return null; + } + + public Action[] getBoundActions() + { + Action [] ret = new Action[map.size()]; + Enumeration e = map.elements(); + int i = 0; + while (e.hasMoreElements()) + { + ret[i++] = (Action) e.nextElement(); + } + return ret; + } + + public KeyStroke[] getBoundKeyStrokes() + { + KeyStroke [] ret = new KeyStroke[map.size()]; + Enumeration e = map.keys(); + int i = 0; + while (e.hasMoreElements()) + { + ret[i++] = (KeyStroke) e.nextElement(); + } + return ret; + } + + public Action getDefaultAction() + { + return defaultAction; + } + + public KeyStroke[] getKeyStrokesForAction(Action a) + { + int i = 0; + Enumeration e = map.keys(); + while (e.hasMoreElements()) + { + if (map.get(e.nextElement()).equals(a)) + ++i; + } + KeyStroke [] ret = new KeyStroke[i]; + i = 0; + e = map.keys(); + while (e.hasMoreElements()) + { + KeyStroke k = (KeyStroke) e.nextElement(); + if (map.get(k).equals(a)) + ret[i++] = k; + } + return ret; + } + + public String getName() + { + return name; + } + + public Keymap getResolveParent() + { + return parent; + } + + public boolean isLocallyDefined(KeyStroke key) + { + return map.containsKey(key); + } + + public void removeBindings() + { + map.clear(); + } + + public void removeKeyStrokeBinding(KeyStroke key) + { + map.remove(key); + } + + public void setDefaultAction(Action a) + { + defaultAction = a; + } + + public void setResolveParent(Keymap p) + { + parent = p; + } + } + + class DefaultTransferHandler + extends TransferHandler + { + public boolean canImport(JComponent component, DataFlavor[] flavors) + { + JTextComponent textComponent = (JTextComponent) component; + + if (! (textComponent.isEnabled() + && textComponent.isEditable() + && flavors != null)) + return false; + + for (int i = 0; i < flavors.length; ++i) + if (flavors[i].equals(DataFlavor.stringFlavor)) + return true; + + return false; + } + + public void exportToClipboard(JComponent component, Clipboard clipboard, + int action) + { + JTextComponent textComponent = (JTextComponent) component; + int start = textComponent.getSelectionStart(); + int end = textComponent.getSelectionEnd(); + + if (start == end) + 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); + } + catch (BadLocationException e) + { + // Ignore this and do nothing. + } + } + + public int getSourceActions() + { + return NONE; + } + + public boolean importData(JComponent component, Transferable transferable) + { + DataFlavor flavor = null; + DataFlavor[] flavors = transferable.getTransferDataFlavors(); + + if (flavors == null) + return false; + + for (int i = 0; i < flavors.length; ++i) + if (flavors[i].equals(DataFlavor.stringFlavor)) + flavor = flavors[i]; + + if (flavor == null) + return false; + + try + { + JTextComponent textComponent = (JTextComponent) component; + String data = (String) transferable.getTransferData(flavor); + textComponent.replaceSelection(data); + return true; + } + catch (IOException e) + { + // Ignored. + } + catch (UnsupportedFlavorException e) + { + // Ignored. + } + + return false; + } + } + + private static final long serialVersionUID = -8796518220218978795L; + + public static final String DEFAULT_KEYMAP = "default"; + public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; + + private static DefaultTransferHandler defaultTransferHandler; + private static Hashtable keymaps = new Hashtable(); + private Keymap keymap; + private char focusAccelerator = '\0'; + private NavigationFilter navigationFilter; + + private CaretBlinkTimer caretBlinkTimer; + + /** + * Get a Keymap from the global keymap table, by name. + * + * @param n The name of the Keymap to look up + * + * @return A Keymap associated with the provided name, or + * null if no such Keymap exists + * + * @see #addKeymap() + * @see #removeKeymap() + * @see #keymaps + */ + public static Keymap getKeymap(String n) + { + return (Keymap) keymaps.get(n); + } + + /** + * Remove a Keymap from the global Keymap table, by name. + * + * @param n The name of the Keymap to remove + * + * @return The keymap removed from the global table + * + * @see #addKeymap() + * @see #getKeymap() + * @see #keymaps + */ + public static Keymap removeKeymap(String n) + { + Keymap km = (Keymap) keymaps.get(n); + keymaps.remove(n); + return km; + } + + /** + * Create a new Keymap with a specific name and parent, and add the new + * Keymap to the global keymap table. The name may be null, + * in which case the new Keymap will not be added to the global + * Keymap table. The parent may also be null, which is + * harmless. + * + * @param n The name of the new Keymap, or null + * @param parent The parent of the new Keymap, or null + * + * @return The newly created Keymap + * + * @see #removeKeymap() + * @see #getKeymap() + * @see #keymaps + */ + public static Keymap addKeymap(String n, Keymap parent) + { + Keymap k = new DefaultKeymap(n); + k.setResolveParent(parent); + if (n != null) + keymaps.put(n, k); + return k; + } + + /** + * Get the current Keymap of this component. + * + * @return The component's current Keymap + * + * @see #setKeymap() + * @see #keymap + */ + public Keymap getKeymap() + { + return keymap; + } + + /** + * Set the current Keymap of this component, installing appropriate + * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the + * {@link InputMap} and {@link ActionMap} parent chains, respectively, + * and fire a property change event with name "keymap". + * + * @see #getKeymap() + * @see #keymap + */ + public void setKeymap(Keymap k) + { + + // phase 1: replace the KeymapWrapper entry in the InputMap chain. + // the goal here is to always maintain the following ordering: + // + // [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]* + // + // that is to say, component-specific InputMaps need to remain children + // of Keymaps, and Keymaps need to remain children of UI-installed + // InputMaps (and the order of each group needs to be preserved, of + // course). + + KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k)); + InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED); + if (childInputMap == null) + setInputMap(JComponent.WHEN_FOCUSED, kw); + else + { + while (childInputMap.getParent() != null + && !(childInputMap.getParent() instanceof KeymapWrapper) + && !(childInputMap.getParent() instanceof InputMapUIResource)) + childInputMap = childInputMap.getParent(); + + // option 1: there is nobody to replace at the end of the chain + if (childInputMap.getParent() == null) + childInputMap.setParent(kw); + + // option 2: there is already a KeymapWrapper in the chain which + // needs replacing (possibly with its own parents, possibly without) + else if (childInputMap.getParent() instanceof KeymapWrapper) + { + if (kw == null) + childInputMap.setParent(childInputMap.getParent().getParent()); + else + { + kw.setParent(childInputMap.getParent().getParent()); + childInputMap.setParent(kw); + } + } + + // option 3: there is an InputMapUIResource in the chain, which marks + // the place where we need to stop and insert ourselves + else if (childInputMap.getParent() instanceof InputMapUIResource) + { + if (kw != null) + { + kw.setParent(childInputMap.getParent()); + childInputMap.setParent(kw); + } + } + } + + // phase 2: replace the KeymapActionMap entry in the ActionMap chain + + KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k)); + ActionMap childActionMap = getActionMap(); + if (childActionMap == null) + setActionMap(kam); + else + { + while (childActionMap.getParent() != null + && !(childActionMap.getParent() instanceof KeymapActionMap) + && !(childActionMap.getParent() instanceof ActionMapUIResource)) + childActionMap = childActionMap.getParent(); + + // option 1: there is nobody to replace at the end of the chain + if (childActionMap.getParent() == null) + childActionMap.setParent(kam); + + // option 2: there is already a KeymapActionMap in the chain which + // needs replacing (possibly with its own parents, possibly without) + else if (childActionMap.getParent() instanceof KeymapActionMap) + { + if (kam == null) + childActionMap.setParent(childActionMap.getParent().getParent()); + else + { + kam.setParent(childActionMap.getParent().getParent()); + childActionMap.setParent(kam); + } + } + + // option 3: there is an ActionMapUIResource in the chain, which marks + // the place where we need to stop and insert ourselves + else if (childActionMap.getParent() instanceof ActionMapUIResource) + { + if (kam != null) + { + kam.setParent(childActionMap.getParent()); + childActionMap.setParent(kam); + } + } + } + + // phase 3: update the explicit keymap field + + Keymap old = keymap; + keymap = k; + firePropertyChange("keymap", old, k); + } + + /** + * Resolves a set of bindings against a set of actions and inserts the + * results into a {@link Keymap}. Specifically, for each provided binding + * b, if there exists a provided action a such + * that a.getValue(Action.NAME) == b.ActionName then an + * entry is added to the Keymap mapping b to + * a. + * + * @param map The Keymap to add new mappings to + * @param bindings The set of bindings to add to the Keymap + * @param actions The set of actions to resolve binding names against + * + * @see Action#NAME + * @see Action#getValue() + * @see KeyBinding#ActionName + */ + public static void loadKeymap(Keymap map, + JTextComponent.KeyBinding[] bindings, + Action[] actions) + { + Hashtable acts = new Hashtable(actions.length); + for (int i = 0; i < actions.length; ++i) + acts.put(actions[i].getValue(Action.NAME), actions[i]); + for (int i = 0; i < bindings.length; ++i) + if (acts.containsKey(bindings[i].actionName)) + map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName)); + } + + /** + * Returns the set of available Actions this component's associated + * editor can run. Equivalent to calling + * getUI().getEditorKit().getActions(). This set of Actions + * is a reasonable value to provide as a parameter to {@link + * #loadKeymap()}, when resolving a set of {@link #KeyBinding} objects + * against this component. + * + * @return The set of available Actions on this component's {@link EditorKit} + * + * @see TextUI#getEditorKit() + * @see EditorKit#getActions() + */ + public Action[] getActions() + { + return getUI().getEditorKit(this).getActions(); + } + + // These are package-private to avoid an accessor method. + Document doc; + Caret caret; + boolean editable; + + private Highlighter highlighter; + private Color caretColor; + private Color disabledTextColor; + private Color selectedTextColor; + private Color selectionColor; + private Insets margin; + private boolean dragEnabled; + + /** + * Creates a new JTextComponent instance. + */ + public JTextComponent() + { + Keymap defkeymap = getKeymap(DEFAULT_KEYMAP); + boolean creatingKeymap = false; + if (defkeymap == null) + { + defkeymap = addKeymap(DEFAULT_KEYMAP, null); + defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction()); + creatingKeymap = true; + } + + caretBlinkTimer = new CaretBlinkTimer(); + + setFocusable(true); + setEditable(true); + enableEvents(AWTEvent.KEY_EVENT_MASK); + updateUI(); + + // need to do this after updateUI() + if (creatingKeymap) + loadKeymap(defkeymap, + new KeyBinding[] { + new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), + DefaultEditorKit.backwardAction), + new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), + DefaultEditorKit.forwardAction), + new KeyBinding(KeyStroke.getKeyStroke("typed \b"), + DefaultEditorKit.deletePrevCharAction), + new KeyBinding(KeyStroke.getKeyStroke("typed \u007f"), + DefaultEditorKit.deleteNextCharAction) + }, + getActions()); + } + + public void setDocument(Document newDoc) + { + Document oldDoc = doc; + doc = newDoc; + firePropertyChange("document", oldDoc, newDoc); + revalidate(); + repaint(); + } + + public Document getDocument() + { + return doc; + } + + /** + * Get the AccessibleContext of this object. + * + * @return an AccessibleContext object + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + public void setMargin(Insets m) + { + margin = m; + } + + public Insets getMargin() + { + return margin; + } + + public void setText(String text) + { + try + { + doc.remove(0, doc.getLength()); + doc.insertString(0, text, null); + } + catch (BadLocationException e) + { + // This can never happen. + } + } + + /** + * Retrieves the current text in this text document. + * + * @return the text + * + * @exception NullPointerException if the underlaying document is null + */ + public String getText() + { + if (doc == null) + return null; + + try + { + return doc.getText(0, doc.getLength()); + } + catch (BadLocationException e) + { + // This should never happen. + return ""; + } + } + + /** + * Retrieves a part of the current text in this document. + * + * @param offset the postion of the first character + * @param length the length of the text to retrieve + * + * @return the text + * + * @exception BadLocationException if arguments do not hold pre-conditions + */ + public String getText(int offset, int length) + throws BadLocationException + { + return getDocument().getText(offset, length); + } + + /** + * Retrieves the currently selected text in this text document. + * + * @return the selected text + * + * @exception NullPointerException if the underlaying document is null + */ + public String getSelectedText() + { + try + { + return doc.getText(getSelectionStart(), getSelectionEnd()); + } + catch (BadLocationException e) + { + // This should never happen. + return null; + } + } + + /** + * Returns a string that specifies the name of the Look and Feel class + * that renders this component. + * + * @return the string "TextComponentUI" + */ + public String getUIClassID() + { + return "TextComponentUI"; + } + + /** + * Returns a string representation of this JTextComponent. + */ + protected String paramString() + { + return "JTextComponent"; + } + + /** + * This method returns the label's UI delegate. + * + * @return The label's UI delegate. + */ + public TextUI getUI() + { + return (TextUI) ui; + } + + /** + * This method sets the label's UI delegate. + * + * @param ui The label's UI delegate. + */ + public void setUI(TextUI newUI) + { + super.setUI(newUI); + } + + /** + * This method resets the label's UI delegate to the default UI for the + * current look and feel. + */ + public void updateUI() + { + setUI((TextUI) UIManager.getUI(this)); + } + + public Dimension getPreferredScrollableViewportSize() + { + return getPreferredSize(); + } + + public int getScrollableUnitIncrement(Rectangle visible, int orientation, + int direction) + { + // We return 1/10 of the visible area as documented in Sun's API docs. + if (orientation == SwingConstants.HORIZONTAL) + return visible.width / 10; + else if (orientation == SwingConstants.VERTICAL) + return visible.height / 10; + else + throw new IllegalArgumentException("orientation must be either " + + "javax.swing.SwingConstants.VERTICAL " + + "or " + + "javax.swing.SwingConstants.HORIZONTAL" + ); + } + + public int getScrollableBlockIncrement(Rectangle visible, int orientation, + int direction) + { + // We return the whole visible area as documented in Sun's API docs. + if (orientation == SwingConstants.HORIZONTAL) + return visible.width; + else if (orientation == SwingConstants.VERTICAL) + return visible.height; + else + throw new IllegalArgumentException("orientation must be either " + + "javax.swing.SwingConstants.VERTICAL " + + "or " + + "javax.swing.SwingConstants.HORIZONTAL" + ); + } + + /** + * Checks whether this text component it editable. + * + * @return true if editable, false otherwise + */ + public boolean isEditable() + { + return editable; + } + + /** + * Enables/disabled this text component's editability. + * + * @param newValue true to make it editable, false otherwise. + */ + public void setEditable(boolean newValue) + { + if (editable == newValue) + return; + + if (newValue == true) + caretBlinkTimer.start(); + else + { + caretBlinkTimer.stop(); + caret.setVisible(false); + } + + boolean oldValue = editable; + editable = newValue; + firePropertyChange("editable", oldValue, newValue); + } + + /** + * The Caret object used in this text component. + * + * @return the caret object + */ + public Caret getCaret() + { + return caret; + } + + /** + * Sets a new Caret for this text component. + * + * @param newCaret the new Caret to set + */ + public void setCaret(Caret newCaret) + { + if (caret != null) + caret.deinstall(this); + + Caret oldCaret = caret; + caret = newCaret; + + caretBlinkTimer.update(); + + if (caret != null) + caret.install(this); + + firePropertyChange("caret", oldCaret, newCaret); + } + + public Color getCaretColor() + { + return caretColor; + } + + public void setCaretColor(Color newColor) + { + Color oldCaretColor = caretColor; + caretColor = newColor; + firePropertyChange("caretColor", oldCaretColor, newColor); + } + + public Color getDisabledTextColor() + { + return disabledTextColor; + } + + public void setDisabledTextColor(Color newColor) + { + Color oldColor = disabledTextColor; + disabledTextColor = newColor; + firePropertyChange("disabledTextColor", oldColor, newColor); + } + + public Color getSelectedTextColor() + { + return selectedTextColor; + } + + public void setSelectedTextColor(Color newColor) + { + Color oldColor = selectedTextColor; + selectedTextColor = newColor; + firePropertyChange("selectedTextColor", oldColor, newColor); + } + + public Color getSelectionColor() + { + return selectionColor; + } + + public void setSelectionColor(Color newColor) + { + Color oldColor = selectionColor; + selectionColor = newColor; + firePropertyChange("selectionColor", oldColor, newColor); + } + + /** + * Retrisves the current caret position. + * + * @return the current position + */ + public int getCaretPosition() + { + return caret.getDot(); + } + + /** + * Sets the caret to a new position. + * + * @param position the new position + */ + public void setCaretPosition(int position) + { + if (doc == null) + return; + + if (position < 0 || position > doc.getLength()) + throw new IllegalArgumentException(); + + caret.setDot(position); + } + + /** + * Moves the caret to a given position. This selects the text between + * the old and the new position of the caret. + */ + public void moveCaretPosition(int position) + { + if (doc == null) + return; + + if (position < 0 || position > doc.getLength()) + throw new IllegalArgumentException(); + + caret.moveDot(position); + } + + public Highlighter getHighlighter() + { + return highlighter; + } + + public void setHighlighter(Highlighter newHighlighter) + { + if (highlighter != null) + highlighter.deinstall(this); + + Highlighter oldHighlighter = highlighter; + highlighter = newHighlighter; + + if (highlighter != null) + highlighter.install(this); + + firePropertyChange("highlighter", oldHighlighter, newHighlighter); + } + + /** + * Returns the start postion of the currently selected text. + * + * @return the start postion + */ + public int getSelectionStart() + { + return Math.min(caret.getDot(), caret.getMark()); + } + + /** + * Selects the text from the given postion to the selection end position. + * + * @param end the start positon of the selected text. + */ + public void setSelectionStart(int start) + { + select(start, getSelectionEnd()); + } + + /** + * Returns the end postion of the currently selected text. + * + * @return the end postion + */ + public int getSelectionEnd() + { + return Math.max(caret.getDot(), caret.getMark()); + } + + /** + * Selects the text from the selection start postion to the given position. + * + * @param end the end positon of the selected text. + */ + public void setSelectionEnd(int end) + { + select(getSelectionStart(), end); + } + + /** + * Selects a part of the content of the text component. + * + * @param start the start position of the selected text + * @param ent the end position of the selected text + */ + public void select(int start, int end) + { + int length = doc.getLength(); + + start = Math.max(start, 0); + start = Math.min(start, length); + + end = Math.max(end, 0); + end = Math.min(end, length); + + setCaretPosition(start); + moveCaretPosition(end); + } + + /** + * Selects the whole content of the text component. + */ + public void selectAll() + { + select(0, doc.getLength()); + } + + public synchronized void replaceSelection(String content) + { + int dot = caret.getDot(); + int mark = caret.getMark(); + + // If content is empty delete selection. + if (content == null) + { + 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()); + } + catch (BadLocationException e) + { + // This should never happen. + } + } + + public boolean getScrollableTracksViewportHeight() + { + if (getParent() instanceof JViewport) + return ((JViewport) getParent()).getHeight() > getPreferredSize().height; + + return false; + } + + public boolean getScrollableTracksViewportWidth() + { + if (getParent() instanceof JViewport) + return ((JViewport) getParent()).getWidth() > getPreferredSize().width; + + return false; + } + + /** + * Adds a CaretListener object to this text component. + * + * @param listener the listener to add + */ + public void addCaretListener(CaretListener listener) + { + listenerList.add(CaretListener.class, listener); + } + + /** + * Removed a CaretListener object from this text component. + * + * @param listener the listener to remove + */ + public void removeCaretListener(CaretListener listener) + { + listenerList.remove(CaretListener.class, listener); + } + + /** + * Returns all added CaretListener objects. + * + * @return an array of listeners + */ + public CaretListener[] getCaretListeners() + { + return (CaretListener[]) getListeners(CaretListener.class); + } + + /** + * Notifies all registered CaretListener objects that the caret + * was updated. + * + * @param event the event to send + */ + protected void fireCaretUpdate(CaretEvent event) + { + CaretListener[] listeners = getCaretListeners(); + + for (int index = 0; index < listeners.length; ++index) + listeners[index].caretUpdate(event); + } + + /** + * Adds an InputListener object to this text component. + * + * @param listener the listener to add + */ + public void addInputMethodListener(InputMethodListener listener) + { + listenerList.add(InputMethodListener.class, listener); + } + + /** + * Removes an InputListener object from this text component. + * + * @param listener the listener to remove + */ + public void removeInputMethodListener(InputMethodListener listener) + { + listenerList.remove(InputMethodListener.class, listener); + } + + /** + * Returns all added InputMethodListener objects. + * + * @return an array of listeners + */ + public InputMethodListener[] getInputMethodListeners() + { + return (InputMethodListener[]) getListeners(InputMethodListener.class); + } + + public Rectangle modelToView(int position) throws BadLocationException + { + return getUI().modelToView(this, position); + } + + public boolean getDragEnabled() + { + return dragEnabled; + } + + public void setDragEnabled(boolean enabled) + { + dragEnabled = enabled; + } + + public int viewToModel(Point pt) + { + return getUI().viewToModel(this, pt); + } + + public void copy() + { + doTransferAction("copy", TransferHandler.getCopyAction()); + } + + public void cut() + { + doTransferAction("cut", TransferHandler.getCutAction()); + } + + public void paste() + { + doTransferAction("paste", TransferHandler.getPasteAction()); + } + + private void doTransferAction(String name, Action action) + { + // Install default TransferHandler if none set. + if (getTransferHandler() == null) + { + if (defaultTransferHandler == null) + defaultTransferHandler = new DefaultTransferHandler(); + + setTransferHandler(defaultTransferHandler); + } + + // Perform action. + ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, + action.getValue(Action.NAME).toString()); + action.actionPerformed(event); + } + + public void setFocusAccelerator(char newKey) + { + if (focusAccelerator == newKey) + return; + + char oldKey = focusAccelerator; + focusAccelerator = newKey; + firePropertyChange(FOCUS_ACCELERATOR_KEY, oldKey, newKey); + } + + public char getFocusAccelerator() + { + return focusAccelerator; + } + + /** + * @since 1.4 + */ + public NavigationFilter getNavigationFilter() + { + return navigationFilter; + } + + /** + * @since 1.4 + */ + public void setNavigationFilter(NavigationFilter filter) + { + navigationFilter = filter; + } + + /** + * Read and set the content this component. If not overridden, the + * method reads the component content as a plain text. + * + * The second parameter of this method describes the input stream. It can + * be String, URL, File and so on. If not null, this object is added to + * the properties of the associated document under the key + * {@link Document#StreamDescriptionProperty}. + * + * @param input an input stream to read from. + * @param streamDescription an object, describing the stream. + * + * @throws IOException if the reader throws it. + * + * @see getDocument() + * @see Document#getProperty(Object) + */ + public void read(Reader input, Object streamDescription) + throws IOException + { + if (streamDescription != null) + { + Document d = getDocument(); + if (d != null) + d.putProperty(Document.StreamDescriptionProperty, streamDescription); + } + + StringBuffer b = new StringBuffer(); + int c; + + // Read till -1 (EOF). + while ((c = input.read()) >= 0) + b.append((char) c); + + setText(b.toString()); + } + + /** + * Write the content of this component to the given stream. If not + * overridden, the method writes the component content as a plain text. + * + * @param output the writer to write into. + * + * @throws IOException if the writer throws it. + */ + public void write(Writer output) + throws IOException + { + output.write(getText()); + } +} diff --git a/libjava/classpath/javax/swing/text/Keymap.java b/libjava/classpath/javax/swing/text/Keymap.java new file mode 100644 index 0000000..c3f61d8 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Keymap.java @@ -0,0 +1,60 @@ +/* Keymap.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import javax.swing.Action; +import javax.swing.KeyStroke; + +public interface Keymap +{ + void addActionForKeyStroke(KeyStroke key, Action a); + Action getAction(KeyStroke key); + Action[] getBoundActions(); + KeyStroke[] getBoundKeyStrokes(); + Action getDefaultAction(); + KeyStroke[] getKeyStrokesForAction(Action a); + String getName(); + Keymap getResolveParent(); + boolean isLocallyDefined(KeyStroke key); + void removeBindings(); + void removeKeyStrokeBinding(KeyStroke keys); + void setDefaultAction(Action a); + void setResolveParent(Keymap parent); +} + + diff --git a/libjava/classpath/javax/swing/text/LayeredHighlighter.java b/libjava/classpath/javax/swing/text/LayeredHighlighter.java new file mode 100644 index 0000000..dcaf1c50 --- /dev/null +++ b/libjava/classpath/javax/swing/text/LayeredHighlighter.java @@ -0,0 +1,57 @@ +/* LayeredHighlighter.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.awt.Graphics; +import java.awt.Shape; + +public abstract class LayeredHighlighter + implements Highlighter +{ + public abstract static class LayerPainter + implements Highlighter.HighlightPainter + { + public abstract Shape paintLayer(Graphics g, int p0, int p1, + Shape viewBounds, JTextComponent editor, + View view); + } + + public abstract void paintLayeredHighlights(Graphics g, int p0, int p1, + Shape viewBounds, + JTextComponent editor, View view); +} diff --git a/libjava/classpath/javax/swing/text/MutableAttributeSet.java b/libjava/classpath/javax/swing/text/MutableAttributeSet.java new file mode 100644 index 0000000..2fe9ad5 --- /dev/null +++ b/libjava/classpath/javax/swing/text/MutableAttributeSet.java @@ -0,0 +1,85 @@ +/* MutableAttributeSet.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.util.Enumeration; + +/** + * MutableAttributeSet + * @author Andrew Selkirk + * @version 1.0 + */ +public interface MutableAttributeSet extends AttributeSet +{ + /** + * addAttribute + * @param name TODO + * @param value TODO + */ + void addAttribute(Object name, Object value); + + /** + * addAttributes + * @param attributes TODO + */ + void addAttributes(AttributeSet attributes); + + /** + * removeAttribute + * @param name TODO + */ + void removeAttribute(Object name); + + /** + * removeAttributes + * @param names TODO + */ + void removeAttributes(Enumeration names); + + /** + * removeAttributes + * @param attributes TODO + */ + void removeAttributes(AttributeSet attributes); + + /** + * setResolveParent + * @param parent TODO + */ + void setResolveParent(AttributeSet parent); +} diff --git a/libjava/classpath/javax/swing/text/NavigationFilter.java b/libjava/classpath/javax/swing/text/NavigationFilter.java new file mode 100644 index 0000000..45f58f9 --- /dev/null +++ b/libjava/classpath/javax/swing/text/NavigationFilter.java @@ -0,0 +1,71 @@ +/* NavigationFilter.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +public class NavigationFilter +{ + public abstract static class FilterBypass + { + public FilterBypass() + { + // Do nothing here. + } + + public abstract Caret getCaret(); + public abstract void moveDot(int dot, Position.Bias bias); + public abstract void setDot(int dot, Position.Bias bias); + } + + public NavigationFilter() + { + // Do nothing here. + } + + public void moveDot(NavigationFilter.FilterBypass fb, int dot, + Position.Bias bias) + { + fb.moveDot(dot, bias); + } + + public void setDot(NavigationFilter.FilterBypass fb, int dot, + Position.Bias bias) + { + fb.setDot(dot, bias); + } +} diff --git a/libjava/classpath/javax/swing/text/PasswordView.java b/libjava/classpath/javax/swing/text/PasswordView.java new file mode 100644 index 0000000..229fd2b --- /dev/null +++ b/libjava/classpath/javax/swing/text/PasswordView.java @@ -0,0 +1,170 @@ +/* PasswordView.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Graphics; + +import javax.swing.JPasswordField; + +public class PasswordView extends FieldView +{ + /** + * Buffer for putting the echo char into it and + * then using it to draw it into the view. + */ + private char[] oneCharBuffer = new char[1]; + + public PasswordView(Element elem) + { + super(elem); + } + + /** + * Draws one echo character at a given position. + * + * @param g the Graphics object to draw to + * @param x the x-position + * @param y the y-position + * @param ch the echo character + * + * @return the next x position right of the drawn character + */ + protected int drawEchoCharacter(Graphics g, int x, int y, char ch) + { + // Update font metrics. + updateMetrics(); + + // Draw character. + oneCharBuffer[0] = ch; + g.drawChars(oneCharBuffer, 0, 1, x, y); + + // Return new x position right of drawn character. + return x + metrics.charWidth(ch); + } + + private char getEchoChar() + { + char ch = ((JPasswordField) getContainer()).getEchoChar(); + + if (ch == 0) + ch = '*'; + + return ch; + } + + /** + * Draws selected text at a given position. + * + * @param g the Graphics object to draw to + * @param x the x-position + * @param y the y-position + * @param p0 the position of the first character to draw + * @param p1 the position of the first character not to draw + * + * @return the next x position right of the drawn character + */ + protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1) + throws BadLocationException + { + // FIXME: Throw BadLocationException somehow. + + // Update font metrics. + updateMetrics(); + + // Get echo character. + char ch = getEchoChar(); + + // Set color for selected text. + g.setColor(selectedColor); + g.setColor(Color.BLACK); + + // Initialize buffer for faster drawing of all characters. + int len = p1 - p0; + char[] buffer = new char[len]; + for (int index = 0; index < len; ++index) + buffer[index] = ch; + + // Draw echo charaters. + g.drawChars(buffer, 0, len, x, y); + + // Return new x position right of all drawn characters. + return x + len * metrics.charWidth(ch); + } + + /** + * Draws unselected text at a given position. + * + * @param g the Graphics object to draw to + * @param x the x-position + * @param y the y-position + * @param p0 the position of the first character to draw + * @param p1 the position of the first character not to draw + * + * @return the next x position right of the drawn character + */ + protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1) + throws BadLocationException + { + // FIXME: Throw BadLocationException somehow. + + // Update font metrics. + updateMetrics(); + + // Get echo character. + char ch = getEchoChar(); + + // Set color for unselected text. + g.setColor(unselectedColor); + g.setColor(Color.BLACK); + + // Initialize buffer for faster drawing of all characters. + int len = p1 - p0; + char[] buffer = new char[len]; + for (int index = 0; index < len; ++index) + buffer[index] = ch; + + // Draw echo charaters. + g.drawChars(buffer, 0, len, x, y); + + // Return new x position right of all drawn characters. + return x + len * metrics.charWidth(ch); + } +} + diff --git a/libjava/classpath/javax/swing/text/PlainDocument.java b/libjava/classpath/javax/swing/text/PlainDocument.java new file mode 100644 index 0000000..c3f59e4 --- /dev/null +++ b/libjava/classpath/javax/swing/text/PlainDocument.java @@ -0,0 +1,166 @@ +/* PlainDocument.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.util.ArrayList; + +public class PlainDocument extends AbstractDocument +{ + private static final long serialVersionUID = 4758290289196893664L; + + public static final String lineLimitAttribute = "lineLimit"; + public static final String tabSizeAttribute = "tabSize"; + + private BranchElement rootElement; + private int tabSize; + + public PlainDocument() + { + this(new GapContent()); + } + + public PlainDocument(AbstractDocument.Content content) + { + super(content); + tabSize = 8; + rootElement = (BranchElement) createDefaultRoot(); + } + + private void reindex() + { + Element[] lines; + try + { + String str = content.getString(0, content.length()); + + ArrayList elts = new ArrayList(); + int j = 0; + for (int i = str.indexOf('\n', 0); i != -1; i = str.indexOf('\n', i + 1)) + { + elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, i + 1)); + j = i + 1; + } + + if (j < content.length()) + elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, content.length())); + + lines = new Element[elts.size()]; + for (int i = 0; i < elts.size(); ++i) + lines[i] = (Element) elts.get(i); + } + catch (BadLocationException e) + { + lines = new Element[1]; + lines[0] = createLeafElement(rootElement, SimpleAttributeSet.EMPTY, 0, 1); + } + + ((BranchElement) rootElement).replace(0, rootElement.getElementCount(), lines); + } + + protected AbstractDocument.AbstractElement createDefaultRoot() + { + BranchElement root = + (BranchElement) createBranchElement(null, SimpleAttributeSet.EMPTY); + + Element[] array = new Element[1]; + array[0] = createLeafElement(root, SimpleAttributeSet.EMPTY, 0, 1); + root.replace(0, 0, array); + + return root; + } + + protected void insertUpdate(DefaultDocumentEvent event, AttributeSet attributes) + { + reindex(); + + super.insertUpdate(event, attributes); + } + + protected void removeUpdate(DefaultDocumentEvent event) + { + super.removeUpdate(event); + + int p0 = event.getOffset(); + int len = event.getLength(); + int p1 = len + p0; + + // check if we must collapse some elements + int i1 = rootElement.getElementIndex(p0); + int i2 = rootElement.getElementIndex(p1); + if (i1 != i2) + { + Element el1 = rootElement.getElement(i1); + Element el2 = rootElement.getElement(i2); + int start = el1.getStartOffset(); + int end = el2.getEndOffset(); + // 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 }); + } + else + { + // otherwise only adjust indices of the element + LeafElement el1 = (LeafElement) rootElement.getElement(i1); + el1.end -= len; + } + + // reindex remaining elements + for (int i = rootElement.getElementIndex(p0) + 1; + i < rootElement.getElementCount(); i++) + { + LeafElement el = (LeafElement) rootElement.getElement(i); + el.start -= len; + el.end -= len; + } + + } + + public Element getDefaultRootElement() + { + return rootElement; + } + + public Element getParagraphElement(int pos) + { + Element root = getDefaultRootElement(); + return root.getElement(root.getElementIndex(pos)); + } +} diff --git a/libjava/classpath/javax/swing/text/PlainView.java b/libjava/classpath/javax/swing/text/PlainView.java new file mode 100644 index 0000000..5d1fab0 --- /dev/null +++ b/libjava/classpath/javax/swing/text/PlainView.java @@ -0,0 +1,241 @@ +/* PlainView.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; + +public class PlainView extends View + implements TabExpander +{ + Color selectedColor; + Color unselectedColor; + Font font; + + protected FontMetrics metrics; + + public PlainView(Element elem) + { + super(elem); + } + + /** + * @since 1.4 + */ + protected void updateMetrics() + { + Component component = getContainer(); + Font font = component.getFont(); + + if (this.font != font) + { + this.font = font; + metrics = component.getFontMetrics(font); + } + } + + /** + * @since 1.4 + */ + protected Rectangle lineToRect(Shape a, int line) + { + // Ensure metrics are up-to-date. + updateMetrics(); + + Rectangle rect = a.getBounds(); + int fontHeight = metrics.getHeight(); + return new Rectangle(rect.x, rect.y + (line * fontHeight), + rect.width, fontHeight); + } + + public Shape modelToView(int position, Shape a, Position.Bias b) + throws BadLocationException + { + // Ensure metrics are up-to-date. + updateMetrics(); + + Document document = getDocument(); + + // Get rectangle of the line containing position. + int lineIndex = getElement().getElementIndex(position); + Rectangle rect = lineToRect(a, lineIndex); + + // Get the rectangle for position. + Element line = getElement().getElement(lineIndex); + int lineStart = line.getStartOffset(); + Segment segment = new Segment(); + document.getText(lineStart, position - lineStart, segment); + int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x, + this, lineStart); + + // Calc the real rectangle. + rect.x += xoffset; + rect.width = 1; + rect.height = metrics.getHeight(); + + return rect; + } + + protected void drawLine(int lineIndex, Graphics g, int x, int y) + { + try + { + metrics = g.getFontMetrics(); + // FIXME: Selected text are not drawn yet. + Element line = getElement().getElement(lineIndex); + drawUnselectedText(g, x, y, line.getStartOffset(), line.getEndOffset()); + //drawSelectedText(g, , , , ); + } + catch (BadLocationException e) + { + // This should never happen. + } + } + + protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1) + throws BadLocationException + { + g.setColor(selectedColor); + Segment segment = new Segment(); + getDocument().getText(p0, p1 - p0, segment); + return Utilities.drawTabbedText(segment, x, y, g, this, 0); + } + + protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1) + throws BadLocationException + { + g.setColor(unselectedColor); + Segment segment = new Segment(); + getDocument().getText(p0, p1 - p0, segment); + return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset); + } + + 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(); + + Rectangle rect = s.getBounds(); + + // FIXME: Text may be scrolled. + Document document = textComponent.getDocument(); + Element root = document.getDefaultRootElement(); + int y = rect.y; + + for (int i = 0; i < root.getElementCount(); i++) + { + drawLine(i, g, rect.x, y); + y += metrics.getHeight(); + } + } + + protected int getTabSize() + { + return 8; + } + + /** + * Returns the next tab stop position after a given reference position. + * + * This implementation ignores the tabStop 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) + { + float tabSizePixels = getTabSize() + metrics.charWidth('m'); + return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels; + } + + public float getPreferredSpan(int axis) + { + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException(); + + // make sure we have the metrics + updateMetrics(); + + 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; + case Y_AXIS: + default: + span = metrics.getHeight() * el.getElementCount(); + break; + } + + return span; + } +} + diff --git a/libjava/classpath/javax/swing/text/Position.java b/libjava/classpath/javax/swing/text/Position.java new file mode 100644 index 0000000..a9d3d09 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Position.java @@ -0,0 +1,62 @@ +/* Position.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + + +public interface Position +{ + static class Bias + { + public static final Bias Backward = new Bias("backward"); + public static final Bias Forward = new Bias("forward"); + + private String name; + + private Bias(String n) + { + name = n; + } + + public String toString() + { + return name; + } + } + + int getOffset(); +} diff --git a/libjava/classpath/javax/swing/text/Segment.java b/libjava/classpath/javax/swing/text/Segment.java new file mode 100644 index 0000000..92d8500 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Segment.java @@ -0,0 +1,176 @@ +/* Segment.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.text.CharacterIterator; + +public class Segment + implements Cloneable, CharacterIterator +{ + private boolean partialReturn; + private int current; + + public char[] array; + public int count; + public int offset; + + public Segment() + { + } + + public Segment(char[] array, int offset, int count) + { + this.array = array; + this.offset = offset; + this.count = count; + } + + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + return null; + } + } + + public char current() + { + if (count == 0 + || current >= getEndIndex()) + return DONE; + + return array[current]; + } + + public char first() + { + if (count == 0) + return DONE; + + current = getBeginIndex(); + return array[current]; + } + + public int getBeginIndex() + { + return offset; + } + + public int getEndIndex() + { + return offset + count; + } + + public int getIndex() + { + return current; + } + + public char last() + { + if (count == 0) + return DONE; + + current = getEndIndex() - 1; + return array[current]; + } + + public char next() + { + if (count == 0) + return DONE; + + if ((current + 1) >= getEndIndex()) + { + current = getEndIndex(); + return DONE; + } + + current++; + return array[current]; + } + + public char previous() + { + if (count == 0 + || current == getBeginIndex()) + return DONE; + + current--; + return array[current]; + } + + public char setIndex(int position) + { + if (position < getBeginIndex() + || position > getEndIndex()) + throw new IllegalArgumentException(); + + current = position; + + if (position == getEndIndex()) + return DONE; + + return array[current]; + } + + public String toString() + { + return new String(array, offset, count); + } + + /** + * @since 1.4 + */ + public void setPartialReturn(boolean p) + { + partialReturn = p; + } + + /** + * @since 1.4 + */ + public boolean isPartialReturn() + { + return partialReturn; + } +} diff --git a/libjava/classpath/javax/swing/text/SimpleAttributeSet.java b/libjava/classpath/javax/swing/text/SimpleAttributeSet.java new file mode 100644 index 0000000..3ef5db6 --- /dev/null +++ b/libjava/classpath/javax/swing/text/SimpleAttributeSet.java @@ -0,0 +1,193 @@ +/* SimpleAttributeSet.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Hashtable; + +public class SimpleAttributeSet + implements MutableAttributeSet, Serializable, Cloneable +{ + public static final AttributeSet EMPTY = new SimpleAttributeSet(); + + Hashtable tab; + + public SimpleAttributeSet() + { + this(null); + } + + public SimpleAttributeSet(AttributeSet a) + { + tab = new Hashtable(); + if (a != null) + addAttributes(a); + } + + public void addAttribute(Object name, Object value) + { + tab.put(name, value); + } + + public void addAttributes(AttributeSet attributes) + { + Enumeration e = attributes.getAttributeNames(); + while (e.hasMoreElements()) + { + Object name = e.nextElement(); + Object val = attributes.getAttribute(name); + tab.put(name, val); + } + } + + public Object clone() + { + SimpleAttributeSet s = new SimpleAttributeSet(); + s.tab = (Hashtable) tab.clone(); + return s; + } + + public boolean containsAttribute(Object name, Object value) + { + return tab.containsKey(name) + && tab.get(name).equals(value); + } + + public boolean containsAttributes(AttributeSet attributes) + { + Enumeration e = attributes.getAttributeNames(); + while (e.hasMoreElements()) + { + Object name = e.nextElement(); + Object val = attributes.getAttribute(name); + if (! containsAttribute(name, val)) + return false; + } + return true; + } + + public AttributeSet copyAttributes() + { + return (AttributeSet) clone(); + } + + public boolean equals(Object obj) + { + return (obj != null) + && (obj instanceof SimpleAttributeSet) + && ((SimpleAttributeSet)obj).tab.equals(this.tab); + } + + public Object getAttribute(Object name) + { + Object val = tab.get(name); + if (val != null) + return val; + + Object p = getResolveParent(); + if (p != null && p instanceof AttributeSet) + return (((AttributeSet)p).getAttribute(name)); + + return null; + } + + public int getAttributeCount() + { + return tab.size(); + } + + public Enumeration getAttributeNames() + { + return tab.keys(); + } + + public AttributeSet getResolveParent() + { + return (AttributeSet) tab.get(ResolveAttribute); + } + + public int hashCode() + { + return tab.hashCode(); + } + + public boolean isDefined(Object attrName) + { + return tab.containsKey(attrName); + } + + public boolean isEmpty() + { + return tab.isEmpty(); + } + + public boolean isEqual(AttributeSet attr) + { + return this.equals(attr); + } + + public void removeAttribute(Object name) + { + tab.remove(name); + } + + public void removeAttributes(AttributeSet attributes) + { + removeAttributes(attributes.getAttributeNames()); + } + + public void removeAttributes(Enumeration names) + { + while (names.hasMoreElements()) + { + removeAttribute(names.nextElement()); + } + } + + public void setResolveParent(AttributeSet parent) + { + addAttribute(ResolveAttribute, parent); + } + + public String toString() + { + return tab.toString(); + } +} diff --git a/libjava/classpath/javax/swing/text/StringContent.java b/libjava/classpath/javax/swing/text/StringContent.java new file mode 100644 index 0000000..bedf480 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StringContent.java @@ -0,0 +1,307 @@ +/* StringContent.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.io.Serializable; +import java.util.Iterator; +import java.util.Vector; + +import javax.swing.undo.AbstractUndoableEdit; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.UndoableEdit; + +/** + * An implementation of the AbstractDocument.Content + * interface useful for small documents or debugging. The character + * content is a simple character array. It's not really efficient. + * + *

Do not use this class for large size.

+ */ +public final class StringContent implements AbstractDocument.Content, Serializable +{ + // This is package-private to avoid an accessor method. + char[] content; + + private int count; + + private Vector positions = new Vector(); + + private class InsertUndo extends AbstractUndoableEdit + { + private int start; + + private int length; + + private String redoContent; + + public InsertUndo(int start, int length) + { + super(); + this.start = start; + this.length = length; + } + + public void undo() + { + super.undo(); + try + { + StringContent.this.checkLocation(this.start, this.length); + this.redoContent = new String(StringContent.this.content, this.start, this.length); + StringContent.this.remove(this.start, this.length); + } + catch (BadLocationException b) + { + throw new CannotUndoException(); + } + } + + public void redo() + { + super.redo(); + try + { + StringContent.this.insertString(this.start, this.redoContent); + } + catch (BadLocationException b) + { + throw new CannotRedoException(); + } + } + } + + private class RemoveUndo extends AbstractUndoableEdit + { + private int start; + + private String undoString; + + public RemoveUndo(int start, String str) + { + super(); + this.start = start; + this.undoString = str; + } + + public void undo() + { + super.undo(); + try + { + StringContent.this.insertString(this.start, this.undoString); + } + catch (BadLocationException bad) + { + throw new CannotUndoException(); + } + } + + public void redo() + { + super.redo(); + try + { + int end = this.undoString.length(); + StringContent.this.remove(this.start, end); + } + catch (BadLocationException bad) + { + throw new CannotRedoException(); + } + } + } + + private class StickyPosition implements Position + { + private int offset = -1; + + public StickyPosition(int offset) + { + this.offset = offset; + } + + // This is package-private to avoid an accessor method. + void setOffset(int offset) + { + this.offset = this.offset >= 0 ? offset : -1; + } + + /** + * Should be >=0. + */ + public int getOffset() + { + return offset < 0 ? 0 : offset; + } + } + + public StringContent() + { + this(1); + } + + public StringContent(int initialLength) + { + super(); + if (initialLength < 1) + initialLength = 1; + this.content = new char[initialLength]; + this.content[0] = '\n'; + this.count = 1; + } + + protected Vector getPositionsInRange(Vector v, + int offset, + int length) + { + Vector refPos = new Vector(); + Iterator iter = this.positions.iterator(); + while(iter.hasNext()) + { + Position p = (Position)iter.next(); + if ((offset <= p.getOffset()) + && (p.getOffset() <= (offset + length))) + refPos.add(p); + } + return refPos; + } + + public Position createPosition(int offset) throws BadLocationException + { + if (offset < this.count || offset > this.count) + checkLocation(offset, 0); + StickyPosition sp = new StickyPosition(offset); + this.positions.add(sp); + return sp; + } + + public int length() + { + return this.count; + } + + public UndoableEdit insertString(int where, String str) + throws BadLocationException + { + checkLocation(where, 0); + if (where == this.count) + throw new BadLocationException("Invalid location", 1); + if (str == null) + throw new NullPointerException(); + char[] insert = str.toCharArray(); + char[] temp = new char[this.content.length + insert.length]; + this.count += insert.length; + // Copy array and insert the string. + if (where > 0) + System.arraycopy(this.content, 0, temp, 0, where); + System.arraycopy(insert, 0, temp, where, insert.length); + System.arraycopy(this.content, where, temp, (where + insert.length), (temp.length - where - insert.length)); + if (this.content.length < temp.length) + this.content = new char[temp.length]; + // Copy the result in the original char array. + System.arraycopy(temp, 0, this.content, 0, temp.length); + // Move all the positions. + Vector refPos = getPositionsInRange(this.positions, where, temp.length - where); + Iterator iter = refPos.iterator(); + while (iter.hasNext()) + { + StickyPosition p = (StickyPosition)iter.next(); + p.setOffset(p.getOffset() + str.length()); + } + InsertUndo iundo = new InsertUndo(where, insert.length); + return iundo; + } + + public UndoableEdit remove(int where, int nitems) throws BadLocationException + { + checkLocation(where, nitems); + char[] temp = new char[(this.content.length - nitems)]; + this.count = this.count - nitems; + RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, nitems)); + // Copy array. + System.arraycopy(this.content, 0, temp, 0, where); + System.arraycopy(this.content, where + nitems, temp, where, this.content.length - where - nitems); + this.content = new char[temp.length]; + // Then copy the result in the original char array. + System.arraycopy(temp, 0, this.content, 0, this.content.length); + // Move all the positions. + Vector refPos = getPositionsInRange(this.positions, where, this.content.length + nitems - where); + Iterator iter = refPos.iterator(); + while (iter.hasNext()) + { + StickyPosition p = (StickyPosition)iter.next(); + int result = p.getOffset() - nitems; + p.setOffset(result); + if (result < 0) + this.positions.remove(p); + } + return rundo; + } + + public String getString(int where, int len) throws BadLocationException + { + checkLocation(where, len); + return new String (this.content, where, len); + } + + public void getChars(int where, int len, Segment txt) throws BadLocationException + { + checkLocation(where, len); + if (txt != null) + { + txt.array = this.content; + txt.offset = where; + txt.count = len; + } + } + + // This is package-private to avoid an accessor method. + void checkLocation(int where, int len) throws BadLocationException + { + if (where < 0) + throw new BadLocationException("Invalid location", 1); + else if (where > this.count) + throw new BadLocationException("Invalid location", this.count); + else if ((where + len)>this.count) + throw new BadLocationException("Invalid range", this.count); + } + +} + diff --git a/libjava/classpath/javax/swing/text/Style.java b/libjava/classpath/javax/swing/text/Style.java new file mode 100644 index 0000000..851ac02 --- /dev/null +++ b/libjava/classpath/javax/swing/text/Style.java @@ -0,0 +1,64 @@ +/* Style.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import javax.swing.event.ChangeListener; + +public interface Style extends MutableAttributeSet +{ + /** + * Returns the name of the style. + * + * @return the name + */ + String getName(); + + /** + * Adds a ChangeListener object to the style. + * + * @param listener the listener object to add + */ + void addChangeListener(ChangeListener listener); + + /** + * Removes a ChangeListener from to the style. + * + * @param listener the listener object to remove, + */ + void removeChangeListener(ChangeListener listener); +} diff --git a/libjava/classpath/javax/swing/text/StyleConstants.java b/libjava/classpath/javax/swing/text/StyleConstants.java new file mode 100644 index 0000000..3f973f2 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StyleConstants.java @@ -0,0 +1,443 @@ +/* StyleConstants.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.Icon; + +public class StyleConstants +{ + public static final int ALIGN_LEFT = 0; + public static final int ALIGN_CENTER = 1; + public static final int ALIGN_RIGHT = 2; + public static final int ALIGN_JUSTIFIED = 3; + + public static final Object Background = CharacterConstants.Background; + 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 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 StrikeThrough = CharacterConstants.StrikeThrough; + public static final Object Subscript = CharacterConstants.Subscript; + public static final Object Superscript = CharacterConstants.Superscript; + public static final Object Underline = CharacterConstants.Underline; + + public static final Object Alignment = ParagraphConstants.Alignment; + public static final Object FirstLineIndent = ParagraphConstants.FirstLineIndent; + public static final Object LeftIndent = ParagraphConstants.LeftIndent; + public static final Object LineSpacing = ParagraphConstants.LineSpacing; + public static final Object Orientation = ParagraphConstants.Orientation; + public static final Object RightIndent = ParagraphConstants.RightIndent; + public static final Object SpaceAbove = ParagraphConstants.SpaceAbove; + public static final Object SpaceBelow = ParagraphConstants.SpaceBelow; + public static final Object TabSet = ParagraphConstants.TabSet; + + public static final String ComponentElementName = "component"; + public static final String IconElementName = "icon"; + + public static final Object ComposedTextAttribute = new StyleConstants("composed text"); + public static final Object ModelAttribute = new StyleConstants("model"); + public static final Object NameAttribute = new StyleConstants("name"); + public static final Object ResolveAttribute = new StyleConstants("resolver"); + + String keyname; + + // Package-private to avoid accessor constructor for use by + // subclasses. + StyleConstants(String k) + { + keyname = k; + } + + public String toString() + { + return keyname; + } + + public static int getAlignment(AttributeSet a) + { + if (a.isDefined(Alignment)) + return ((Integer)a.getAttribute(Alignment)).intValue(); + else + return ALIGN_LEFT; + } + + public static Color getBackground(AttributeSet a) + { + if (a.isDefined(Background)) + return (Color) a.getAttribute(Background); + else + return Color.BLACK; + } + + public static int getBidiLevel(AttributeSet a) + { + if (a.isDefined(BidiLevel)) + return ((Integer)a.getAttribute(BidiLevel)).intValue(); + else + return 0; + } + + public static Component getComponent(AttributeSet a) + { + if (a.isDefined(ComponentAttribute)) + return (Component) a.getAttribute(ComponentAttribute); + else + return (Component) null; + } + + public static float getFirstLineIndent(AttributeSet a) + { + if (a.isDefined(FirstLineIndent)) + return ((Float)a.getAttribute(FirstLineIndent)).floatValue(); + else + return 0.f; + } + + public static String getFontFamily(AttributeSet a) + { + if (a.isDefined(FontFamily)) + return (String) a.getAttribute(FontFamily); + else + return "Monospaced"; + } + + public static int getFontSize(AttributeSet a) + { + if (a.isDefined(FontSize)) + return ((Integer)a.getAttribute(FontSize)).intValue(); + else + return 12; + } + + public static Color getForeground(AttributeSet a) + { + if (a.isDefined(Foreground)) + return (Color) a.getAttribute(Foreground); + else + return Color.BLACK; + } + + public static Icon getIcon(AttributeSet a) + { + if (a.isDefined(IconAttribute)) + return (Icon) a.getAttribute(IconAttribute); + else + return (Icon) null; + } + + public static float getLeftIndent(AttributeSet a) + { + if (a.isDefined(LeftIndent)) + return ((Float)a.getAttribute(LeftIndent)).floatValue(); + else + return 0.f; + } + + public static float getLineSpacing(AttributeSet a) + { + if (a.isDefined(LineSpacing)) + return ((Float)a.getAttribute(LineSpacing)).floatValue(); + else + return 0.f; + } + + public static float getRightIndent(AttributeSet a) + { + if (a.isDefined(RightIndent)) + return ((Float)a.getAttribute(RightIndent)).floatValue(); + else + return 0.f; + } + + public static float getSpaceAbove(AttributeSet a) + { + if (a.isDefined(SpaceAbove)) + return ((Float)a.getAttribute(SpaceAbove)).floatValue(); + else + return 0.f; + } + + public static float getSpaceBelow(AttributeSet a) + { + if (a.isDefined(SpaceBelow)) + return ((Float)a.getAttribute(SpaceBelow)).floatValue(); + else + return 0.f; + } + + public static javax.swing.text.TabSet getTabSet(AttributeSet a) + { + if (a.isDefined(StyleConstants.TabSet)) + return (javax.swing.text.TabSet) a.getAttribute(StyleConstants.TabSet); + else + return (javax.swing.text.TabSet) null; + } + + public static boolean isBold(AttributeSet a) + { + if (a.isDefined(Bold)) + return ((Boolean) a.getAttribute(Bold)).booleanValue(); + else + return false; + } + + public static boolean isItalic(AttributeSet a) + { + if (a.isDefined(Italic)) + return ((Boolean) a.getAttribute(Italic)).booleanValue(); + else + return false; + } + + public static boolean isStrikeThrough(AttributeSet a) + { + if (a.isDefined(StrikeThrough)) + return ((Boolean) a.getAttribute(StrikeThrough)).booleanValue(); + else + return false; + } + + public static boolean isSubscript(AttributeSet a) + { + if (a.isDefined(Subscript)) + return ((Boolean) a.getAttribute(Subscript)).booleanValue(); + else + return false; + } + + public static boolean isSuperscript(AttributeSet a) + { + if (a.isDefined(Superscript)) + return ((Boolean) a.getAttribute(Superscript)).booleanValue(); + else + return false; + } + + public static boolean isUnderline(AttributeSet a) + { + if (a.isDefined(Underline)) + return ((Boolean) a.getAttribute(Underline)).booleanValue(); + else + return false; + } + + public static void setAlignment(MutableAttributeSet a, int align) + { + a.addAttribute(Alignment, new Integer(align)); + } + + public static void setBackground(MutableAttributeSet a, Color fg) + { + a.addAttribute(Background, fg); + } + + public static void setBidiLevel(MutableAttributeSet a, int lev) + { + a.addAttribute(BidiLevel, new Integer(lev)); + } + + public static void setBold(MutableAttributeSet a, boolean b) + { + a.addAttribute(Bold, Boolean.valueOf(b)); + } + + public static void setComponent(MutableAttributeSet a, Component c) + { + a.addAttribute(ComponentAttribute, c); + } + + public static void setFirstLineIndent(MutableAttributeSet a, float i) + { + a.addAttribute(FirstLineIndent, new Float(i)); + } + + public static void setFontFamily(MutableAttributeSet a, String fam) + { + a.addAttribute(FontFamily, fam); + } + + public static void setFontSize(MutableAttributeSet a, int s) + { + a.addAttribute(FontSize, new Integer(s)); + } + + public static void setForeground(MutableAttributeSet a, Color fg) + { + a.addAttribute(Foreground, fg); + } + + public static void setIcon(MutableAttributeSet a, Icon c) + { + a.addAttribute(IconAttribute, c); + } + + public static void setItalic(MutableAttributeSet a, boolean b) + { + a.addAttribute(Italic, Boolean.valueOf(b)); + } + + public static void setLeftIndent(MutableAttributeSet a, float i) + { + a.addAttribute(LeftIndent, new Float(i)); + } + + public static void setLineSpacing(MutableAttributeSet a, float i) + { + a.addAttribute(LineSpacing, new Float(i)); + } + + public static void setRightIndent(MutableAttributeSet a, float i) + { + a.addAttribute(RightIndent, new Float(i)); + } + + public static void setSpaceAbove(MutableAttributeSet a, float i) + { + a.addAttribute(SpaceAbove, new Float(i)); + } + + public static void setSpaceBelow(MutableAttributeSet a, float i) + { + a.addAttribute(SpaceBelow, new Float(i)); + } + + public static void setStrikeThrough(MutableAttributeSet a, boolean b) + { + a.addAttribute(StrikeThrough, Boolean.valueOf(b)); + } + + public static void setSubscript(MutableAttributeSet a, boolean b) + { + a.addAttribute(Subscript, Boolean.valueOf(b)); + } + + public static void setSuperscript(MutableAttributeSet a, boolean b) + { + a.addAttribute(Superscript, Boolean.valueOf(b)); + } + + public static void setTabSet(MutableAttributeSet a, javax.swing.text.TabSet tabs) + { + a.addAttribute(StyleConstants.TabSet, tabs); + } + + public static void setUnderline(MutableAttributeSet a, boolean b) + { + a.addAttribute(Underline, Boolean.valueOf(b)); + } + + // The remainder are so-called "typesafe enumerations" which + // alias subsets of the above constants. + public static class CharacterConstants + extends StyleConstants + implements AttributeSet.CharacterAttribute + { + private CharacterConstants(String k) + { + super(k); + } + + public static Object Background = ColorConstants.Background; + public static Object BidiLevel = new CharacterConstants("bidiLevel"); + public static Object Bold = FontConstants.Bold; + public static Object ComponentAttribute = new CharacterConstants("component"); + public static Object Family = FontConstants.Family; + public static Object Size = FontConstants.Size; + public static Object Foreground = ColorConstants.Foreground; + public static Object IconAttribute = new CharacterConstants("icon"); + public static Object Italic = FontConstants.Italic; + public static Object StrikeThrough = new CharacterConstants("strikethrough"); + public static Object Subscript = new CharacterConstants("subscript"); + public static Object Superscript = new CharacterConstants("superscript"); + public static Object Underline = new CharacterConstants("underline"); + } + + public static class ColorConstants + extends StyleConstants + implements AttributeSet.ColorAttribute, AttributeSet.CharacterAttribute + { + private ColorConstants(String k) + { + super(k); + } + public static Object Foreground = new ColorConstants("foreground"); + public static Object Background = new ColorConstants("background"); + } + + public static class FontConstants + extends StyleConstants + implements AttributeSet.FontAttribute, AttributeSet.CharacterAttribute + { + private FontConstants(String k) + { + super(k); + } + public static Object Bold = new FontConstants("bold"); + public static Object Family = new FontConstants("family"); + public static Object Italic = new FontConstants("italic"); + public static Object Size = new FontConstants("size"); + } + + public static class ParagraphConstants + extends StyleConstants + implements AttributeSet.ParagraphAttribute + { + private ParagraphConstants(String k) + { + super(k); + } + public static Object Alignment = new ParagraphConstants("Alignment"); + public static Object FirstLineIndent = new ParagraphConstants("FirstLineIndent"); + public static Object LeftIndent = new ParagraphConstants("LeftIndent"); + public static Object LineSpacing = new ParagraphConstants("LineSpacing"); + public static Object Orientation = new ParagraphConstants("Orientation"); + public static Object RightIndent = new ParagraphConstants("RightIndent"); + public static Object SpaceAbove = new ParagraphConstants("SpaceAbove"); + public static Object SpaceBelow = new ParagraphConstants("SpaceBelow"); + public static Object TabSet = new ParagraphConstants("TabSet"); + } + +} diff --git a/libjava/classpath/javax/swing/text/StyleContext.java b/libjava/classpath/javax/swing/text/StyleContext.java new file mode 100644 index 0000000..ae11622 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StyleContext.java @@ -0,0 +1,730 @@ +/* StyleContext.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Toolkit; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Hashtable; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +public class StyleContext + implements Serializable, AbstractDocument.AttributeContext +{ + public class NamedStyle + implements Serializable, Style + { + protected ChangeEvent changeEvent; + protected EventListenerList listenerList; + + AttributeSet attributes; + String name; + + public NamedStyle() + { + this(null, null); + } + + public NamedStyle(Style parent) + { + this(null, parent); + } + + public NamedStyle(String name, Style parent) + { + this.name = name; + this.attributes = getEmptySet(); + this.changeEvent = new ChangeEvent(this); + this.listenerList = new EventListenerList(); + setResolveParent(parent); + } + + public String getName() + { + return name; + } + + public void setName(String n) + { + name = n; + fireStateChanged(); + } + + public void addChangeListener(ChangeListener l) + { + listenerList.add(ChangeListener.class, l); + } + + public void removeChangeListener(ChangeListener l) + { + listenerList.remove(ChangeListener.class, l); + } + + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) getListeners(ChangeListener.class); + } + + protected void fireStateChanged() + { + ChangeListener[] listeners = getChangeListeners(); + for (int i = 0; i < listeners.length; ++i) + { + listeners[i].stateChanged(changeEvent); + } + } + + public void addAttribute(Object name, Object value) + { + attributes = StyleContext.this.addAttribute(attributes, name, value); + fireStateChanged(); + } + + public void addAttributes(AttributeSet attr) + { + attributes = StyleContext.this.addAttributes(attributes, attr); + fireStateChanged(); + } + + public boolean containsAttribute(Object name, Object value) + { + return attributes.containsAttribute(name, value); + } + + public boolean containsAttributes(AttributeSet attrs) + { + return attributes.containsAttributes(attrs); + } + + public AttributeSet copyAttributes() + { + return attributes.copyAttributes(); + } + + public Object getAttribute(Object attrName) + { + return attributes.getAttribute(attrName); + } + + public int getAttributeCount() + { + return attributes.getAttributeCount(); + } + + public Enumeration getAttributeNames() + { + return attributes.getAttributeNames(); + } + + public boolean isDefined(Object attrName) + { + return attributes.isDefined(attrName); + } + + public boolean isEqual(AttributeSet attr) + { + return attributes.isEqual(attr); + } + + public void removeAttribute(Object name) + { + attributes = StyleContext.this.removeAttribute(attributes, name); + fireStateChanged(); + } + + public void removeAttributes(AttributeSet attrs) + { + attributes = StyleContext.this.removeAttributes(attributes, attrs); + fireStateChanged(); + } + + public void removeAttributes(Enumeration names) + { + attributes = StyleContext.this.removeAttributes(attributes, names); + fireStateChanged(); + } + + + public AttributeSet getResolveParent() + { + return attributes.getResolveParent(); + } + + public void setResolveParent(AttributeSet parent) + { + if (parent != null) + { + attributes = StyleContext.this.addAttribute + (attributes, ResolveAttribute, parent); + } + fireStateChanged(); + } + + public String toString() + { + return ("[NamedStyle: name=" + name + ", attrs=" + attributes.toString() + "]"); + } + } + + public class SmallAttributeSet + implements AttributeSet + { + final Object [] attrs; + public SmallAttributeSet(AttributeSet a) + { + if (a == null) + attrs = new Object[0]; + else + { + int n = a.getAttributeCount(); + int i = 0; + attrs = new Object[n * 2]; + Enumeration e = a.getAttributeNames(); + while (e.hasMoreElements()) + { + Object name = e.nextElement(); + attrs[i++] = name; + attrs[i++] = a.getAttribute(name); + } + } + } + + public SmallAttributeSet(Object [] a) + { + if (a == null) + attrs = new Object[0]; + else + { + attrs = new Object[a.length]; + System.arraycopy(a, 0, attrs, 0, a.length); + } + } + + public Object clone() + { + return new SmallAttributeSet(this.attrs); + } + + public boolean containsAttribute(Object name, Object value) + { + for (int i = 0; i < attrs.length; i += 2) + { + if (attrs[i].equals(name) && + attrs[i+1].equals(value)) + return true; + } + return false; + } + + public boolean containsAttributes(AttributeSet a) + { + Enumeration e = a.getAttributeNames(); + while (e.hasMoreElements()) + { + Object name = e.nextElement(); + Object val = a.getAttribute(name); + if (!containsAttribute(name, val)) + return false; + } + return true; + } + + public AttributeSet copyAttributes() + { + return (AttributeSet) clone(); + } + + public boolean equals(Object obj) + { + return + (obj instanceof SmallAttributeSet) + && this.isEqual((AttributeSet)obj); + } + + public Object getAttribute(Object key) + { + for (int i = 0; i < attrs.length; i += 2) + { + if (attrs[i].equals(key)) + return attrs[i+1]; + } + + Object p = getResolveParent(); + if (p != null && p instanceof AttributeSet) + return (((AttributeSet)p).getAttribute(key)); + + return null; + } + + public int getAttributeCount() + { + return attrs.length / 2; + } + + public Enumeration getAttributeNames() + { + return new Enumeration() + { + int i = 0; + public boolean hasMoreElements() + { + return i < attrs.length; + } + public Object nextElement() + { + i += 2; + return attrs[i-2]; + } + }; + } + + public AttributeSet getResolveParent() + { + return (AttributeSet) getAttribute(ResolveAttribute); + } + + public int hashCode() + { + return java.util.Arrays.asList(attrs).hashCode(); + } + + public boolean isDefined(Object key) + { + for (int i = 0; i < attrs.length; i += 2) + { + if (attrs[i].equals(key)) + return true; + } + return false; + } + + public boolean isEqual(AttributeSet attr) + { + return attr != null + && attr.containsAttributes(this) + && this.containsAttributes(attr); + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("[StyleContext.SmallattributeSet:"); + for (int i = 0; i < attrs.length; ++i) + { + sb.append(" ("); + sb.append(attrs[i].toString()); + sb.append("="); + sb.append(attrs[i+1].toString()); + sb.append(")"); + } + sb.append("]"); + return sb.toString(); + } + } + + // FIXME: official javadocs suggest that these might be more usefully + // implemented using a WeakHashMap, but not sure if that works most + // places or whether it really matters anyways. + // + // FIXME: also not sure if these tables ought to be static (singletons), + // shared across all StyleContexts. I think so, but it's not clear in + // docs. revert to non-shared if you think it matters. + + /** + * The name of the default style. + */ + public static final String DEFAULT_STYLE = "default"; + + /** + * The default style for this style context. + */ + NamedStyle defaultStyle = new NamedStyle(DEFAULT_STYLE, null); + + static Hashtable sharedAttributeSets = new Hashtable(); + static Hashtable sharedFonts = new Hashtable(); + + static StyleContext defaultStyleContext = new StyleContext(); + static final int compressionThreshold = 9; + + EventListenerList listenerList; + Hashtable styleTable; + + /** + * Creates a new instance of the style context. Add the default style + * to the style table. + */ + public StyleContext() + { + listenerList = new EventListenerList(); + styleTable = new Hashtable(); + styleTable.put(DEFAULT_STYLE, defaultStyle); + } + + protected SmallAttributeSet createSmallAttributeSet(AttributeSet a) + { + return new SmallAttributeSet(a); + } + + protected MutableAttributeSet createLargeAttributeSet(AttributeSet a) + { + return new SimpleAttributeSet(a); + } + + public void addChangeListener(ChangeListener listener) + { + listenerList.add(ChangeListener.class, listener); + } + + public void removeChangeListener(ChangeListener listener) + { + listenerList.remove(ChangeListener.class, listener); + } + + public ChangeListener[] getChangeListeners() + { + return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); + } + + public Style addStyle(String name, Style parent) + { + Style newStyle = new NamedStyle(name, parent); + if (name != null) + styleTable.put(name, newStyle); + return newStyle; + } + + public void removeStyle(String name) + { + styleTable.remove(name); + } + + /** + * Get the style from the style table. If the passed name + * matches {@link #DEFAULT_STYLE}, returns the default style. + * Otherwise returns the previously defined style of + * null if the style with the given name is not defined. + * + * @param name the name of the style. + * + * @return the style with the given name or null if no such defined. + */ + public Style getStyle(String name) + { + return (Style) styleTable.get(name); + } + + /** + * Get the names of the style. The returned enumeration always + * contains at least one member, the default style. + */ + public Enumeration getStyleNames() + { + return styleTable.keys(); + } + + // + // StyleContexts only understand the "simple" model of fonts present in + // pre-java2d systems: fonts are a family name, a size (integral number + // of points), and a mask of style parameters (plain, bold, italic, or + // bold|italic). We have an inner class here called SimpleFontSpec which + // holds such triples. + // + // A SimpleFontSpec can be built for *any* AttributeSet because the size, + // family, and style keys in an AttributeSet have default values (defined + // over in StyleConstants). + // + // We keep a static cache mapping SimpleFontSpecs to java.awt.Fonts, so + // that we reuse Fonts between styles and style contexts. + // + + private static class SimpleFontSpec + { + String family; + int style; + int size; + public SimpleFontSpec(String family, + int style, + int size) + { + this.family = family; + this.style = style; + this.size = size; + } + public boolean equals(Object obj) + { + return (obj != null) + && (obj instanceof SimpleFontSpec) + && (((SimpleFontSpec)obj).family.equals(this.family)) + && (((SimpleFontSpec)obj).style == this.style) + && (((SimpleFontSpec)obj).size == this.size); + } + public int hashCode() + { + return family.hashCode() + style + size; + } + } + + public Font getFont(AttributeSet attr) + { + String family = StyleConstants.getFontFamily(attr); + int style = Font.PLAIN; + if (StyleConstants.isBold(attr)) + style += Font.BOLD; + if (StyleConstants.isItalic(attr)) + style += Font.ITALIC; + int size = StyleConstants.getFontSize(attr); + return getFont(family, style, size); + } + + public Font getFont(String family, int style, int size) + { + SimpleFontSpec spec = new SimpleFontSpec(family, style, size); + if (sharedFonts.containsKey(spec)) + return (Font) sharedFonts.get(spec); + else + { + Font tmp = new Font(family, style, size); + sharedFonts.put(spec, tmp); + return tmp; + } + } + + public FontMetrics getFontMetrics(Font f) + { + return Toolkit.getDefaultToolkit().getFontMetrics(f); + } + + public Color getForeground(AttributeSet a) + { + return StyleConstants.getForeground(a); + } + + public Color getBackground(AttributeSet a) + { + return StyleConstants.getBackground(a); + } + + protected int getCompressionThreshold() + { + return compressionThreshold; + } + + public static StyleContext getDefaultStyleContext() + { + return defaultStyleContext; + } + + public AttributeSet addAttribute(AttributeSet old, Object name, Object value) + { + if (old instanceof MutableAttributeSet) + { + ((MutableAttributeSet)old).addAttribute(name, value); + return old; + } + else + { + MutableAttributeSet mutable = createLargeAttributeSet(old); + mutable.addAttribute(name, value); + if (mutable.getAttributeCount() >= getCompressionThreshold()) + return mutable; + else + { + SmallAttributeSet small = createSmallAttributeSet(mutable); + if (sharedAttributeSets.containsKey(small)) + small = (SmallAttributeSet) sharedAttributeSets.get(small); + else + sharedAttributeSets.put(small,small); + return small; + } + } + } + + public AttributeSet addAttributes(AttributeSet old, AttributeSet attributes) + { + if (old instanceof MutableAttributeSet) + { + ((MutableAttributeSet)old).addAttributes(attributes); + return old; + } + else + { + MutableAttributeSet mutable = createLargeAttributeSet(old); + mutable.addAttributes(attributes); + if (mutable.getAttributeCount() >= getCompressionThreshold()) + return mutable; + else + { + SmallAttributeSet small = createSmallAttributeSet(mutable); + if (sharedAttributeSets.containsKey(small)) + small = (SmallAttributeSet) sharedAttributeSets.get(small); + else + sharedAttributeSets.put(small,small); + return small; + } + } + } + + public AttributeSet getEmptySet() + { + AttributeSet e = createSmallAttributeSet(null); + if (sharedAttributeSets.containsKey(e)) + e = (AttributeSet) sharedAttributeSets.get(e); + else + sharedAttributeSets.put(e, e); + return e; + } + + public void reclaim(AttributeSet attributes) + { + if (sharedAttributeSets.containsKey(attributes)) + sharedAttributeSets.remove(attributes); + } + + public AttributeSet removeAttribute(AttributeSet old, Object name) + { + if (old instanceof MutableAttributeSet) + { + ((MutableAttributeSet)old).removeAttribute(name); + if (old.getAttributeCount() < getCompressionThreshold()) + { + SmallAttributeSet small = createSmallAttributeSet(old); + if (!sharedAttributeSets.containsKey(small)) + sharedAttributeSets.put(small,small); + old = (AttributeSet) sharedAttributeSets.get(small); + } + return old; + } + else + { + MutableAttributeSet mutable = createLargeAttributeSet(old); + mutable.removeAttribute(name); + SmallAttributeSet small = createSmallAttributeSet(mutable); + if (sharedAttributeSets.containsKey(small)) + small = (SmallAttributeSet) sharedAttributeSets.get(small); + else + sharedAttributeSets.put(small,small); + return small; + } + } + + public AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes) + { + return removeAttributes(old, attributes.getAttributeNames()); + } + + public AttributeSet removeAttributes(AttributeSet old, Enumeration names) + { + if (old instanceof MutableAttributeSet) + { + ((MutableAttributeSet)old).removeAttributes(names); + if (old.getAttributeCount() < getCompressionThreshold()) + { + SmallAttributeSet small = createSmallAttributeSet(old); + if (!sharedAttributeSets.containsKey(small)) + sharedAttributeSets.put(small,small); + old = (AttributeSet) sharedAttributeSets.get(small); + } + return old; + } + else + { + MutableAttributeSet mutable = createLargeAttributeSet(old); + mutable.removeAttributes(names); + SmallAttributeSet small = createSmallAttributeSet(mutable); + if (sharedAttributeSets.containsKey(small)) + small = (SmallAttributeSet) sharedAttributeSets.get(small); + else + sharedAttributeSets.put(small,small); + return small; + } + } + + + // FIXME: there's some sort of quasi-serialization stuff in here which I + // have left incomplete; I'm not sure I understand the intent properly. + + public static Object getStaticAttribute(Object key) + { + throw new InternalError("not implemented"); + } + + public static Object getStaticAttributeKey(Object key) + { + throw new InternalError("not implemented"); + } + + public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a) + throws ClassNotFoundException, IOException + { + throw new InternalError("not implemented"); + } + + public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a) + throws IOException + { + throw new InternalError("not implemented"); + } + + public void readAttributes(ObjectInputStream in, MutableAttributeSet a) + throws ClassNotFoundException, IOException + { + throw new InternalError("not implemented"); + } + + public void writeAttributes(ObjectOutputStream out, AttributeSet a) + throws IOException + { + throw new InternalError("not implemented"); + } +} diff --git a/libjava/classpath/javax/swing/text/StyledDocument.java b/libjava/classpath/javax/swing/text/StyledDocument.java new file mode 100644 index 0000000..ea27754 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StyledDocument.java @@ -0,0 +1,145 @@ +/* StyledDcoument.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.awt.Color; +import java.awt.Font; + +/** + * StyledDocument + * @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 diff --git a/libjava/classpath/javax/swing/text/StyledEditorKit.java b/libjava/classpath/javax/swing/text/StyledEditorKit.java new file mode 100644 index 0000000..459f243 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StyledEditorKit.java @@ -0,0 +1,503 @@ +/* StyledEditorKit.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package 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.event.CaretEvent; +import javax.swing.event.CaretListener; + +/** + * StyledEditorKit + * + * @author Andrew Selkirk + */ +public class StyledEditorKit extends DefaultEditorKit +{ + private static final long serialVersionUID = 7002391892985555948L; + + /** + * UnderlineAction + */ + public static class UnderlineAction extends StyledEditorKit.StyledTextAction + { + /** + * Constructor UnderlineAction + */ + public UnderlineAction() + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * ItalicAction + */ + public static class ItalicAction extends StyledEditorKit.StyledTextAction + { + /** + * Constructor ItalicAction + */ + public ItalicAction() + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * BoldAction + */ + public static class BoldAction extends StyledEditorKit.StyledTextAction + { + /** + * Constructor BoldAction + */ + public BoldAction() + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * AlignmentAction + */ + public static class AlignmentAction extends StyledEditorKit.StyledTextAction + { + /** + * a + */ + private int a; + + /** + * Constructor AlignmentAction + * @param nm TODO + * @param a TODO + */ + public AlignmentAction(String nm, int a) + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * ForegroundAction + */ + public static class ForegroundAction extends StyledEditorKit.StyledTextAction + { + /** + * fg + */ + private Color fg; + + /** + * Constructor ForegroundAction + * @param nm TODO + * @param fg TODO + */ + public ForegroundAction(String nm, Color fg) + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * FontSizeAction + */ + public static class FontSizeAction extends StyledEditorKit.StyledTextAction + { + /** + * size + */ + private int size; + + /** + * Constructor FontSizeAction + * @param nm TODO + * @param size TODO + */ + public FontSizeAction(String nm, int size) + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * FontFamilyAction + */ + public static class FontFamilyAction extends StyledEditorKit.StyledTextAction + { + /** + * family + */ + private String family; + + /** + * Constructor FontFamilyAction + * @param nm TODO + * @param family TODO + */ + public FontFamilyAction(String nm, String family) + { + super("TODO"); + // TODO + } + + /** + * actionPerformed + * @param event TODO + */ + public void actionPerformed(ActionEvent event) + { + // TODO + } + } + + /** + * StyledTextAction + */ + public abstract static class StyledTextAction extends TextAction + { + /** + * Constructor StyledTextAction + * @param nm TODO + */ + public StyledTextAction(String nm) + { + super(nm); + // TODO + } + + /** + * getEditor + * @param event TODO + * @returns JEditorPane + */ + protected final JEditorPane getEditor(ActionEvent event) + { + return null; // TODO + } + + /** + * setCharacterAttributes + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + protected final void setCharacterAttributes(JEditorPane value0, + AttributeSet value1, + boolean value2) + { + // TODO + } + + /** + * getStyledDocument + * @param value0 TODO + * @returns StyledDocument + */ + protected final StyledDocument getStyledDocument(JEditorPane value0) + { + return null; // TODO + } + + /** + * getStyledEditorKit + * @param value0 TODO + * @returns StyledEditorKit + */ + protected final StyledEditorKit getStyledEditorKit(JEditorPane value0) + { + return null; // TODO + } + + /** + * setParagraphAttributes + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + protected final void setParagraphAttributes(JEditorPane value0, + AttributeSet value1, + boolean value2) + { + // TODO + } + } + + /** + * StyledViewFactory + */ + static class StyledViewFactory + implements ViewFactory + { + /** + * Constructor StyledViewFactory + */ + StyledViewFactory() + { + // TODO + } + + /** + * create + * @param value0 TODO + * @returns View + */ + public View create(Element value0) + { + return null; // TODO + } + } + + /** + * AttributeTracker + */ + class AttributeTracker + implements CaretListener, PropertyChangeListener, Serializable + { + /** + * Constructor AttributeTracker + * @param value0 TODO + */ + AttributeTracker(StyledEditorKit value0) + { + // TODO + } + + /** + * updateInputAttributes + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + void updateInputAttributes(int value0, int value1, JTextComponent value2) + { + // TODO + } + + /** + * propertyChange + * @param value0 TODO + */ + public void propertyChange(PropertyChangeEvent value0) + { + // TODO + } + + /** + * caretUpdate + * @param value0 TODO + */ + public void caretUpdate(CaretEvent value0) + { + // TODO + } + } + + /** + * currentRun + */ + Element currentRun; + + /** + * currentParagraph + */ + Element currentParagraph; + + /** + * inputAttributes + */ + MutableAttributeSet inputAttributes; + + /** + * Constructor StyledEditorKit + */ + public StyledEditorKit() + { + // TODO + } + + /** + * clone + * @returns Object + */ + public Object clone() + { + return null; // TODO + } + + /** + * getActions + * @returns Action[] + */ + public Action[] getActions() + { + return null; // TODO + } + + /** + * getInputAttributes + * @returns MutableAttributeSet + */ + public MutableAttributeSet getInputAttributes() + { + return null; // TODO + } + + /** + * getCharacterAttributeRun + * @returns Element + */ + public Element getCharacterAttributeRun() + { + return null; // TODO + } + + /** + * createDefaultDocument + * @returns Document + */ + public Document createDefaultDocument() + { + return null; // TODO + } + + /** + * install + * @param component TODO + */ + public void install(JEditorPane component) + { + // TODO + } + + /** + * deinstall + * @param component TODO + */ + public void deinstall(JEditorPane component) + { + // TODO + } + + /** + * getViewFactory + * @returns ViewFactory + */ + public ViewFactory getViewFactory() + { + return null; // TODO + } + + /** + * createInputAttributes + * @param element TODO + * @param set TODO + */ + protected void createInputAttributes(Element element, MutableAttributeSet set) + { + // TODO + } +} diff --git a/libjava/classpath/javax/swing/text/TabExpander.java b/libjava/classpath/javax/swing/text/TabExpander.java new file mode 100644 index 0000000..d70dd46 --- /dev/null +++ b/libjava/classpath/javax/swing/text/TabExpander.java @@ -0,0 +1,43 @@ +/* TabExpander.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +public interface TabExpander +{ + float nextTabStop(float x, int tabOffset); +} \ No newline at end of file diff --git a/libjava/classpath/javax/swing/text/TabSet.java b/libjava/classpath/javax/swing/text/TabSet.java new file mode 100644 index 0000000..146f545 --- /dev/null +++ b/libjava/classpath/javax/swing/text/TabSet.java @@ -0,0 +1,102 @@ +/* TabSet.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.io.Serializable; + +public class TabSet implements Serializable +{ + TabStop[] tabs; + + public TabSet(TabStop[] t) + { + tabs = t; + } + + public TabStop getTab(int i) + { + return tabs[i]; + } + + public TabStop getTabAfter(float location) + { + int idx = getTabIndexAfter(location); + if (idx == -1) + return null; + else + return tabs[idx]; + } + + public int getTabCount() + { + return tabs.length; + } + + public int getTabIndex(TabStop tab) + { + for (int i = 0; i < tabs.length; ++i) + if (tabs[i] == tab) + return i; + return -1; + } + + public int getTabIndexAfter(float location) + { + int idx = -1; + for (int i = 0; i < tabs.length; ++i) + { + if (location < tabs[i].getPosition()) + idx = i; + } + return idx; + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < tabs.length; ++i) + { + if (i != 0) + sb.append(" - "); + sb.append(tabs[i].toString()); + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/libjava/classpath/javax/swing/text/TabStop.java b/libjava/classpath/javax/swing/text/TabStop.java new file mode 100644 index 0000000..032da8b --- /dev/null +++ b/libjava/classpath/javax/swing/text/TabStop.java @@ -0,0 +1,133 @@ +/* TabSet.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +import java.io.Serializable; + +public class TabStop implements Serializable +{ + public static final int ALIGN_LEFT = 0; + public static final int ALIGN_RIGHT = 1; + public static final int ALIGN_CENTER = 2; + public static final int ALIGN_DECIMAL = 4; + public static final int ALIGN_BAR = 5; + + public static final int LEAD_NONE = 0; + public static final int LEAD_DOTS = 1; + public static final int LEAD_HYPHENS = 2; + public static final int LEAD_UNDERLINE = 3; + public static final int LEAD_THICKLINE = 4; + public static final int LEAD_EQUALS = 5; + + float pos; + int align; + int leader; + + public TabStop(float pos) + { + this(pos, ALIGN_LEFT, LEAD_NONE); + } + + public TabStop(float pos, int align, int leader) + { + this.pos = pos; + this.align = align; + this.leader = leader; + } + + public boolean equals(Object other) + { + return (other != null) + && (other instanceof TabStop) + && (((TabStop)other).getPosition() == this.getPosition()) + && (((TabStop)other).getLeader() == this.getLeader()) + && (((TabStop)other).getAlignment() == this.getAlignment()); + } + + public int getAlignment() + { + return align; + } + + public int getLeader() + { + return leader; + } + + public float getPosition() + { + return pos; + } + + public int hashCode() + { + return (int) pos + (int) leader + (int) align; + } + + public String toString() + { + String prefix = ""; + switch (align) + { + case ALIGN_LEFT: + prefix = "left "; + break; + case ALIGN_RIGHT: + prefix = "right "; + break; + + case ALIGN_CENTER: + prefix = "center "; + break; + + case ALIGN_DECIMAL: + prefix = "decimal "; + break; + + case ALIGN_BAR: + prefix = "bar "; + break; + + default: + break; + } + + return (prefix + "tab @" + pos + ((leader == LEAD_NONE) ? "" : "(w/leaders)")); + } + +} diff --git a/libjava/classpath/javax/swing/text/TabableView.java b/libjava/classpath/javax/swing/text/TabableView.java new file mode 100644 index 0000000..2a96ea9 --- /dev/null +++ b/libjava/classpath/javax/swing/text/TabableView.java @@ -0,0 +1,44 @@ +/* TabableView.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +public interface TabableView +{ + float getPartialSpan(int p0, int p1); + float getTabbedSpan(float x, TabExpander expander); +} diff --git a/libjava/classpath/javax/swing/text/TextAction.java b/libjava/classpath/javax/swing/text/TextAction.java new file mode 100644 index 0000000..8588e3c --- /dev/null +++ b/libjava/classpath/javax/swing/text/TextAction.java @@ -0,0 +1,111 @@ +/* TextAction.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.HashSet; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +/** + * TextAction + * @author Andrew Selkirk + */ +public abstract class TextAction extends AbstractAction +{ + /** + * Constructor TextAction + * @param name TODO + */ + public TextAction(String name) + { + super(name); + } + + /** + * Returns the JTextComponent object associated with the given + * ActionEvent. If the source of the event is not a + * JTextComponent the currently focused text component is returned. + * + * @param event the action event + * + * @return the JTextComponent + */ + protected final JTextComponent getTextComponent(ActionEvent event) + { + if (event.getSource() instanceof JTextComponent) + return (JTextComponent) event.getSource(); + + return getFocusedComponent(); + } + + /** + * Creates a new array of Action containing both given arrays. + * + * @param list1 the first action array + * @param list2 the second action array + * + * @return the augmented array of actions + */ + public static final Action[] augmentList(Action[] list1, Action[] list2) + { + HashSet actionSet = new HashSet(); + + for (int i = 0; i < list1.length; ++i) + actionSet.add(list1[i]); + + for (int i = 0; i < list2.length; ++i) + actionSet.add(list2[i]); + + ArrayList list = new ArrayList(actionSet); + return (Action[]) list.toArray(new Action[actionSet.size()]); + } + + /** + * Returns the current focused JTextComponent object. + * + * @return the JTextComponent + */ + protected final JTextComponent getFocusedComponent() + { + return null; // TODO + } +} diff --git a/libjava/classpath/javax/swing/text/Utilities.java b/libjava/classpath/javax/swing/text/Utilities.java new file mode 100644 index 0000000..d40408d --- /dev/null +++ b/libjava/classpath/javax/swing/text/Utilities.java @@ -0,0 +1,198 @@ +/* Utilities.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.FontMetrics; +import java.awt.Graphics; + +/** + * A set of utilities to deal with text. This is used by several other classes + * inside this package. + * + * @author Roman Kennke (roman@ontographics.com) + */ +public class Utilities +{ + /** + * The length of the char buffer that holds the characters to be drawn. + */ + private static final int BUF_LENGTH = 64; + + /** + * Creates a new Utilities object. + */ + public Utilities() + { + // Nothing to be done here. + } + + /** + * Draws the given text segment. Contained tabs and newline characters + * are taken into account. Tabs are expanded using the + * specified {@link TabExpander}. + * + * @param s the text fragment to be drawn. + * @param x the x position for drawing. + * @param y the y position for drawing. + * @param g the {@link Graphics} context for drawing. + * @param e the {@link TabExpander} which specifies the Tab-expanding + * technique. + * @param startOffset starting offset in the text. + * @return the x coordinate at the end of the drawn text. + */ + public static final int drawTabbedText(Segment s, int x, int y, Graphics g, + TabExpander e, int startOffset) + { + // This buffers the chars to be drawn. + char[] buffer = s.array; + + + // The current x and y pixel coordinates. + int pixelX = x; + int pixelY = y; + + // The font metrics of the current selected font. + FontMetrics metrics = g.getFontMetrics(); + int ascent = metrics.getAscent(); + + int pixelWidth = 0; + int pos = s.offset; + int len = 0; + + for (int offset = s.offset; offset < (s.offset + s.count); ++offset) + { + char c = buffer[offset]; + if (c == '\t' || c == '\n') + { + if (len > 0) { + g.drawChars(buffer, pos, len, pixelX, pixelY + ascent); + pixelX += pixelWidth; + pixelWidth = 0; + } + pos = offset+1; + len = 0; + } + + switch (c) + { + case '\t': + // In case we have a tab, we just 'jump' over the tab. + // When we have no tab expander we just use the width of ' '. + if (e != null) + pixelX = (int) e.nextTabStop((float) pixelX, + startOffset + offset - s.offset); + else + pixelX += metrics.charWidth(' '); + break; + case '\n': + // In case we have a newline, we must jump to the next line. + pixelY += metrics.getHeight(); + pixelX = x; + break; + default: + ++len; + pixelWidth += metrics.charWidth(buffer[offset]); + break; + } + } + + if (len > 0) + g.drawChars(buffer, pos, len, pixelX, pixelY + ascent); + + return pixelX; + } + + /** + * Determines the width, that the given text s would take + * if it was printed with the given {@link java.awt.FontMetrics} on the + * specified screen position. + * @param s the text fragment + * @param metrics the font metrics of the font to be used + * @param x the x coordinate of the point at which drawing should be done + * @param e the {@link TabExpander} to be used + * @param startOffset the index in s where to start + * @returns the width of the given text s. This takes tabs and newlines + * into account. + */ + public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, + int x, TabExpander e, + int startOffset) + { + // This buffers the chars to be drawn. + char[] buffer = s.array; + + // The current x coordinate. + int pixelX = x; + + // The current maximum width. + int maxWidth = 0; + + for (int offset = s.offset; offset < (s.offset + s.count); ++offset) + { + switch (buffer[offset]) + { + case '\t': + // In case we have a tab, we just 'jump' over the tab. + // When we have no tab expander we just use the width of 'm'. + if (e != null) + pixelX = (int) e.nextTabStop((float) pixelX, + startOffset + offset - s.offset); + else + pixelX += metrics.charWidth(' '); + break; + case '\n': + // In case we have a newline, we must 'draw' + // the buffer and jump on the next line. + pixelX += metrics.charWidth(buffer[offset]); + maxWidth = Math.max(maxWidth, pixelX - x); + pixelX = x; + break; + default: + // Here we draw the char. + pixelX += metrics.charWidth(buffer[offset]); + break; + } + } + + // Take the last line into account. + maxWidth = Math.max(maxWidth, pixelX - x); + + return maxWidth; + } +} diff --git a/libjava/classpath/javax/swing/text/View.java b/libjava/classpath/javax/swing/text/View.java new file mode 100644 index 0000000..4d9ed7b --- /dev/null +++ b/libjava/classpath/javax/swing/text/View.java @@ -0,0 +1,463 @@ +/* View.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.awt.Container; +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; + +public abstract class View implements SwingConstants +{ + public static final int BadBreakWeight = 0; + public static final int ExcellentBreakWeight = 2000; + public static final int ForcedBreakWeight = 3000; + public static final int GoodBreakWeight = 1000; + + public static final int X_AXIS = 0; + public static final int Y_AXIS = 1; + + private float width, height; + private Element elt; + private View parent; + + /** + * The child views. + */ + View[] children; + + /** + * Creates a new View instance. + * + * @param elem an Element value + */ + public View(Element elem) + { + elt = elem; + children = new View[0]; + } + + public abstract void paint(Graphics g, Shape s); + + public void setParent(View parent) + { + this.parent = parent; + } + + public View getParent() + { + return parent; + } + + public Container getContainer() + { + View parent = getParent(); + return parent != null ? parent.getContainer() : null; + } + + public Document getDocument() + { + return getElement().getDocument(); + } + + public Element getElement() + { + return elt; + } + + public abstract float getPreferredSpan(int axis); + + public int getResizeWeight(int axis) + { + return 0; + } + + public float getMaximumSpan(int axis) + { + if (getResizeWeight(axis) <= 0) + return getPreferredSpan(axis); + + return Integer.MAX_VALUE; + } + + public float getMinimumSpan(int axis) + { + if (getResizeWeight(axis) <= 0) + return getPreferredSpan(axis); + + return Integer.MAX_VALUE; + } + + public void setSize(float width, float height) + { + // The default implementation does nothing. + } + + public float getAlignment(int axis) + { + return 0.5f; + } + + public AttributeSet getAttributes() + { + return getElement().getAttributes(); + } + + public boolean isVisible() + { + return true; + } + + public int getViewCount() + { + return 0; + } + + public View getView(int index) + { + return null; + } + + public ViewFactory getViewFactory() + { + View parent = getParent(); + return parent != null ? parent.getViewFactory() : null; + } + + public void replace(int offset, int length, View[] views) + { + // Default implementation does nothing. + } + + public void insert(int offset, View view) + { + View[] array = { view }; + replace(offset, 1, array); + } + + public void append(View view) + { + View[] array = { view }; + replace(getViewCount(), 1, array); + } + + public void removeAll() + { + replace(0, getViewCount(), null); + } + + public void remove(int index) + { + replace(index, 1, null); + } + + public View createFragment(int p0, int p1) + { + // The default implementation doesn't support fragmentation. + return this; + } + + public int getStartOffset() + { + return getElement().getStartOffset(); + } + + public int getEndOffset() + { + return getElement().getEndOffset(); + } + + public Shape getChildAllocation(int index, Shape a) + { + return null; + } + + /** + * @since 1.4 + */ + public int getViewIndex(float x, float y, Shape allocation) + { + return -1; + } + + /** + * @since 1.4 + */ + public String getToolTipText(float x, float y, Shape allocation) + { + int index = getViewIndex(x, y, allocation); + + if (index < -1) + return null; + + Shape childAllocation = getChildAllocation(index, allocation); + + if (childAllocation.getBounds().contains(x, y)) + return getView(index).getToolTipText(x, y, childAllocation); + + return null; + } + + /** + * @since 1.3 + */ + public Graphics getGraphics() + { + return getContainer().getGraphics(); + } + + public void preferenceChanged(View child, boolean width, boolean height) + { + if (parent != null) + parent.preferenceChanged(this, width, height); + else + ((JComponent) getContainer()).revalidate(); + } + + public int getBreakWeight(int axis, float pos, float len) + { + return BadBreakWeight; + } + + public View breakView(int axis, int offset, float pos, float len) + { + return this; + } + + /** + * @since 1.3 + */ + public int getViewIndex(int pos, Position.Bias b) + { + return -1; + } + + /** + * Receive notification about an insert update to the text model. + * + * The default implementation of this method does the following: + * + * + * @param ev the DocumentEvent that describes the change + * @param shape the shape of the view + * @param vf the ViewFactory for creating child views + */ + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Element el = getElement(); + DocumentEvent.ElementChange ec = ev.getChange(el); + if (ec != null) + updateChildren(ec, ev, vf); + forwardUpdate(ec, ev, shape, vf); + updateLayout(ec, ev, shape); + } + + /** + * Receive notification about a remove update to the text model. + * + * The default implementation of this method does the following: + * + * + * @param ev the DocumentEvent that describes the change + * @param shape the shape of the view + * @param vf the ViewFactory for creating child views + */ + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Element el = getElement(); + DocumentEvent.ElementChange ec = ev.getChange(el); + if (ec != null) + updateChildren(ec, ev, vf); + forwardUpdate(ec, ev, shape, vf); + updateLayout(ec, ev, shape); + } + + /** + * Receive notification about a change update to the text model. + * + * The default implementation of this method does the following: + * + * + * @param ev the DocumentEvent that describes the change + * @param shape the shape of the view + * @param vf the ViewFactory for creating child views + */ + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + Element el = getElement(); + DocumentEvent.ElementChange ec = ev.getChange(el); + if (ec != null) + updateChildren(ec, ev, vf); + forwardUpdate(ec, ev, shape, vf); + updateLayout(ec, ev, shape); + } + + /** + * Updates the list of children that is returned by {@link #getView} + * and {@link #getViewCount}. + * + * Element that are specified as beeing added in the ElementChange record are + * assigned a view for using the ViewFactory. Views of Elements that + * are specified as beeing removed are removed from the list. + * + * @param ec the ElementChange record that describes the change of the + * element + * @param ev the DocumentEvent describing the change of the document model + * @param vf the ViewFactory to use for creating new views + * + * @return whether or not the child views represent the child elements of + * the element that this view is responsible for. Some views may + * create views that are responsible only for parts of the element + * that they are responsible for and should then return false. + * + * @since 1.3 + */ + protected boolean updateChildren(DocumentEvent.ElementChange ec, + DocumentEvent ev, + ViewFactory vf) + { + Element[] added = ec.getChildrenAdded(); + Element[] removed = ec.getChildrenRemoved(); + View[] newChildren = new View[children.length + added.length + - removed.length]; + int index = ec.getIndex(); + System.arraycopy(children, 0, newChildren, 0, index); + System.arraycopy(children, index, added, 0, added.length); + int index2 = index + removed.length; + int len2 = children.length - index2; + System.arraycopy(children, index2, newChildren, index + added.length, + len2); + children = newChildren; + + return true; + } + + /** + * Forwards the DocumentEvent to child views that need to get notified + * of the change to the model. This calles {@link #forwardUpdateToView} + * for each View that must be forwarded to. + * + * @param ec the ElementChange describing the element changes (may be + * null if there were no changes) + * @param ev the DocumentEvent describing the changes to the model + * @param shape the current allocation of the view + * @param vf the ViewFactory used to create new Views + * + * @since 1.3 + */ + protected void forwardUpdate(DocumentEvent.ElementChange ec, + DocumentEvent ev, Shape shape, ViewFactory vf) + { + for (int i = 0; i < children.length; i++) + { + View child = children[i]; + forwardUpdateToView(child, ev, shape, vf); + } + } + + /** + * Forwards an update event to the given child view. This calls + * {@link #insertUpdate}, {@link #removeUpdate} or {@link #changedUpdate}, + * depending on the type of document event. + * + * @param view the View to forward the event to + * @param ev the DocumentEvent to forward + * @param shape the current allocation of the View + * @param vf the ViewFactory used to create new Views + * + * @since 1.3 + */ + protected void forwardUpdateToView(View view, DocumentEvent ev, Shape shape, + ViewFactory vf) + { + DocumentEvent.EventType type = ev.getType(); + if (type == DocumentEvent.EventType.INSERT) + view.insertUpdate(ev, shape, vf); + else if (type == DocumentEvent.EventType.REMOVE) + view.removeUpdate(ev, shape, vf); + else if (type == DocumentEvent.EventType.CHANGE) + view.changedUpdate(ev, shape, vf); + } + + /** + * Updates the layout. + * + * @param ec the ElementChange that describes the changes to the element + * @param ev the DocumentEvent that describes the changes to the model + * @param shape the current allocation for this view + * + * @since 1.3 + */ + protected void updateLayout(DocumentEvent.ElementChange ec, + DocumentEvent ev, Shape shape) + { + Rectangle b = shape.getBounds(); + if (ec != null) + preferenceChanged(this, true, true); + } +} + diff --git a/libjava/classpath/javax/swing/text/ViewFactory.java b/libjava/classpath/javax/swing/text/ViewFactory.java new file mode 100644 index 0000000..0794880 --- /dev/null +++ b/libjava/classpath/javax/swing/text/ViewFactory.java @@ -0,0 +1,50 @@ +/* ViewFactory.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.text; + +public interface ViewFactory +{ + /** + * Creates a view for a given element. + * + * @param elem them element to create view for + * + * @return a new created view + */ + View create(Element elem); +} diff --git a/libjava/classpath/javax/swing/text/html/HTML.java b/libjava/classpath/javax/swing/text/html/HTML.java new file mode 100644 index 0000000..3c03a63 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/HTML.java @@ -0,0 +1,1309 @@ +/* HTML.java -- HTML document tag constants + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text.html; + +import java.io.Serializable; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import java.util.Map; +import java.util.TreeMap; + +import javax.swing.text.AttributeSet; + +/** + * HTML attribute and tag definitions. + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class HTML +{ + /** + * Represents a HTML attribute. + */ + public static class Attribute + implements Serializable + { + /** + * The action attribute + */ + public static final Attribute ACTION = new Attribute("action"); + + /** + * The align attribute + */ + public static final Attribute ALIGN = new Attribute("align"); + + /** + * The alink attribute + */ + public static final Attribute ALINK = new Attribute("alink"); + + /** + * The alt attribute + */ + public static final Attribute ALT = new Attribute("alt"); + + /** + * The archive attribute + */ + public static final Attribute ARCHIVE = new Attribute("archive"); + + /** + * The background attribute + */ + public static final Attribute BACKGROUND = new Attribute("background"); + + /** + * The bgcolor attribute + */ + public static final Attribute BGCOLOR = new Attribute("bgcolor"); + + /** + * The border attribute + */ + public static final Attribute BORDER = new Attribute("border"); + + /** + * The cellpadding attribute + */ + public static final Attribute CELLPADDING = new Attribute("cellpadding"); + + /** + * The cellspacing attribute + */ + public static final Attribute CELLSPACING = new Attribute("cellspacing"); + + /** + * The checked attribute + */ + public static final Attribute CHECKED = new Attribute("checked"); + + /** + * The class attribute + */ + public static final Attribute CLASS = new Attribute("class"); + + /** + * The classid attribute + */ + public static final Attribute CLASSID = new Attribute("classid"); + + /** + * The clear attribute + */ + public static final Attribute CLEAR = new Attribute("clear"); + + /** + * The code attribute + */ + public static final Attribute CODE = new Attribute("code"); + + /** + * The codebase attribute + */ + public static final Attribute CODEBASE = new Attribute("codebase"); + + /** + * The codetype attribute + */ + public static final Attribute CODETYPE = new Attribute("codetype"); + + /** + * The color attribute + */ + public static final Attribute COLOR = new Attribute("color"); + + /** + * The cols attribute + */ + public static final Attribute COLS = new Attribute("cols"); + + /** + * The colspan attribute + */ + public static final Attribute COLSPAN = new Attribute("colspan"); + + /** + * The comment attribute + */ + public static final Attribute COMMENT = new Attribute("comment"); + + /** + * The compact attribute + */ + public static final Attribute COMPACT = new Attribute("compact"); + + /** + * The content attribute + */ + public static final Attribute CONTENT = new Attribute("content"); + + /** + * The coords attribute + */ + public static final Attribute COORDS = new Attribute("coords"); + + /** + * The data attribute + */ + public static final Attribute DATA = new Attribute("data"); + + /** + * The declare attribute + */ + public static final Attribute DECLARE = new Attribute("declare"); + + /** + * The dir attribute + */ + public static final Attribute DIR = new Attribute("dir"); + + /** + * The dummy attribute + */ + public static final Attribute DUMMY = new Attribute("dummy"); + + /** + * The enctype attribute + */ + public static final Attribute ENCTYPE = new Attribute("enctype"); + + /** + * The endtag attribute + */ + public static final Attribute ENDTAG = new Attribute("endtag"); + + /** + * The face attribute + */ + public static final Attribute FACE = new Attribute("face"); + + /** + * The frameborder attribute + */ + public static final Attribute FRAMEBORDER = new Attribute("frameborder"); + + /** + * The halign attribute + */ + public static final Attribute HALIGN = new Attribute("halign"); + + /** + * The height attribute + */ + public static final Attribute HEIGHT = new Attribute("height"); + + /** + * The href attribute + */ + public static final Attribute HREF = new Attribute("href"); + + /** + * The hspace attribute + */ + public static final Attribute HSPACE = new Attribute("hspace"); + + /** + * The http-equiv attribute + */ + public static final Attribute HTTPEQUIV = new Attribute("http-equiv"); + + /** + * The id attribute + */ + public static final Attribute ID = new Attribute("id"); + + /** + * The ismap attribute + */ + public static final Attribute ISMAP = new Attribute("ismap"); + + /** + * The lang attribute + */ + public static final Attribute LANG = new Attribute("lang"); + + /** + * The language attribute + */ + public static final Attribute LANGUAGE = new Attribute("language"); + + /** + * The link attribute + */ + public static final Attribute LINK = new Attribute("link"); + + /** + * The lowsrc attribute + */ + public static final Attribute LOWSRC = new Attribute("lowsrc"); + + /** + * The marginheight attribute + */ + public static final Attribute MARGINHEIGHT = new Attribute("marginheight"); + + /** + * The marginwidth attribute + */ + public static final Attribute MARGINWIDTH = new Attribute("marginwidth"); + + /** + * The maxlength attribute + */ + public static final Attribute MAXLENGTH = new Attribute("maxlength"); + + /** + * The media attribute + */ + public static final Attribute MEDIA = new Attribute("media"); + + /** + * The method attribute + */ + public static final Attribute METHOD = new Attribute("method"); + + /** + * The multiple attribute + */ + public static final Attribute MULTIPLE = new Attribute("multiple"); + + /** + * The n attribute + */ + public static final Attribute N = new Attribute("n"); + + /** + * The name attribute + */ + public static final Attribute NAME = new Attribute("name"); + + /** + * The nohref attribute + */ + public static final Attribute NOHREF = new Attribute("nohref"); + + /** + * The noresize attribute + */ + public static final Attribute NORESIZE = new Attribute("noresize"); + + /** + * The noshade attribute + */ + public static final Attribute NOSHADE = new Attribute("noshade"); + + /** + * The nowrap attribute + */ + public static final Attribute NOWRAP = new Attribute("nowrap"); + + /** + * The prompt attribute + */ + public static final Attribute PROMPT = new Attribute("prompt"); + + /** + * The rel attribute + */ + public static final Attribute REL = new Attribute("rel"); + + /** + * The rev attribute + */ + public static final Attribute REV = new Attribute("rev"); + + /** + * The rows attribute + */ + public static final Attribute ROWS = new Attribute("rows"); + + /** + * The rowspan attribute + */ + public static final Attribute ROWSPAN = new Attribute("rowspan"); + + /** + * The scrolling attribute + */ + public static final Attribute SCROLLING = new Attribute("scrolling"); + + /** + * The selected attribute + */ + public static final Attribute SELECTED = new Attribute("selected"); + + /** + * The shape attribute + */ + public static final Attribute SHAPE = new Attribute("shape"); + + /** + * The shapes attribute + */ + public static final Attribute SHAPES = new Attribute("shapes"); + + /** + * The size attribute + */ + public static final Attribute SIZE = new Attribute("size"); + + /** + * The src attribute + */ + public static final Attribute SRC = new Attribute("src"); + + /** + * The standby attribute + */ + public static final Attribute STANDBY = new Attribute("standby"); + + /** + * The start attribute + */ + public static final Attribute START = new Attribute("start"); + + /** + * The style attribute + */ + public static final Attribute STYLE = new Attribute("style"); + + /** + * The target attribute + */ + public static final Attribute TARGET = new Attribute("target"); + + /** + * The text attribute + */ + public static final Attribute TEXT = new Attribute("text"); + + /** + * The title attribute + */ + public static final Attribute TITLE = new Attribute("title"); + + /** + * The type attribute + */ + public static final Attribute TYPE = new Attribute("type"); + + /** + * The usemap attribute + */ + public static final Attribute USEMAP = new Attribute("usemap"); + + /** + * The valign attribute + */ + public static final Attribute VALIGN = new Attribute("valign"); + + /** + * The value attribute + */ + public static final Attribute VALUE = new Attribute("value"); + + /** + * The valuetype attribute + */ + public static final Attribute VALUETYPE = new Attribute("valuetype"); + + /** + * The version attribute + */ + public static final Attribute VERSION = new Attribute("version"); + + /** + * The vlink attribute + */ + public static final Attribute VLINK = new Attribute("vlink"); + + /** + * The vspace attribute + */ + public static final Attribute VSPACE = new Attribute("vspace"); + + /** + * The width attribute + */ + public static final Attribute WIDTH = new Attribute("width"); + private final String name; + + /** + * Creates the attribute with the given name. + */ + protected Attribute(String a_name) + { + name = a_name; + } + + /** + * Calls compareTo on the tag names (Strings) + */ + public int compareTo(Object other) + { + return name.compareTo(((Attribute) other).name); + } + + /** + * The attributes are equal if the names are equal + * (ignoring case) + */ + public boolean equals(Object other) + { + if (other == this) + return true; + + if (!(other instanceof Attribute)) + return false; + + Attribute that = (Attribute) other; + + return that.name.equalsIgnoreCase(name); + } + + /** + * Returns the hash code which corresponds to the string for this tag. + */ + public int hashCode() + { + return name == null ? 0 : name.hashCode(); + } + + /** + * Returns the attribute name. The names of the built-in attributes + * are always returned in lowercase. + */ + public String toString() + { + return name; + } + + /** + * Return an array of all attributes, declared in the HTML.Attribute + * class. WARNING: attributes are the only public fields, + * expected in this class. + */ + static Attribute[] getAllAttributes() + { + Field[] f = Attribute.class.getFields(); + Attribute[] attrs = new Attribute[ f.length ]; + Field x; + int p = 0; + Attribute a; + + for (int i = 0; i < f.length; i++) + { + x = f [ i ]; + + if ((x.getModifiers() & Modifier.STATIC) != 0) + { + if (x.getType().equals(Attribute.class)) + { + try + { + a = (Attribute) x.get(null); + attrs [ p++ ] = a; + } + catch (Exception ex) + { + ex.printStackTrace(System.err); + throw new Error("This should never happen, report a bug"); + } + } + } + } + + return attrs; + } + } + + /** + * Represents a HTML tag. + */ + public static class Tag + implements Comparable, Serializable + { + /** + * The <a> tag + */ + public static final Tag A = new Tag("a"); + + /** + * The <address> tag + */ + public static final Tag ADDRESS = new Tag("address"); + + /** + * The <applet> tag + */ + public static final Tag APPLET = new Tag("applet"); + + /** + * The <area> tag + */ + public static final Tag AREA = new Tag("area"); + + /** + * The <b> tag + */ + public static final Tag B = new Tag("b"); + + /** + * The <base> tag + */ + public static final Tag BASE = new Tag("base"); + + /** + * The <basefont> tag + */ + public static final Tag BASEFONT = new Tag("basefont"); + + /** + * The <big> tag + */ + public static final Tag BIG = new Tag("big"); + + /** + * The <blockquote> tag , breaks flow, block tag. + */ + public static final Tag BLOCKQUOTE = new Tag("blockquote", BREAKS | BLOCK); + + /** + * The <body> tag , breaks flow, block tag. + */ + public static final Tag BODY = new Tag("body", BREAKS | BLOCK); + + /** + * The <br> tag , breaks flow. + */ + public static final Tag BR = new Tag("br", BREAKS); + + /** + * The <caption> tag + */ + public static final Tag CAPTION = new Tag("caption"); + + /** + * The <center> tag , breaks flow. + */ + public static final Tag CENTER = new Tag("center", BREAKS); + + /** + * The <cite> tag + */ + public static final Tag CITE = new Tag("cite"); + + /** + * The <code> tag + */ + public static final Tag CODE = new Tag("code"); + + /** + * The <dd> tag , breaks flow, block tag. + */ + public static final Tag DD = new Tag("dd", BREAKS | BLOCK); + + /** + * The <dfn> tag + */ + public static final Tag DFN = new Tag("dfn"); + + /** + * The <dir> tag , breaks flow, block tag. + */ + public static final Tag DIR = new Tag("dir", BREAKS | BLOCK); + + /** + * The <div> tag , breaks flow, block tag. + */ + public static final Tag DIV = new Tag("div", BREAKS | BLOCK); + + /** + * The <dl> tag , breaks flow, block tag. + */ + public static final Tag DL = new Tag("dl", BREAKS | BLOCK); + + /** + * The <dt> tag , breaks flow, block tag. + */ + public static final Tag DT = new Tag("dt", BREAKS | BLOCK); + + /** + * The <em> tag + */ + public static final Tag EM = new Tag("em"); + + /** + * The <font> tag + */ + public static final Tag FONT = new Tag("font"); + + /** + * The <form> tag , breaks flow. + */ + public static final Tag FORM = new Tag("form", BREAKS); + + /** + * The <frame> tag + */ + public static final Tag FRAME = new Tag("frame"); + + /** + * The <frameset> tag + */ + public static final Tag FRAMESET = new Tag("frameset"); + + /** + * The <h1> tag , breaks flow, block tag. + */ + public static final Tag H1 = new Tag("h1", BREAKS | BLOCK); + + /** + * The <h2> tag , breaks flow, block tag. + */ + public static final Tag H2 = new Tag("h2", BREAKS | BLOCK); + + /** + * The <h3> tag , breaks flow, block tag. + */ + public static final Tag H3 = new Tag("h3", BREAKS | BLOCK); + + /** + * The <h4> tag , breaks flow, block tag. + */ + public static final Tag H4 = new Tag("h4", BREAKS | BLOCK); + + /** + * The <h5> tag , breaks flow, block tag. + */ + public static final Tag H5 = new Tag("h5", BREAKS | BLOCK); + + /** + * The <h6> tag , breaks flow, block tag. + */ + public static final Tag H6 = new Tag("h6", BREAKS | BLOCK); + + /** + * The <head> tag , breaks flow, block tag. + */ + public static final Tag HEAD = new Tag("head", BREAKS | BLOCK); + + /** + * The <hr> tag , breaks flow. + */ + public static final Tag HR = new Tag("hr", BREAKS); + + /** + * The <html> tag , breaks flow. + */ + public static final Tag HTML = new Tag("html", BREAKS); + + /** + * The <i> tag + */ + public static final Tag I = new Tag("i"); + + /** + * The <img> tag + */ + public static final Tag IMG = new Tag("img"); + + /** + * The <input> tag + */ + public static final Tag INPUT = new Tag("input"); + + /** + * The <isindex> tag , breaks flow. + */ + public static final Tag ISINDEX = new Tag("isindex", BREAKS); + + /** + * The <kbd> tag + */ + public static final Tag KBD = new Tag("kbd"); + + /** + * The <li> tag , breaks flow, block tag. + */ + public static final Tag LI = new Tag("li", BREAKS | BLOCK); + + /** + * The <link> tag + */ + public static final Tag LINK = new Tag("link"); + + /** + * The <map> tag + */ + public static final Tag MAP = new Tag("map"); + + /** + * The <menu> tag , breaks flow, block tag. + */ + public static final Tag MENU = new Tag("menu", BREAKS | BLOCK); + + /** + * The <meta> tag + */ + public static final Tag META = new Tag("meta"); + + /** + * The <nobr> tag + */ + public static final Tag NOBR = new Tag("nobr"); + + /** + * The <noframes> tag , breaks flow, block tag. + */ + public static final Tag NOFRAMES = new Tag("noframes", BREAKS | BLOCK); + + /** + * The <object> tag + */ + public static final Tag OBJECT = new Tag("object"); + + /** + * The <ol> tag , breaks flow, block tag. + */ + public static final Tag OL = new Tag("ol", BREAKS | BLOCK); + + /** + * The <option> tag + */ + public static final Tag OPTION = new Tag("option"); + + /** + * The <p> tag , breaks flow, block tag. + */ + public static final Tag P = new Tag("p", BREAKS | BLOCK); + + /** + * The <param> tag + */ + public static final Tag PARAM = new Tag("param"); + + /** + * The <pre> tag , breaks flow, block tag, preformatted. + */ + public static final Tag PRE = new Tag("pre", BREAKS | BLOCK | PREFORMATTED); + + /** + * The <s> tag + */ + public static final Tag S = new Tag("s"); + + /** + * The <samp> tag + */ + public static final Tag SAMP = new Tag("samp"); + + /** + * The <script> tag + */ + public static final Tag SCRIPT = new Tag("script"); + + /** + * The <select> tag + */ + public static final Tag SELECT = new Tag("select"); + + /** + * The <small> tag + */ + public static final Tag SMALL = new Tag("small"); + + /** + * The <span> tag + */ + public static final Tag SPAN = new Tag("span"); + + /** + * The <strike> tag + */ + public static final Tag STRIKE = new Tag("strike"); + + /** + * The <strong> tag + */ + public static final Tag STRONG = new Tag("strong"); + + /** + * The <style> tag + */ + public static final Tag STYLE = new Tag("style"); + + /** + * The <sub> tag + */ + public static final Tag SUB = new Tag("sub"); + + /** + * The <sup> tag + */ + public static final Tag SUP = new Tag("sup"); + + /** + * The <table> tag , block tag. + */ + public static final Tag TABLE = new Tag("table", BLOCK); + + /** + * The <td> tag , breaks flow, block tag. + */ + public static final Tag TD = new Tag("td", BREAKS | BLOCK); + + /** + * The <textarea> tag , preformatted. + */ + public static final Tag TEXTAREA = new Tag("textarea", PREFORMATTED); + + /** + * The <th> tag , breaks flow, block tag. + */ + public static final Tag TH = new Tag("th", BREAKS | BLOCK); + + /** + * The <title> tag , breaks flow, block tag. + */ + public static final Tag TITLE = new Tag("title", BREAKS | BLOCK); + + /** + * The <tr> tag , block tag. + */ + public static final Tag TR = new Tag("tr", BLOCK); + + /** + * The <tt> tag + */ + public static final Tag TT = new Tag("tt"); + + /** + * The <u> tag + */ + public static final Tag U = new Tag("u"); + + /** + * The <ul> tag , breaks flow, block tag. + */ + public static final Tag UL = new Tag("ul", BREAKS | BLOCK); + + /** + * The <var> tag + */ + public static final Tag VAR = new Tag("var"); + + /* Special tags */ + + /** + * Total number of syntetic tags, delared in the Tag class. + * This must be adjusted if the new synthetic tags are declared. + * Otherwise the HTML.getAllTags() will not work as expected. + */ + private static final int TOTAL_SYNTHETIC_TAGS = 3; + + /** + * All comments are labeled with this tag. + * 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); + + /** + * 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); + + /** + * 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. + */ + public static final Tag IMPLIED = new Tag("implied", SYNTETIC); + final String name; + final int flags; + + /** + * Create the unitialised instance of HTML.Tag. + * + * The {@link #breaksFlow()}, {@link #isBlock()} + * and {@link #isPreformatted()} will always return false. + * The {@link #toString()} will return null. + * + * @since 1.3 + */ + public Tag() + { + name = null; + flags = 0; + } + + /** + * Creates a new Tag with the specified id, and with causesBreak + * and isBlock set to false. + */ + protected Tag(String id) + { + name = id; + flags = 0; + } + + /** + * Creates a new Tag with the specified tag name and + * causesBreak and isBlock properties. + */ + protected Tag(String id, boolean causesBreak, boolean isBlock) + { + int f = 0; + + if (causesBreak) + { + f |= BREAKS; + } + + if (isBlock) + { + f |= BLOCK; + } + + flags = f; + name = id; + } + + /** + * Create a tag taking flags. + */ + Tag(String id, int a_flags) + { + name = id; + flags = a_flags; + } + + /** + * Returns true if this tag is a block tag, which is a tag used to + * add structure to a document. + */ + public boolean isBlock() + { + return (flags & BLOCK) != 0; + } + + /** + * Returns true if this tag is pre-formatted, which is true if + * the tag is either PRE or TEXTAREA + */ + public boolean isPreformatted() + { + return (flags & PREFORMATTED) != 0; + } + + /** + * Returns true if this tag causes a line break to the flow of text + */ + public boolean breaksFlow() + { + return (flags & BREAKS) != 0; + } + + /** + * Calls compareTo on the tag names (Strings) + */ + public int compareTo(Object other) + { + return name.compareTo(((Tag) other).name); + } + + /** + * The tags are equal if the names are equal (ignoring case). + */ + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof Tag)) + { + return false; + } + + Tag that = (Tag) other; + + return that.name.equalsIgnoreCase(name); + } + + /** + * Returns the hash code which corresponds to the string for this tag. + */ + public int hashCode() + { + return name == null ? 0 : name.hashCode(); + } + + /** + * Returns the tag name. The names of the built-in tags are always + * returned in lowercase. + */ + public String toString() + { + return name; + } + + /** + * Return an array of HTML tags, declared in HTML.Tag class. + * WARNING: This method expects that the Tags are the only + * public fields declared in the Tag class. + */ + static Tag[] getAllTags() + { + Field[] f = Tag.class.getFields(); + Field x; + + // The syntetic tags are not included. + Tag[] tags = new Tag[ f.length - TOTAL_SYNTHETIC_TAGS ]; + int p = 0; + Tag t; + + for (int i = 0; i < f.length; i++) + { + x = f [ i ]; + + if ((x.getModifiers() & Modifier.STATIC) != 0) + { + if (x.getType().equals(Tag.class)) + { + try + { + t = (Tag) x.get(null); + + if (!t.isSyntetic()) + { + tags [ p++ ] = t; + } + } + catch (IllegalAccessException ex) + { + unexpected(ex); + } + catch (IllegalArgumentException ex) + { + unexpected(ex); + } + } + } + } + + return tags; + } + + /** + * Returns true for tags, generated by the html reader + * (COMMENT, CONTENT and IMPLIED). + */ + boolean isSyntetic() + { + return (flags & SYNTETIC) != 0; + } + + private static void unexpected(Exception ex) + throws Error + { + throw new Error("This should never happen, report a bug", ex); + } + } + + /** + * Represents an unknown HTML tag. + * @author Mark Wielaard (mark@klomp.org) + */ + public static class UnknownTag + extends Tag + implements Serializable + { + private static final long serialVersionUID = -1534369342247250625L; + + /** + * Creates a new UnknownTag with the specified name + * @param name The tag name. + * + */ + public UnknownTag(String name) + { + super(name); + } + } + + /** + * This value is returned for attributes without value that have no + * default value defined in the DTD. + */ + public static final String NULL_ATTRIBUTE_VALUE = "#DEFAULT"; + + /* Package level html tag flags */ + static final int BREAKS = 1; + static final int BLOCK = 2; + static final int PREFORMATTED = 4; + static final int SYNTETIC = 8; + private static Map tagMap; + private static Map attrMap; + + /** + * The public constructor (does nothing). It it seldom required to have + * an instance of this class, because all public fields and methods + * are static. + */ + public HTML() + { + } + + /** + * Returns the set of the recognized HTML attributes. + */ + public static HTML.Attribute[] getAllAttributeKeys() + { + return Attribute.getAllAttributes(); + } + + /** + * Returns the set of actual HTML tags that are recognized by + * the default HTML reader. The returned array does not include the + * COMMENT, CONTENT and IMPLIED tags. + */ + public static HTML.Tag[] getAllTags() + { + return Tag.getAllTags(); + } + + /** + * Returns an htl attribute constant for the given attribute name. + * @param attName the attribute name, case insensitive + */ + public static Attribute getAttributeKey(String attName) + { + if (attrMap == null) + { + // Create the map on demand. + attrMap = new TreeMap(); + + Attribute[] attrs = getAllAttributeKeys(); + + for (int i = 0; i < attrs.length; i++) + { + attrMap.put(attrs [ i ].toString(), attrs [ i ]); + } + } + + return (Attribute) attrMap.get(attName.toLowerCase()); + } + + /** + * Searches the value of given attribute in the provided set. + * If the value is found (String type expected), tries to parse it as + * an integer value. If succeded, returns the obtained integer value. + * + * For example:

+ * SimpleAttributeSet ase = new SimpleAttributeSet(); + * ase.addAttribute(HTML.getAttributeKey("size"),"222"); + * System.out.println( + * HTML.getIntegerAttributeValue + * (ase, HTML.getAttributeKey("size"), 333)); // prints "222" + * System.out.println( + * HTML.getIntegerAttributeValue + * (ase, HTML.getAttributeKey("width"), 333)); // prints "333". + *

+ * + * + * @param set The attribute set to search in. If the set contains the + * given attribute, it must by a type of String. + * @param attribute The html attribute to search in + * @param defaultValue The value that is returned if the attribute is not + * found in the given set or if the NumberFormatException was thrown + * during the parsing. + */ + public static int getIntegerAttributeValue(AttributeSet set, + HTML.Attribute attribute, + int defaultValue + ) + { + Object v = set.getAttribute(attribute); + + if (v == null) + { + return defaultValue; + } + + try + { + return Integer.parseInt(v.toString().trim()); + } + catch (Exception ex) + { + return defaultValue; + } + } + + /** + * Returns a HTML tag constant for the given HTML attribute name. + * If the tag is unknown, the null is returned. + * @param tagName the tag name, case insensitive + */ + public static Tag getTag(String tagName) + { + if (tagMap == null) + { + // Create the mao on demand. + tagMap = new TreeMap(); + + Tag[] tags = getAllTags(); + + for (int i = 0; i < tags.length; i++) + { + tagMap.put(tags [ i ].toString(), tags [ i ]); + } + } + + return (Tag) tagMap.get(tagName.toLowerCase()); + } +} diff --git a/libjava/classpath/javax/swing/text/html/HTMLDocument.java b/libjava/classpath/javax/swing/text/html/HTMLDocument.java new file mode 100644 index 0000000..a95e496 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/HTMLDocument.java @@ -0,0 +1,53 @@ +/* HTMLDocument.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.html; + +import javax.swing.text.DefaultStyledDocument; + +/** + * TODO: This class is not yet completetely implemented. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class HTMLDocument extends DefaultStyledDocument +{ + public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event) + { + } +} diff --git a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java new file mode 100644 index 0000000..7ae78ec --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java @@ -0,0 +1,249 @@ +/* HTMLEditorKit.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.html; + +import java.io.Reader; +import java.io.Serializable; + +import javax.swing.text.BadLocationException; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.StyledEditorKit; + +/** + * This class is NOT implemented. This file currently holds only + * declarations of the two enclosing classes, necessary for testing + * the implemented javax.swing.text.html.parser package. + * + * @author No authorship is taken, implement the class and be! + * TODO: replace this header after implementing the class. + */ +public class HTMLEditorKit + extends StyledEditorKit + implements Serializable, Cloneable +{ + /** + * The abstract HTML parser declaration. + */ + public abstract static class Parser + { + /** + * Parse the HTML text, calling various methods of the provided callback + * in response to the occurence of the corresponding HTML constructions. + * @param reader The reader to read the source HTML from. + * @param callback The callback to receive information about the parsed + * HTML structures + * @param ignoreCharSet If true, the parser ignores all charset information + * that may be present in HTML documents. + * @throws IOException, normally if the reader throws one. + */ + public abstract void parse(Reader reader, ParserCallback callback, + boolean ignoreCharSet + ) + throws java.io.IOException; + } + + /** + * The "hook" that receives all information about the HTML document + * structure while parsing it. The methods are invoked by parser + * and should be normally overridden. + */ + public static class ParserCallback + { + /** + * If the tag does not occurs in the html stream directly, but + * is supposed by parser, the tag attribute set contains this additional + * attribute, having value Boolean.True. + */ + public static final Object IMPLIED = "_implied_"; + + /** + * The parser calls this method after it finishes parsing the document. + */ + public void flush() + throws BadLocationException + { + } + + /** + * Handle HTML comment, present in the given position. + * @param comment the comment + * @position the position of the comment in the text being parsed. + */ + public void handleComment(char[] comment, int position) + { + } + + /** + * Notifies about the character sequences, used to separate lines in + * this document. The parser calls this method after it finishes + * parsing the document, but before flush(). + * @param end_of_line The "end of line sequence", one of: \r or \n or \r\n. + */ + public void handleEndOfLineString(String end_of_line) + { + } + + /** + * The method is called when the HTML closing tag ((like </table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param The tag being handled + * @position the tag position in the text being parsed. + */ + public void handleEndTag(HTML.Tag tag, int position) + { + } + + /** + * Handle the error. + * @param message The message, explaining the error. + * @param position The starting position of the fragment that has caused + * the error in the html document being parsed. + */ + public void handleError(String message, int position) + { + } + + /** + * Handle the tag with no content, like <br>. The method is + * called for the elements that, in accordance with the current DTD, + * has an empty content. + * @param tag The tag being handled. + * @param position The tag position in the text being parsed. + */ + public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attributes, + int position + ) + { + } + + /** + * The method is called when the HTML opening tag ((like <table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param tag The tag being handled + * @param position The tag position in the text being parsed + */ + public void handleStartTag(HTML.Tag tag, MutableAttributeSet attributes, + int position + ) + { + } + + /** + * Handle the text section. + * @param text A section text. + * @param position The text position in the HTML document text being parsed. + */ + public void handleText(char[] text, int position) + { + } + } + + /** + * Use serialVersionUID (v1.4) for interoperability. + */ + private static final long serialVersionUID = 8751997116710384592L; + + /** + * Default cascading stylesheed file ("default.css"). + */ + public static final String DEFAULT_CSS = "default.css"; + + /** + * The bold action identifier. + */ + public static final String BOLD_ACTION = "html-bold-action"; + + /** + * The italic action identifier. + */ + public static final String ITALIC_ACTION = "html-italic-action"; + + /** + * The color action indentifier + * (passing the color as an argument). + */ + public static final String COLOR_ACTION = "html-color-action"; + + /** + * The increase font action identifier. + */ + public static final String FONT_CHANGE_BIGGER = "html-font-bigger"; + + /** + * The decrease font action identifier. + */ + public static final String FONT_CHANGE_SMALLER = "html-font-smaller"; + + /** + * Align images at the bottom. + */ + public static final String IMG_ALIGN_BOTTOM = "html-image-align-bottom"; + + /** + * Align images at the middle. + */ + public static final String IMG_ALIGN_MIDDLE = "html-image-align-middle"; + + /** + * Align images at the top. + */ + public static final String IMG_ALIGN_TOP = "html-image-align-top"; + + /** + * Align images at the border. + */ + public static final String IMG_BORDER = "html-image-border"; + + /** + * The "logical style" action identifier, passing that style as parameter. + */ + public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action"; + + /** + * The "ident paragraph left" action. + */ + public static final String PARA_INDENT_LEFT = "html-para-indent-left"; + + /** + * The "ident paragraph right" action. + */ + public static final String PARA_INDENT_RIGHT = "html-para-indent-right"; +} \ 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 new file mode 100644 index 0000000..dc0ab10 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java @@ -0,0 +1,132 @@ +/* HTMLFrameHyperlinkEvent.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.html; + +import java.net.URL; + +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkEvent.EventType; +import javax.swing.text.Element; + +/** + * HTMLFrameHyperlinkEvent transfers information about the link that was + * activated in a frame. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class HTMLFrameHyperlinkEvent + extends HyperlinkEvent +{ + private final String target_frame; + + /** + * Creates a new hypertext link event. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param element The element in the document representing the anchor. + * @param frame - the Frame to display the document in. + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL url, + Element element, String frame) + { + super(source, type, url, frame, element); + target_frame = frame; + } + + /** + * Creates a new hypertext link event. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param frame - the Frame to display the document in. + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL url, + String frame) + { + super(source, type, url, frame); + target_frame = frame; + } + + /** + * Creates a new hypertext link event. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param description The description for this link. + * @param element The element in the document representing the anchor. + * @param frame - the Frame to display the document in. + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL url, + String description, Element element, + String frame) + { + super(source, type, url, description, element); + target_frame = frame; + } + + /** + * Creates a new hypertext link event. + * + * @param source The object this link is associated to. + * @param type The type of event. + * @param url The URL this link pointing too. + * @param description The description for this link. + * @param frame - the Frame to display the document in. + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL url, + String description, String frame) + { + super(source, type, url, description); + target_frame = frame; + } + + /** + * Gets the string, passed as the target frame identifier. + * + * @return the target for the link. + */ + public String getTarget() + { + return target_frame; + } +} diff --git a/libjava/classpath/javax/swing/text/html/package.html b/libjava/classpath/javax/swing/text/html/package.html new file mode 100644 index 0000000..c7e7744 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/package.html @@ -0,0 +1,50 @@ + + + + +GNU Classpath - javax.swing.text.html + + +

Provides supporting classes for web browsers, + web robots, web page content analysers, web editors and + other applications applications working with Hypertext + Markup Language (HTML). +

+ + + diff --git a/libjava/classpath/javax/swing/text/html/parser/AttributeList.java b/libjava/classpath/javax/swing/text/html/parser/AttributeList.java new file mode 100644 index 0000000..5bca0bf --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/AttributeList.java @@ -0,0 +1,294 @@ +/* AttributeList.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.html.parser; + +import gnu.javax.swing.text.html.parser.support.gnuStringIntMapper; + +import java.io.Serializable; + +import java.util.Enumeration; +import java.util.Vector; + +/** + *

+ * Stores the attribute information, obtained by parsing SGML (DTD) tag + * <!ATTLIST .. >

+ *

+ * Elements can have a associated named properties (attributes) having the + * assigned values. The element start tag can have any number of attribute + * value pairs, separated by spaces. They can appear in any order. + * SGML requires you to delimit the attribute values using either double (") + * or single (') quotation marks. In HTML, it is possible + * (but not recommended) to specify the value of an attribute without + * quotation marks. Such attribute value may only contain + * letters, digits, hyphens (-) and periods (.) . + *

+ *

+ * The AttributeList defines a single attribute that additionally + * has a pointer referencing the possible subsequent attribute. + * The whole structure is just a simple linked list, storing all attributes of + * some Element. + * Use the getNext() method repeatedly to see all attributes in + * the list. + *

+ * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public final class AttributeList + implements DTDConstants, Serializable +{ + /** Maps between type names and they string values. */ + private static final gnuStringIntMapper mapper = + new gnuStringIntMapper() + { + protected void create() + { + add("CDATA", DTDConstants.CDATA); + add("ENTITY", DTDConstants.ENTITY); + add("ENTITIES", DTDConstants.ENTITIES); + add("ID", DTDConstants.ID); + add("IDREF", DTDConstants.IDREF); + add("IDREFS", DTDConstants.IDREFS); + add("NAME", DTDConstants.NAME); + add("NAMES", DTDConstants.NAMES); + add("NMTOKEN", DTDConstants.NMTOKEN); + add("NMTOKENS", DTDConstants.NMTOKENS); + add("NOTATION", DTDConstants.NOTATION); + add("NUMBER", DTDConstants.NUMBER); + add("NUMBERS", DTDConstants.NUMBERS); + add("NUTOKEN", DTDConstants.NUTOKEN); + add("NUTOKENS", DTDConstants.NUTOKENS); + } + }; + + /** Use serialVersionUID for interoperability. */ + private static final long serialVersionUID = -1361214058742015233L; + + /** + * The value of ( = pointer to ) the next attribute in the linked list, + * storing all attributes of some Element. Contains null for the + * last attribute. + */ + public AttributeList next; + + /** + * The name of the attribute. The attribute names are case insensitive. + */ + public String name; + + /** + * The default value of this attribute. Equals to null if no default value + * is specified. + */ + public String value; + + /** + * The explicit set of the allowed values of this attribute. Equals to + * null, if this parameter was not specified. + * Values, defined in DTD, are case insensitive. + */ + public Vector values; + + /** + * The modifier of this attribute. This field contains one of the + * following DTD constants: + * + */ + public int modifier; + + /** + * The type of the attribute. The possible values of this field + * (NUMBER, NAME, ID, CDATA and so on) are defined in DTDConstants. + */ + public int type; + + /** + * Creates the attribute with the given name, initializing other fields + * to the default values ( 0 and null ). + * + * @param a_name The name of the attribute. + */ + public AttributeList(String a_name) + { + name = a_name; + } + + /** + * Creates the attribute with the given properties. + * @param a_name The name of the attribute + * @param a_type The type of the attribute. The possible values are defined + * in DTDConstants. + * @param a_modifier The modifier of this attribute. The possible values + * are defined in DTDConstants. + * @param a_default The default value of this attribute + * @param allowed_values The explicit set of the allowed values of + * this attribute + * @param a_next The value of the subsequent instance of the AttributeList, + * representing the next attribute definition for the same element. + * Equals to null for the last attribute definition. + */ + public AttributeList(String a_name, int a_type, int a_modifier, + String a_default, Vector allowed_values, + AttributeList a_next + ) + { + this(a_name); + type = a_type; + modifier = a_modifier; + value = a_default; + values = allowed_values; + next = a_next; + } + + /** + * Get the modifier of this attribute. This field contains one of the + * following DTD constants: + * + */ + public int getModifier() + { + return modifier; + } + + /** + * Get the name of the attribute. + * The value is returned as it was supplied to a + * constructor, preserving the character case. + */ + public String getName() + { + return name; + } + + /** + * Get the value of ( = pointer to ) the next attribute in the linked list, + * storing all attributes of some Element. Contains null for the + * last attribute. + */ + public AttributeList getNext() + { + return next; + } + + /** + * Get the type of the attribute. The possible values of this field + * (NUMBER, NAME, ID, CDATA and so on) are defined in DTDConstants. + */ + public int getType() + { + return type; + } + + /** + * Get the default value of this attribute. + */ + public String getValue() + { + return value; + } + + /** + * Get the allowed values of this attribute. + */ + public Enumeration getValues() + { + return values.elements(); + } + + /** + * Converts a string value, representing a valid SGLM attribute type, + * into the corresponding value, defined in DTDConstants. + * @param typeName the name of the type (character case is ignored). + * @return a value from DTDConstants or DTDConstants.ANY if the + * string is not representing a known type. The known attribute types + * in this implementation are CDATA, ENTITY, ENTITIES, ID, IDREF, IDREFS, + * NAME, NAMES, NMTOKEN, NMTOKENS, NOTATION, NUMBER, NUMBERS, NUTOKEN and + * NUTOKENS. + * @throws NullPointerException if the passed parameter is null. + */ + public static int name2type(String typeName) + { + return mapper.get(typeName.toUpperCase()); + } + + /** + * Returns the attribute name. + */ + public String toString() + { + return name; + } + + /** + * Converts a value from DTDConstants into the string representation. + * @param type - an integer value of the public static integer field, + * defined in the DTDConstants class. + * @return a corresponding SGML DTD keyword (UPPERCASE) or null if there + * are no attribute type constant having the given value. + */ + public static String type2name(int type) + { + return mapper.get(type); + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/ContentModel.java b/libjava/classpath/javax/swing/text/html/parser/ContentModel.java new file mode 100644 index 0000000..deb7b16 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/ContentModel.java @@ -0,0 +1,218 @@ +/* ContentModel.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.html.parser; + +import gnu.javax.swing.text.html.parser.models.transformer; + +import java.io.Serializable; + +import java.util.Vector; + +/** + * A representation of the element content. The instances of this class + * can be arranged into the linked list, representing a BNF expression. + * The content model is constructed as a branched tree structure in the + * following way: + *
+ * a = new ContentModel('+', A, null); // a reprensents A+
+ * b = new ContentModel('&', B, a); // b represents B & A+
+ * c = new ContentModel('*', b, null); // c represents ( B & A+) *
+ * d = new ContentModel('|', new ContentModel('*', A, null),
+ *          new ContentModel('?', B, null)); // d represents ( A* | B? )
+ * 
+ * where the valid operations are: + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public final class ContentModel + implements Serializable +{ + /** Use serialVersionUID for interoperability. */ + private static final long serialVersionUID = -1130825523866321257L; + + /** + * The next content model model ( = pointer to the next element of + * the linked list) for the binary expression (',','&' or '|'). Null + * for the last element in the list. + */ + public ContentModel next; + + /** + * The document content, containing either Element or the enclosed + * content model (that would be in the parentheses in BNF expression). + */ + public Object content; + + /** + * Specifies the BNF operation between this node and the node, + * stored in the field next (or for this node, if it is + * an unary operation. + */ + public int type; + + /** Create a content model initializing all fields to default values. */ + public ContentModel() + { + } + + /** + * Create a content model, consisting of the single element. + * Examples: + * + * a = new ContentModel('+', A, null); // a reprensents A+ + * b = new ContentModel('&', B, a); // b represents B & A+ + * c = new ContentModel('*', b, null); // c represents ( B & A+) * + * d = new ContentModel('|', A, + * new ContentModel('?',b, null); + * // d represents + * + */ + public ContentModel(Element a_content) + { + content = a_content; + } + + /** + * Create a content model, involving expression of the given type. + * @param a_type The expression operation type ('*','?' or '+' + * @param a_content The content for that the expression is applied. + */ + public ContentModel(int a_type, ContentModel a_content) + { + content = a_content; + type = a_type; + } + + /** + * Create a content model, involving binary expression of the given type. + * @param a_type The expression operation type ( ',', '|' or '&'). + * @param a_content The content of the left part of the expression. + * @param a_next The content model, representing the right part of the + * expression. + */ + public ContentModel(int a_type, Object a_content, ContentModel a_next) + { + content = a_content; + type = a_type; + next = a_next; + } + + /** + * Adds all list elements to the given vector, ignoring the + * operations between the elements. The old vector values are not + * discarded. + * @param elements - a vector to add the values to. + */ + public void getElements(Vector elements) + { + ContentModel c = this; + + while (c != null) + { + elements.add(c.content); + c = c.next; + } + } + + /** + * Checks if the content model matches an empty input stream. + * The empty content is created using SGML DTD keyword EMPTY. + * The empty model is a model with the content field equal to null. + * + * @return true if the content field is equal to null. + */ + public boolean empty() + { + return content == null; + } + + /** + * Get the element, stored in the next.content. + * The method is programmed as the part of the standard API, but not + * used in this implementation. + * @return the value of the field next. + */ + public Element first() + { + return (Element) next.content; + } + + /** + * Checks if this object can potentially be the first token in the + * ContenModel list. The method is programmed as the part of the + * standard API, but not used in this implementation. + */ + public boolean first(Object token) + { + ContentModel c = this; + while (c.next != null) + { + if (c.content != null && c.content.toString().equals(token.toString()) && + c.type != ',' + ) + + // Agree if the operation with the preceeding element + // is not the comma operation. + return true; + c = c.next; + } + return false; + } + + /** + * Returns a string representation (an expression) of this content model. + * The expression has BNF-like syntax, except the absence of the + * unary operator is additionally indicated by " ' ". It is + * advisable to check the created models for correctness using this + * method. + */ + public String toString() + { + return transformer.transform(this).toString(); + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/DTD.java b/libjava/classpath/javax/swing/text/html/parser/DTD.java new file mode 100644 index 0000000..63d03ea --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/DTD.java @@ -0,0 +1,607 @@ +/* DTD.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.html.parser; + +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.BitSet; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.util.Vector; + +/** + *

Representation or the SGML DTD document. + * Provides basis for describing a syntax of the + * HTML documents. The fields of this class are NOT initialized in + * constructor. You need to do this separately before passing this data + * structure to the HTML parser. The subclasses with the fields, pre- + * initialized, for example, for HTML 4.01, can be available only between + * the implementation specific classes + * ( for example, {@link gnu.javax.swing.text.html.parser.HTML_401F } + * in this implementation).

+ *

+ * If you need more information about SGML DTD documents, + * the author suggests to read SGML tutorial on + * {@link http://www.w3.org/TR/WD-html40-970708/intro/sgmltut.html}. + * We also recommend Goldfarb C.F (1991) The SGML Handbook, + * Oxford University Press, 688 p, ISBN: 0198537379. + *

+ *

+ * Warning: the html, head and other tag fields will only be automatically + * assigned if the VM has the correctly implemented reflection mechanism. + * As these fields are not used anywhere in the implementation, not + * exception will be thrown in the opposite case. + *

+ * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class DTD + implements DTDConstants +{ + /** + * The version of the persistent data format. + */ + public static int FILE_VERSION = 1; + + /** + * The table of existing available DTDs. + */ + static Hashtable dtdHash = new Hashtable(); + + /** + * The applet element for this DTD. + */ + public Element applet; + + /** + * The base element for this DTD. + */ + public Element base; + + /** + * The body element for this DTD. + */ + public Element body; + + /** + * The head element for this DTD. + */ + public Element head; + + /** + * The html element for this DTD. + */ + public Element html; + + /** + * The isindex element of for this DTD. + */ + public Element isindex; + + /** + * The meta element for this DTD. + */ + public Element meta; + + /** + * The p element for this DTD. + */ + public Element p; + + /** + * The param element for this DTD. + */ + public Element param; + + /** + * The pcdata for this DTD. + */ + public Element pcdata; + + /** + * The title element for this DTD. + */ + public Element title; + + /** + * The element for accessing all DTD elements by name. + */ + public Hashtable elementHash = new Hashtable(); + + /** + * The entity table for accessing all DTD entities by name. + */ + public Hashtable entityHash = new Hashtable(); + + /** + * The name of this DTD. + */ + public String name; + + /** + * Contains all elements in this DTD. The + * javax.swing.text.html.parser.Element#index field of all elements + * in this vector is set to the element position in this vector. + */ + public Vector elements = new Vector(); + + /** Create a new DTD with the specified name. */ + protected DTD(String a_name) + { + name = a_name; + } + + /** Get this DTD by name. The current implementation + * only looks in the internal table of DTD documents. If no corresponding + * entry is found, the new entry is created, placed into + * the table and returned. */ + public static DTD getDTD(String name) + throws IOException + { + DTD d = (DTD) dtdHash.get(name); + + if (d == null) + { + d = new DTD(name); + dtdHash.put(d.name, d); + } + + return d; + } + + /** + * Get the element by the element name. If the element is not yet + * defined, it is newly created and placed into the element table. + * If the element name matches (ingoring case) a public non static + * element field in this class, this field is assigned to the value + * of the newly created element. + */ + public Element getElement(String element_name) + { + return newElement(element_name); + } + + /** + * Get the element by the value of its + * {@link javax.swing.text.html.parser.Element#index} field. + */ + public Element getElement(int index) + { + return (Element) elements.get(index); + } + + /** + * Get the entity with the given identifier. + * @param id that can be returned by + * {@link javax.swing.text.html.parser.Entity#name2type(String an_entity)} + * @return The entity from this DTD or null if there is no entity with + * such id or such entity is not present in the table of this instance. + */ + public Entity getEntity(int id) + { + String name = Entity.mapper.get(id); + + if (name != null) + return (Entity) entityHash.get(name); + else + return null; + } + + /** + * Get the named entity by its name. + */ + public Entity getEntity(String entity_name) + { + return (Entity) entityHash.get(entity_name); + } + + /** + * Get the name of this instance of DTD + */ + public String getName() + { + return name; + } + + /** + * Creates, adds into the entity table and returns the + * character entity like &lt; + * (means '<' ); + * @param name The entity name (without heading & and closing ;) + * @param type The entity type + * @param character The entity value (single character) + * @return The created entity + */ + public Entity defEntity(String name, int type, int character) + { + Entity e = newEntity(name, type); + e.data = new char[] { (char) character }; + return e; + } + + /** + * Define the attributes for the element with the given name. + * If the element is not exist, it is created. + * @param forElement + * @param attributes + */ + public void defineAttributes(String forElement, AttributeList attributes) + { + Element e = (Element) elementHash.get(forElement.toLowerCase()); + + if (e == null) + e = newElement(forElement); + + e.atts = attributes; + } + + /** + * Defines the element and adds it to the element table. Sets the + * Element.index field to the value, unique for this + * instance of DTD. If the element with the given name already exists, + * replaces all other its settings by the method argument values. + * @param name the name of the element + * @param type the type of the element + * @param headless true if the element needs no starting tag + * (should not occur in HTML). + * @param tailless true if the element needs no ending tag (like + * <hr> + * @param content the element content + * @param exclusions the set of elements that must not occur inside + * this element. The Element.index value defines which + * bit in this bitset corresponds to that element. + * @param inclusions the set of elements that can occur inside this + * element. the Element.index value defines which + * bit in this bitset corresponds to that element. + * @param attributes the element attributes. + * @return the newly defined element. + */ + public Element defineElement(String name, int type, boolean headless, + boolean tailless, ContentModel content, + BitSet exclusions, BitSet inclusions, + AttributeList attributes + ) + { + Element e = newElement(name); + e.type = type; + e.oStart = headless; + e.oEnd = tailless; + e.content = content; + e.exclusions = exclusions; + e.inclusions = inclusions; + e.atts = attributes; + + return e; + } + + /** + * Creates, intializes and adds to the entity table the new + * entity. + * @param name the name of the entity + * @param type the type of the entity + * @param data the data section of the entity + * @return the created entity + */ + public Entity defineEntity(String name, int type, char[] data) + { + Entity e = newEntity(name, type); + e.data = data; + + return e; + } + + /** Place this DTD into the DTD table. */ + public static void putDTDHash(String name, DTD dtd) + { + dtdHash.put(name, dtd); + } + + /** + *

Reads DTD from an archived format. This format is not standardized + * and differs between implementations.

This implementation + * reads and defines all entities and elements using + * ObjectInputStream. The elements and entities can be written into the + * stream in any order. The objects other than elements and entities + * are ignored.

+ * @param stream A data stream to read from. + * @throws java.io.IOException If one is thrown by the input stream + */ + public void read(DataInputStream stream) + throws java.io.IOException + { + ObjectInputStream oi = new ObjectInputStream(stream); + Object def; + try + { + while (true) + { + def = oi.readObject(); + if (def instanceof Element) + { + Element e = (Element) def; + elementHash.put(e.name.toLowerCase(), e); + assignField(e); + } + else if (def instanceof Entity) + { + Entity e = (Entity) def; + entityHash.put(e.name, e); + } + } + } + catch (ClassNotFoundException ex) + { + throw new IOException(ex.getMessage()); + } + catch (EOFException ex) + { + // ok EOF + } + } + + /** + * Returns the name of this instance of DTD. + */ + public String toString() + { + return name; + } + + /** + * Creates and returns new attribute (not an attribute list). + * @param name the name of this attribute + * @param type the type of this attribute (FIXED, IMPLIED or + * REQUIRED from DTDConstants). + * @param modifier the modifier of this attribute + * @param default_value the default value of this attribute + * @param allowed_values the allowed values of this attribute. The multiple + * possible values in this parameter are supposed to be separated by + * '|', same as in SGML DTD <!ATTLIST tag. This parameter + * can be null if no list of allowed values is specified. + * @param atts the previous attribute of this element. This is + * placed to the field + * {@link javax.swing.text.html.parser.AttributeList#next }, + * creating a linked list. + * @return + */ + protected AttributeList defAttributeList(String name, int type, int modifier, + String default_value, + String allowed_values, + AttributeList atts + ) + { + AttributeList al = new AttributeList(name); + al.modifier = modifier; + al.value = default_value; + al.next = atts; + + if (allowed_values != null) + { + StringTokenizer st = new StringTokenizer(allowed_values, " \t|"); + Vector v = new Vector(st.countTokens()); + + while (st.hasMoreTokens()) + v.add(st.nextToken()); + + al.values = v; + } + + return al; + } + + /** + * Creates a new content model. + * @param type specifies the BNF operation for this content model. + * The valid operations are documented in the + * {@link javax.swing.text.html.parser.ContentModel#type }. + * @param content the content of this content model + * @param next if the content model is specified by BNF-like + * expression, contains the rest of this expression. + * @return The newly created content model. + */ + protected ContentModel defContentModel(int type, Object content, + ContentModel next + ) + { + ContentModel model = new ContentModel(); + model.type = type; + model.next = next; + model.content = content; + + return model; + } + + /** + * Defines a new element and adds it to the element table. + * If the element alredy exists, + * overrides it settings with the specified values. + * @param name the name of the new element + * @param type the type of the element + * @param headless true if the element needs no starting tag + * @param tailless true if the element needs no closing tag + * @param content the element content. + * @param exclusions the elements that must be excluded from the + * content of this element, in all levels of the hierarchy. + * @param inclusions the elements that can be included as the + * content of this element. + * @param attributes the element attributes. + * @return the created or updated element. + */ + protected Element defElement(String name, int type, boolean headless, + boolean tailless, ContentModel content, + String[] exclusions, String[] inclusions, + AttributeList attributes + ) + { + // compute the bit sets + BitSet exclude = bitSet(exclusions); + BitSet include = bitSet(inclusions); + + Element e = + defineElement(name, type, headless, tailless, content, exclude, include, + attributes + ); + + return e; + } + + /** + * Creates, intializes and adds to the entity table the new + * entity. + * @param name the name of the entity + * @param type the type of the entity + * @param data the data section of the entity + * @return the created entity + */ + protected Entity defEntity(String name, int type, String data) + { + Entity e = newEntity(name, type); + e.data = data.toCharArray(); + + return e; + } + + private void assignField(Element e) + { + String element_name = e.name; + try + { + // Assign the field via reflection. + Field f = getClass().getField(element_name.toLowerCase()); + if ((f.getModifiers() & Modifier.PUBLIC) != 0) + if ((f.getModifiers() & Modifier.STATIC) == 0) + if (f.getType().isAssignableFrom(e.getClass())) + f.set(this, e); + } + catch (IllegalAccessException ex) + { + unexpected(ex); + } + catch (NoSuchFieldException ex) + { + // This is ok. + } + + // Some virtual machines may still lack the proper + // implementation of reflection. As the tag fields + // are not used anywhere in this implementation, + // (and this class is also rarely used by the end user), + // it may be better not to crash everything by throwing an error + // for each case when the HTML parsing is required. + catch (Throwable t) + { + // This VM has no reflection mechanism implemented! + if (t instanceof OutOfMemoryError) + throw (Error) t; + } + } + + /** + * Create the bit set for this array of elements. + * The unknown elements are automatically defined and added + * to the element table. + * @param elements + * @return + */ + private BitSet bitSet(String[] elements) + { + BitSet b = new BitSet(); + + for (int i = 0; i < elements.length; i++) + { + Element e = getElement(elements [ i ]); + + if (e == null) + e = newElement(elements [ i ]); + + b.set(e.index); + } + + return b; + } + + /** + * Find the element with the given name in the element table. + * If not find, create a new element with this name and add to the + * table. + * @param name the name of the element + * @return the found or created element. + */ + private Element newElement(String name) + { + Element e = (Element) elementHash.get(name.toLowerCase()); + + if (e == null) + { + e = new Element(); + e.name = name; + e.index = elements.size(); + elements.add(e); + elementHash.put(e.name.toLowerCase(), e); + assignField(e); + } + return e; + } + + /** + * Creates and adds to the element table the entity with an + * unitialized data section. Used internally. + * @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) + { + Entity e = new Entity(name, type, null); + entityHash.put(e.name, e); + return e; + } + + private void unexpected(Exception ex) + { + throw new Error("This should never happen, report a bug", ex); + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/DTDConstants.java b/libjava/classpath/javax/swing/text/html/parser/DTDConstants.java new file mode 100644 index 0000000..a771264 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/DTDConstants.java @@ -0,0 +1,290 @@ +/* DTDConstants.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.html.parser; + +/** + *

This class defines the SGML basic types, used for describing HTML 4.01 + * at {@link http://www.w3.org/TR/html4/types.html }. Not all constants, + * defined here, are actually used in HTML 4.01 SGML specification. Some others + * are defined just as part of the required implementation. + *

+ *

+ * If you need more information about SGML DTD documents, + * the author suggests to read SGML tutorial on + * {@link http://www.w3.org/TR/WD-html40-970708/intro/sgmltut.html}. + * We also recommend Goldfarb C.F (1991) The SGML Handbook, + * Oxford University Press, 688 p, ISBN: 0198537379. + *

+ * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public interface DTDConstants +{ + /* ----- The data types, used in HTML 4.01 SGML definition: ---- */ + + /** + * The CDATA (Character data) constant, specifes the content model, + * consisting of characters only. In SGML for HTML 4.01, the character + * entities must be replaced by characters, the line feeds must be + * ignored and any number of the subsequent carriage returns or tabs + * must be replaced by a single space. + */ + int CDATA = 1; + + /** + * The EMPTY constant, means the element with no content. + */ + int EMPTY = 17; + + /** + * The ID constant, means that the token is the unique identifier. + * This identifier can be referenced by attribute with value of IDREF. + * The identifier must begin with letter, followed by any number of + * letters, digits, hyphens, underscores, colons and periods. + */ + int ID = 4; + + /** + * The IDREF constant, specifies reference to a valid ID within + * the document. + */ + int IDREF = 5; + + /** + * The IDREFS constant, a space separated list of IDREFs + */ + int IDREFS = 6; + + /** + * The NAME constant, means the token that + * must begin with letter, followed by any number of + * letters, digits, hyphens, underscores, colons and periods. + */ + int NAME = 7; + + /** + * The NAMES constant, specifies a space separated of NAMEs. + */ + int NAMES = 8; + + /** + * The NMTOKEN constant, specifies the attribute, consisting of + * characters that can be either digits or alphabetic characters). + */ + int NMTOKEN = 9; + + /** + * The NMTOKENS constant, specifies a list of NMTOKENs. + */ + int NMTOKENS = 10; + + /** + * The NOTATION constant, a previously defined data type. + */ + int NOTATION = 11; + + /** + * The NUMBER constant (means that the attribute consists of at least + * one decimal digit). + */ + int NUMBER = 12; + + /** + * The NUMBERS constant, specifies a space separated list of NUMBERs. + */ + int NUMBERS = 13; + + /** + * The NUTOKEN constant. + */ + int NUTOKEN = 14; + + /** + * The NUTOKENS constant. + */ + int NUTOKENS = 15; + + /* ------- + The entity scope constants. + As these four constants are combined with the bitwise OR, + they are defined in the hexadecimal notation. + The reason of setting the two bits at once (for PUBLIC and SYSTEM) + is probably historical. ----- */ + + /** + * The PUBLIC constant, specifies the public entity. The PUBLIC entities + * are assumed to be known to many systems so that a full declaration + * need not be transmitted. For example, + * <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"> + */ + int PUBLIC = 0xA; + + /** + * The SYSTEM constant, specifies the system entitiy. The system entities + * are assumed to be known but require the clear identifer + * (like the file path), where they can be found in the system. + * For example, + * <DOCTYPE html SYSTEM "/path/to/file.dtd"> . + */ + int SYSTEM = 0x11; + + /** + * The PARAMETER constant, specifies that entity is only valid + * inside SGML DTD scope. + */ + int PARAMETER = 0x40000; + + /** + * The GENERAL constant, specifies theat the entity is valid in the + * whole HTML document scope. + */ + int GENERAL = 0x10000; + + /* ---- The constants, defining if the element attribute is required, + fixed or implied. ---- */ + + /** + * The attribute modifier #REQUIRED constant, indicates that the + * value must be supplied. + */ + int REQUIRED = 2; + + /** + * The attribute modifier #FIXED constant, means that the attribute has + * the fixed value that cannot be changed. + */ + int FIXED = 1; + + /** + * The attribute modifier #IMPLIED constant, + * indicating that for this attribute the user agent must provide + * the value itself. + */ + int IMPLIED = 5; + + /** + * The attribute modifier #CURRENT constant, specifies the value + * that at any point in the document is the last value supplied for + * that element. A value is required to be supplied for the first + * occurrence of an element + */ + int CURRENT = 3; + + /** + * The attribute modifier #CONREF constant, specifies the IDREF value of + * the reference to content in another location of the document. + * The element with this attribute is empty, the content from + * that another location must be used instead. + */ + int CONREF = 4; + + /* ----- Constants, defining if the element + start and end tags are required. ---- */ + + /** + * The STARTTAG, meaning that the element needs a starting tag. + */ + int STARTTAG = 13; + + /** + * The ENDTAG constant, meaning that the element needs a closing tag. + */ + int ENDTAG = 14; + + /* ----- Other constants: ----- */ + + /** + * The ANY constant, specifies + * an attribute, consisting from arbitrary characters. + */ + int ANY = 19; + + /** + * The DEFAULT constant, specifies the default value. + */ + int DEFAULT = 131072; + + /** + * The ENTITIES constant (list of ENTITYes) + */ + int ENTITIES = 3; + + /** + * The ENTITY constant, meaning the numeric or symbolic name of some + * HTML data. + */ + int ENTITY = 2; + + /** + * The MD constant. + */ + int MD = 16; + + /** + * The MODEL constant. + */ + int MODEL = 18; + + /** + * The MS constant. + */ + int MS = 15; + + /** + * The PI (Processing Instruction) constant, specifies a processing + * instruction. Processing instructions are used to embed information + * intended for specific applications. + */ + int PI = 12; + + /** + * The RCDATA constant (Entity References and Character Data), specifies + * the content model, consisting of characters AND entities. The + * "<" is threated as an ordinary character, but + * "&name;" still means the general entity with + * the given name. + */ + int RCDATA = 16; + + /** + * The SDATA constant. Means that the value contains the entity name + * and the replacement value of a character entity reference. + */ + int SDATA = 11; +} diff --git a/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java b/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java new file mode 100644 index 0000000..c706f4d --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java @@ -0,0 +1,261 @@ +/* DocumentParser.java -- A parser for HTML documents. + 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.parser; + +import gnu.javax.swing.text.html.parser.htmlAttributeSet; +import javax.swing.text.html.parser.Parser; + +import java.io.IOException; +import java.io.Reader; + +import javax.swing.text.BadLocationException; +import javax.swing.text.html.HTMLEditorKit; + +/** + *

A simple error-tolerant HTML parser that uses a DTD document + * to access data on the possible tokens, arguments and syntax.

+ *

The parser reads an HTML content from a Reader and calls various + * notifying methods (which should be overridden in a subclass) + * when tags or data are encountered.

+ *

Some HTML elements need no opening or closing tags. The + * task of this parser is to invoke the tag handling methods also when + * the tags are not explicitly specified and must be supposed using + * information, stored in the DTD. + * For example, parsing the document + *

<table><tr><td>a<td>b<td>c</tr>
+ * will invoke exactly the handling methods exactly in the same order + * (and with the same parameters) as if parsing the document:
+ * <html><head></head><body><table>< + * tbody><tr><td>a</td><td>b + * </td><td>c</td></tr>< + * /tbody></table></body></html>

+ * (supposed tags are given in italics). The parser also supports + * obsolete elements of HTML syntax.

+ *

+ * In this implementation, DocumentParser is directly derived from its + * ancestor without changes of functionality. + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class DocumentParser + extends Parser + implements DTDConstants +{ + /** + * The enclosed working parser class. + */ + private class gnuParser + extends gnu.javax.swing.text.html.parser.support.Parser + { + private gnuParser(DTD d) + { + super(d); + } + + protected final void handleComment(char[] comment) + { + parser.handleComment(comment); + callBack.handleComment(comment, hTag.where.startPosition); + } + + protected final void handleEmptyTag(TagElement tag) + throws javax.swing.text.ChangedCharSetException + { + parser.handleEmptyTag(tag); + callBack.handleSimpleTag(tag.getHTMLTag(), getAttributes(), + hTag.where.startPosition + ); + } + + protected final void handleEndTag(TagElement tag) + { + parser.handleEndTag(tag); + callBack.handleEndTag(tag.getHTMLTag(), hTag.where.startPosition); + } + + protected final void handleError(int line, String message) + { + parser.handleError(line, message); + callBack.handleError(message, hTag.where.startPosition); + } + + protected final void handleStartTag(TagElement tag) + { + parser.handleStartTag(tag); + htmlAttributeSet attributes = gnu.getAttributes(); + + if (tag.fictional()) + attributes.addAttribute(HTMLEditorKit.ParserCallback.IMPLIED, + Boolean.TRUE + ); + + callBack.handleStartTag(tag.getHTMLTag(), attributes, + hTag.where.startPosition + ); + } + + protected final void handleText(char[] text) + { + parser.handleText(text); + callBack.handleText(text, hTag.where.startPosition); + } + + DTD getDTD() + { + return dtd; + } + } + + /** + * This field is used to access the identically named + * methods of the outer class. + * This is package-private to avoid an accessor method. + */ + DocumentParser parser = this; + + /** + * The callback. + * This is package-private to avoid an accessor method. + */ + HTMLEditorKit.ParserCallback callBack; + + /** + * The reference to the working class of HTML parser that is + * actually used to parse the document. + * This is package-private to avoid an accessor method. + */ + gnuParser gnu; + + /** + * Creates a new parser that uses the given DTD to access data on the + * possible tokens, arguments and syntax. There is no single - step way + * to get a default DTD; you must either refer to the implementation - + * 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) + { + super(a_dtd); + gnu = new gnuParser(a_dtd); + } + + /** + * Parses the HTML document, calling methods of the provided + * callback. This method must be multithread - safe. + * @param reader The reader to read the HTML document from + * @param callback The callback that is notifyed about the presence + * of HTML elements in the document. + * @param ignoreCharSet If thrue, any charset changes during parsing + * are ignored. + * @throws java.io.IOException + */ + public void parse(Reader reader, HTMLEditorKit.ParserCallback a_callback, + boolean ignoreCharSet + ) + throws IOException + { + callBack = a_callback; + gnu.parse(reader); + + callBack.handleEndOfLineString(gnu.getEndOfLineSequence()); + try + { + callBack.flush(); + } + catch (BadLocationException ex) + { + // Convert this into the supported type of exception. + throw new IOException(ex.getMessage()); + } + } + + /** + * Handle HTML comment. The default method returns without action. + * @param comment the comment being handled + */ + protected void handleComment(char[] comment) + { + } + + /** + * Handle the tag with no content, like <br>. The method is + * called for the elements that, in accordance with the current DTD, + * has an empty content. + * @param tag the tag being handled. + * @throws javax.swing.text.ChangedCharSetException + */ + protected void handleEmptyTag(TagElement tag) + throws javax.swing.text.ChangedCharSetException + { + } + + /** + * The method is called when the HTML closing tag ((like </table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param The tag being handled + */ + protected void handleEndTag(TagElement tag) + { + } + + /* Handle error that has occured in the given line. */ + protected void handleError(int line, String message) + { + } + + /** + * The method is called when the HTML opening tag ((like <table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param The tag being handled + */ + protected void handleStartTag(TagElement tag) + { + } + + /** + * Handle the text section. + * @param text a section text. + */ + protected void handleText(char[] text) + { + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/Element.java b/libjava/classpath/javax/swing/text/html/parser/Element.java new file mode 100644 index 0000000..f0a0f33 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/Element.java @@ -0,0 +1,317 @@ +/* Element.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.html.parser; + +import gnu.javax.swing.text.html.parser.support.gnuStringIntMapper; + +import java.io.Serializable; + +import java.util.BitSet; + +/** + *

+ * Stores the element information, obtained by parsing SGML DTD + * tag <!ELEMENT .. >. This class has no public + * constructor and can only be instantiated using the + * {@link javax.swing.text.html.parser.DTD } methods

+ * + *

SGML defines elements that represent structures or + * behavior. An element typically consists of a start tag, content, and an + * end tag. Hence the elements are not tags. The HTML 4.0 definition specifies + * that some elements are not required to have the end tags. Also, some + * HTML elements (like <hr>) have no content. Element names + * are case sensitive.

+ * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public final class Element + implements DTDConstants, Serializable +{ + /** + * Package level mapper between type names and they string values. + */ + static final gnuStringIntMapper mapper = + new gnuStringIntMapper() + { + protected void create() + { + add("CDATA", DTDConstants.CDATA); + add("RCDATA", DTDConstants.RCDATA); + add("EMPTY", DTDConstants.EMPTY); + add("ANY", DTDConstants.ANY); + } + }; + + /** Use serialVersionUID for interoperability. */ + private static final long serialVersionUID = -6717939384601675586L; + + /** + * The element attributes. + */ + public AttributeList atts; + + /** + * Contains refernces to elements that must NOT occur inside this element, + * at any level of hierarchy. + */ + public BitSet exclusions; + + /** + * Contains refernces to elements that must CAN occur inside this element, + * at any level of hierarchy. + */ + public BitSet inclusions; + + /** + * The content model, defining elements, entities and DTD text + * that may/may not occur inside this element. + */ + public ContentModel content; + + /** + * A field to store additional user data for this Element. + */ + public Object data; + + /** + * The element name. + */ + public String name; + + /** + * True is this element need not to have the closing tag, false + * otherwise. The HTML 4.0 definition specifies + * that some elements (like <hr>are + * not required to have the end tags. + */ + public boolean oEnd; + + /** + * True is this element need not to have the starting tag, false + * otherwise. The HTML 4.0 definition specifies + * that some elements (like <head> or + * <body>) are + * not required to have the start tags. + + */ + public boolean oStart; + + /** + * This field contains the unique integer identifier of this Element, + * used to refer the element (more exactly, the element flag) + * in inclusions and exclusions bit set. + */ + public int index; + + /** + * The element type, containing value, defined in DTDConstants. + * In this implementation, the element type can be + * CDATA, RCDATA, EMPTY or ANY. + */ + public int type; + + /** + * 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() + { + } + + /** + * Converts the string representation of the element type + * into its unique integer identifier, defined in DTDConstants. + * @param a_type A name of the type + * @return DTDConstants.CDATA, DTDConstants.RCDATA, DTDConstants.EMPTY, + * DTDConstants.ANY or null if the type name is not + * "CDATA", "RCDATA", "EMPTY" or "ANY". This function is case sensitive. + * @throws NullPointerException if a_type is null. + */ + public static int name2type(String a_type) + { + return mapper.get(a_type); + } + + /** + * Get the element attribute by name. + * @param attribute the attribute name, case insensitive. + * @return the correspoding attribute of this element. The class, + * for storing as attribute list, as a single attribute, is used to + * store a single attribute in this case. + * @throws NullPointerException if the attribute name is null. + */ + public AttributeList getAttribute(String attribute) + { + AttributeList a = atts; + + while (a != null && !attribute.equalsIgnoreCase(a.name)) + a = a.next; + + return a; + } + + /** + * Get the element attribute by its value. + * @param a_value the attribute value, case insensitive. + * @return the correspoding attribute of this element. The class, + * for storing as attribute list, as a single attribute, is used to + * store a single attribute in this case. If there are several + * attributes with the same value, there is no garranty, which one + * is returned. + */ + public AttributeList getAttributeByValue(String a_value) + { + AttributeList a = atts; + + if (a_value == null) + { + while (a != null) + { + if (a.value == null) + return a; + + a = a.next; + } + } + else + { + while (a != null) + { + if (a.value != null && a_value.equalsIgnoreCase(a.value)) + return a; + + a = a.next; + } + } + + return null; + } + + /** + * Get all attributes of this document as an attribute list. + * @return + */ + public AttributeList getAttributes() + { + return atts; + } + + /** + * Get the content model, defining elements, entities and DTD text + * that may/may not occur inside this element. + */ + public ContentModel getContent() + { + return content; + } + + /** + * Returns true for the element with no content. + * Empty elements are defined with the SGML DTD keyword "EMPTY". + * @return true if content model field (content) method is equal to + * null or its method empty() returns true. + */ + public boolean isEmpty() + { + return content == null || content.empty(); + } + + /** + * Get the unique integer identifier of this Element, + * used to refer the element (more exactly, the element flag) + * in inclusions and exclusions bit set. + * WARNING: This value may not be the same between different + * implementations. + */ + public int getIndex() + { + return index; + } + + /** + * Get the element name. + */ + public String getName() + { + return name; + } + + /** + * Get the element type. + * @return one of the values, defined DTDConstants. + * In this implementation, the element type can be + * CDATA, RCDATA, EMPTY or ANY. + */ + public int getType() + { + return type; + } + + /** + * True is this element need not to have the starting tag, false + * otherwise.s element need not to have the closing tag, false + * otherwise. The HTML 4.0 definition specifies + * that some elements (like <hr>are + * not required to have the end tags. + */ + public boolean omitEnd() + { + return oEnd; + } + + /** + * True is this element need not to have the closing tag, false + * otherwise. The HTML 4.0 definition specifies + * that some elements (like <head> or + * <body>) are + * not required to have the start tags. + */ + public boolean omitStart() + { + return oStart; + } + + /** + * Returns the name of this element. + */ + public String toString() + { + return name; + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/Entity.java b/libjava/classpath/javax/swing/text/html/parser/Entity.java new file mode 100644 index 0000000..766984f --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/Entity.java @@ -0,0 +1,185 @@ +/* Entity.java -- Stores information, obtained by parsing SGML DTL + * <!ENTITY % .. > tag + 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.parser; + +import gnu.javax.swing.text.html.parser.support.gnuStringIntMapper; + +import java.io.Serializable; + +/** + *

Stores information, obtained by parsing SGML DTL + * <!ENTITY % .. > tag.

+ *

+ * The entity defines some kind of macro that can be used elsewhere in + * the document. + * When the macro is referred to by the name in the DTD, it is expanded into + * a string + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public final class Entity + implements DTDConstants, Serializable +{ + /** + * Package level mapper between type names and they string values. + */ + final static gnuStringIntMapper mapper = + new gnuStringIntMapper() + { + protected void create() + { + add("ANY", DTDConstants.ANY); + add("CDATA", DTDConstants.CDATA); + add("PUBLIC", DTDConstants.PUBLIC); + add("SDATA", DTDConstants.SDATA); + add("PI", DTDConstants.PI); + add("STARTTAG", DTDConstants.STARTTAG); + add("ENDTAG", DTDConstants.ENDTAG); + add("MS", DTDConstants.MS); + add("MD", DTDConstants.MD); + add("SYSTEM", DTDConstants.SYSTEM); + } + }; + + /** + * The entity name. + */ + public String name; + + /** + * The entity data + */ + public char[] data; + + /** + * The entity type. + */ + public int type; + + /** + * String representation of the entity data. + */ + private String sdata; + + /** + * Create a new entity + * @param a_name the entity name + * @param a_type the entity type + * @param a_data the data replacing the entity reference + */ + public Entity(String a_name, int a_type, char[] a_data) + { + name = a_name; + type = a_type; + data = a_data; + } + + /** + * Converts a given string to the corresponding entity type. + * @return a value, defined in DTDConstants (one of + * PUBLIC, CDATA, SDATA, PI, STARTTAG, ENDTAG, MS, MD, SYSTEM) + * or CDATA if the parameter is not a valid entity type. + */ + public static int name2type(String an_entity) + { + int r = mapper.get(an_entity); + return (r == 0) ? DTDConstants.CDATA : r; + } + + /** + * Get the entity data. + */ + public char[] getData() + { + return data; + } + + /** + * Returns true for general entities. Each general entity can be + * referenced as &entity-name;. Such entities are + * defined by the SGML DTD tag + * <!ENTITY name "value">. The general + * entities can be used anywhere in the document. + */ + public boolean isGeneral() + { + return (type & DTDConstants.GENERAL) != 0; + } + + /** + * Get the entity name. + */ + public String getName() + { + return name; + } + + /** + * Returns true for parameter entities. Each parameter entity can be + * referenced as &entity-name;. Such entities are + * defined by the SGML DTD tag + * <!ENTITY % name "value">. The parameter + * entities can be used only in SGML context. + */ + public boolean isParameter() + { + return (type & DTDConstants.PARAMETER) != 0; + } + + /** + * Returns a data as String + */ + public String getString() + { + if (sdata == null) + sdata = new String(data); + + return sdata; + } + + /** + * Get the entity type. + * @return the value of the {@link #type}. + */ + public int getType() + { + return type; + } + +} diff --git a/libjava/classpath/javax/swing/text/html/parser/Parser.java b/libjava/classpath/javax/swing/text/html/parser/Parser.java new file mode 100644 index 0000000..5867107 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/Parser.java @@ -0,0 +1,436 @@ +/* Parser.java -- HTML parser + 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.parser; + +import java.io.IOException; +import java.io.Reader; + +import javax.swing.text.ChangedCharSetException; +import javax.swing.text.SimpleAttributeSet; + +/* + * FOR DEVELOPERS: To avoid regression, please run the package test + * textsuite/javax.swing.text.html.parser/AllParserTests after your + * modifications. + */ + +/** + *

A simple error-tolerant HTML parser that uses a DTD document + * to access data on the possible tokens, arguments and syntax.

+ *

The parser reads an HTML content from a Reader and calls various + * notifying methods (which should be overridden in a subclass) + * when tags or data are encountered.

+ *

Some HTML elements need no opening or closing tags. The + * task of this parser is to invoke the tag handling methods also when + * the tags are not explicitly specified and must be supposed using + * information, stored in the DTD. + * For example, parsing the document + *

<table><tr><td>a<td>b<td>c</tr>
+ * will invoke exactly the handling methods exactly in the same order + * (and with the same parameters) as if parsing the document:
+ * <html><head></head><body><table>< + * tbody><tr><td>a</td><td>b + * </td><td>c</td></tr>< + * /tbody></table></body></html>

+ * (supposed tags are given in italics). The parser also supports + * obsolete elements of HTML syntax.

+ *

+ * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class Parser + implements DTDConstants +{ + /** + * The document template description that will be used to parse the documents. + */ + protected DTD dtd; + + /** + * The value of this field determines whether or not the Parser will be + * strict in enforcing SGML compatibility. The default value is false, + * stating that the parser should do everything to parse and get at least + * some information even from the incorrectly written HTML input. + */ + protected boolean strict; + + /** + * The package level reference to the working HTML parser in this + * implementation. + */ + final gnu.javax.swing.text.html.parser.support.Parser gnu; + + /** + * Creates a new parser that uses the given DTD to access data on the + * possible tokens, arguments and syntax. There is no single - step way + * to get a default DTD; you must either refer to the implementation - + * 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 Parser(DTD a_dtd) + { + dtd = a_dtd; + + final Parser j = this; + + gnu = + new gnu.javax.swing.text.html.parser.support.Parser(dtd) + { + protected final void handleComment(char[] comment) + { + j.handleComment(comment); + } + + protected final void handleEOFInComment() + { + j.handleEOFInComment(); + } + + protected final void handleEmptyTag(TagElement tag) + throws javax.swing.text.ChangedCharSetException + { + j.handleEmptyTag(tag); + } + + protected final void handleStartTag(TagElement tag) + { + j.handleStartTag(tag); + } + + protected final void handleEndTag(TagElement tag) + { + j.handleEndTag(tag); + } + + protected final void handleError(int line, String message) + { + j.handleError(line, message); + } + + protected final void handleText(char[] text) + { + j.handleText(text); + } + + protected final void handleTitle(char[] title) + { + j.handleTitle(title); + } + + protected final void markFirstTime(Element element) + { + j.markFirstTime(element); + } + + protected final void startTag(TagElement tag) + throws ChangedCharSetException + { + j.startTag(tag); + } + + protected final void endTag(boolean omitted) + { + j.endTag(omitted); + } + + protected TagElement makeTag(Element element) + { + return j.makeTag(element); + } + + protected TagElement makeTag(Element element, boolean isSupposed) + { + return j.makeTag(element, isSupposed); + } + }; + } + + /** + * Parse the HTML text, calling various methods in response to the + * occurence of the corresponding HTML constructions. + * @param reader The reader to read the source HTML from. + * @throws IOException If the reader throws one. + */ + public synchronized void parse(Reader reader) + throws IOException + { + gnu.parse(reader); + } + + /** + * Parses DTD markup declaration. Currently returns without action. + * @return null. + * @throws java.io.IOException + */ + public String parseDTDMarkup() + throws IOException + { + return gnu.parseDTDMarkup(); + } + + /** + * Parse DTD document declarations. Currently only parses the document + * type declaration markup. + * @param strBuff + * @return true if this is a valid DTD markup declaration. + * @throws IOException + */ + protected boolean parseMarkupDeclarations(StringBuffer strBuff) + throws IOException + { + return gnu.parseMarkupDeclarations(strBuff); + } + + /** + * Get the attributes of the current tag. + * @return The attribute set, representing the attributes of the current tag. + */ + protected SimpleAttributeSet getAttributes() + { + return gnu.getAttributes(); + } + + /** + * Get the number of the document line being parsed. + * @return The current line. + */ + protected int getCurrentLine() + { + return gnu.hTag.where.beginLine; + } + + /** + * Get the current position in the document being parsed. + * @return The current position. + */ + protected int getCurrentPos() + { + return gnu.hTag.where.startPosition; + } + + /** + * The method is called when the HTML end (closing) tag is found or if + * the parser concludes that the one should be present in the + * current position. The method is called immediatly + * before calling the handleEndTag(). + * @param omitted True if the tag is no actually present in the document, + * but is supposed by the parser (like </html> at the end of the + * document). + */ + protected void endTag(boolean omitted) + { + } + + /** + * Invokes the error handler. The default method in this implementation + * finally delegates the call to handleError, also providing the number of the + * current line. + */ + protected void error(String msg) + { + gnu.error(msg); + } + + /** + * Invokes the error handler. The default method in this implementation + * finally delegates the call to error (msg+": '"+invalid+"'"). + */ + protected void error(String msg, String invalid) + { + gnu.error(msg, invalid); + } + + /** + * Invokes the error handler. The default method in this implementation + * finally delegates the call to error (parm1+" "+ parm2+" "+ parm3). + */ + protected void error(String parm1, String parm2, String parm3) + { + gnu.error(parm1, parm2, parm3); + } + + /** + * Invokes the error handler. The default method in this implementation + * finally delegates the call to error + * (parm1+" "+ parm2+" "+ parm3+" "+ parm4). + */ + protected void error(String parm1, String parm2, String parm3, String parm4) + { + gnu.error(parm1, parm2, parm3, parm4); + } + + /** + * In this implementation, this is never called and returns without action. + */ + protected void flushAttributes() + { + gnu.flushAttributes(); + } + + /** + * Handle HTML comment. The default method returns without action. + * @param comment The comment being handled + */ + protected void handleComment(char[] comment) + { + } + + /** + * This is additionally called in when the HTML content terminates + * without closing the HTML comment. This can only happen if the + * HTML document contains errors (for example, the closing --;gt is + * missing. The default method calls the error handler. + */ + protected void handleEOFInComment() + { + gnu.error("Unclosed comment"); + } + + /** + * Handle the tag with no content, like <br>. The method is + * called for the elements that, in accordance with the current DTD, + * has an empty content. + * @param The tag being handled. + * @throws javax.swing.text.ChangedCharSetException + */ + protected void handleEmptyTag(TagElement tag) + throws ChangedCharSetException + { + } + + /** + * The method is called when the HTML closing tag ((like </table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param The tag being handled + */ + protected void handleEndTag(TagElement tag) + { + } + + /* Handle error that has occured in the given line. */ + protected void handleError(int line, String message) + { + } + + /** + * The method is called when the HTML opening tag ((like <table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param The tag being handled + */ + protected void handleStartTag(TagElement tag) + { + } + + /** + * Handle the text section. + *

For non-preformatted section, the parser replaces + * \t, \r and \n by spaces and then multiple spaces + * by a single space. Additionaly, all whitespace around + * tags is discarded. + *

+ *

For pre-formatted text (inside TEXAREA and PRE), the parser preserves + * all tabs and spaces, but removes one bounding \r, \n or \r\n, + * if it is present. Additionally, it replaces each occurence of \r or \r\n + * by a single \n.

+ * + * @param text A section text. + */ + protected void handleText(char[] text) + { + } + + /** + * Handle HTML <title> tag. This method is invoked when + * both title starting and closing tags are already behind. + * The passed argument contains the concatenation of all + * title text sections. + * @param The title text. + */ + protected void handleTitle(char[] title) + { + } + + /** + * Constructs the tag from the given element. In this implementation, + * this is defined, but never called. + * @param element the base element of the tag. + * @return the tag + */ + protected TagElement makeTag(Element element) + { + return makeTag(element, false); + } + + /** + * Constructs the tag from the given element. + * @param the tag base {@link javax.swing.text.html.parser.Element} + * @param isSupposed true if the tag is not actually present in the + * html input, but the parser supposes that it should to occur in + * the current location. + * @return the tag + */ + protected TagElement makeTag(Element element, boolean isSupposed) + { + return new TagElement(element, isSupposed); + } + + /** + * This is called when the tag, representing the given element, + * occurs first time in the document. + * @param element + */ + protected void markFirstTime(Element element) + { + } + + /** + * The method is called when the HTML opening tag ((like <table>) + * is found or if the parser concludes that the one should be present + * in the current position. The method is called immediately before + * calling the handleStartTag. + * @param The tag + */ + protected void startTag(TagElement tag) + throws ChangedCharSetException + { + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/ParserDelegator.java b/libjava/classpath/javax/swing/text/html/parser/ParserDelegator.java new file mode 100644 index 0000000..4b54e8a --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/ParserDelegator.java @@ -0,0 +1,210 @@ +/* ParserDelegator.java -- Delegator for ParserDocument. + 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.parser; + +import gnu.javax.swing.text.html.parser.HTML_401F; +import gnu.javax.swing.text.html.parser.htmlAttributeSet; + +import java.io.IOException; +import java.io.Reader; +import java.io.Serializable; + +import javax.swing.text.BadLocationException; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.HTMLEditorKit.ParserCallback; + +/** + * This class instantiates and starts the working instance of + * html parser, being responsible for providing the default DTD. + * + * TODO Later this class must be derived from the totally abstract class + * HTMLEditorKit.Parser. HTMLEditorKit that does not yet exist. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class ParserDelegator + extends javax.swing.text.html.HTMLEditorKit.Parser + implements Serializable +{ + private class gnuParser + extends gnu.javax.swing.text.html.parser.support.Parser + { + private static final long serialVersionUID = 1; + + private gnuParser(DTD d) + { + super(d); + } + + protected final void handleComment(char[] comment) + { + callBack.handleComment(comment, hTag.where.startPosition); + } + + protected final void handleEmptyTag(TagElement tag) + throws javax.swing.text.ChangedCharSetException + { + callBack.handleSimpleTag(tag.getHTMLTag(), getAttributes(), + hTag.where.startPosition + ); + } + + protected final void handleEndTag(TagElement tag) + { + callBack.handleEndTag(tag.getHTMLTag(), hTag.where.startPosition); + } + + protected final void handleError(int line, String message) + { + callBack.handleError(message, hTag.where.startPosition); + } + + protected final void handleStartTag(TagElement tag) + { + htmlAttributeSet attributes = gnu.getAttributes(); + + if (tag.fictional()) + attributes.addAttribute(ParserCallback.IMPLIED, Boolean.TRUE); + + callBack.handleStartTag(tag.getHTMLTag(), attributes, + hTag.where.startPosition + ); + } + + protected final void handleText(char[] text) + { + callBack.handleText(text, hTag.where.startPosition); + } + + DTD getDTD() + { + // Accessing the inherited gnu.javax.swing.text.html.parser.support.Parser + // field. super. is a workaround, required to support JDK1.3's javac. + return super.dtd; + } + } + + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = -1276686502624777206L; + + private static DTD dtd = HTML_401F.getInstance(); + + /** + * The callback. + * This is package-private to avoid an accessor method. + */ + HTMLEditorKit.ParserCallback callBack; + + /** + * The reference to the working class of HTML parser that is + * actually used to parse the document. + * This is package-private to avoid an accessor method. + */ + gnuParser gnu; + + /** + * Parses the HTML document, calling methods of the provided + * callback. This method must be multithread - safe. + * @param reader The reader to read the HTML document from + * @param callback The callback that is notifyed about the presence + * of HTML elements in the document. + * @param ignoreCharSet If thrue, any charset changes during parsing + * are ignored. + * @throws java.io.IOException + */ + public void parse(Reader reader, HTMLEditorKit.ParserCallback a_callback, + boolean ignoreCharSet + ) + throws IOException + { + callBack = a_callback; + + if (gnu == null || !dtd.equals(gnu.getDTD())) + { + gnu = new gnuParser(dtd); + } + + gnu.parse(reader); + + callBack.handleEndOfLineString(gnu.getEndOfLineSequence()); + try + { + callBack.flush(); + } + catch (BadLocationException ex) + { + // Convert this into the supported type of exception. + throw new IOException(ex.getMessage()); + } + } + + /** + * Calling this method instructs that, if not specified directly, + * the documents will be parsed using the default + * DTD of the implementation. + */ + protected static void setDefaultDTD() + { + dtd = HTML_401F.getInstance(); + } + + /** + * Registers the user - written DTD under the given name, also + * making it default for the subsequent parsings. This has effect on + * all subsequent calls to the parse(...) . If you need to specify + * your DTD locally, simply {@link javax.swing.text.html.parser.Parser} + * instead. + * @param dtd The DTD that will be used to parse documents by this class. + * @param name The name of this DTD. + * @return No standard is specified on which instance of DTD must be + * returned by this method, and it is recommended to leave the returned + * value without consideration. This implementation returns the DTD + * that was previously set as the default DTD, or the implementations + * default DTD if none was set. + */ + protected static DTD createDTD(DTD a_dtd, String name) + { + DTD.putDTDHash(name, a_dtd); + + DTD dtd_prev = dtd; + dtd = a_dtd; + return dtd_prev; + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/TagElement.java b/libjava/classpath/javax/swing/text/html/parser/TagElement.java new file mode 100644 index 0000000..4558b15 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/TagElement.java @@ -0,0 +1,142 @@ +/* TagElement.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.html.parser; + +import javax.swing.text.html.HTML; + +/** + * The SGML element, defining a single html tag. + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class TagElement +{ + /** + * The Element the tag was constructed from. + */ + private final Element element; + + /** + * The coresponding HTML tag, assigned once in constructor. + */ + private final HTML.Tag tag; + + /** + * The 'fictional' flag. + */ + private final boolean fictional; + + /** + * Creates the html tag element from the defintion, stored in the + * given element. Sets the flag 'fictional' to false. + * @param an_element + */ + public TagElement(Element an_element) + { + this(an_element, false); + } + + /** + * Creates the html tag element from the defintion, stored in the + * given element, setting the flag 'fictional' to the given value. + */ + public TagElement(Element an_element, boolean is_fictional) + { + element = an_element; + fictional = is_fictional; + + HTML.Tag t = HTML.getTag(element.getName()); + + if (t != null) + tag = t; + else + tag = new HTML.UnknownTag(element.getName()); + } + + /** + * Get the element from that the tag was constructed. + */ + public Element getElement() + { + return element; + } + + /** + * Get the corresponding HTML tag. This is either one of the + * pre-defined HTML tags or the instance of the UnknownTag with the + * element name. + */ + public HTML.Tag getHTMLTag() + { + return tag; + } + + /** + * Calls isPreformatted() for the corresponding html tag and returns + * the obtained value. + */ + public boolean isPreformatted() + { + return tag.isPreformatted(); + } + + /** + * Calls breaksFlow() for the corresponding html tag and returns + * the obtained value. + */ + public boolean breaksFlow() + { + return tag.breaksFlow(); + } + + /** + * Get the value of the flag 'fictional'. + */ + public boolean fictional() + { + return fictional; + } + + /** + * Returns string representation of this object. + */ + public String toString() + { + return getElement() + (fictional ? "?" : ""); + } +} diff --git a/libjava/classpath/javax/swing/text/html/parser/package.html b/libjava/classpath/javax/swing/text/html/parser/package.html new file mode 100644 index 0000000..5d5157f --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/parser/package.html @@ -0,0 +1,50 @@ + + + + +GNU Classpath - javax.swing.text.html.parser + + +

Provides the DTD driven for web browsers, + web robots, web page content analysers, web editors and + other applications applications working with Hypertext + Markup Language (HTML). +

+ + + diff --git a/libjava/classpath/javax/swing/text/package.html b/libjava/classpath/javax/swing/text/package.html new file mode 100644 index 0000000..50043b6 --- /dev/null +++ b/libjava/classpath/javax/swing/text/package.html @@ -0,0 +1,46 @@ + + + + +GNU Classpath - javax.swing.text + + +

+ + + diff --git a/libjava/classpath/javax/swing/text/rtf/ControlWordToken.java b/libjava/classpath/javax/swing/text/rtf/ControlWordToken.java new file mode 100644 index 0000000..7008f0f --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/ControlWordToken.java @@ -0,0 +1,86 @@ +/* ControlWordToken.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.rtf; + +/** + * A special {@link Token} that represents a control word in RTF like + * '\deff0' where 'deff' is the name of the control word and '0' is an + * optional parameter. + * + * @author Roman Kennke (roman@ontographics.com) + */ +class ControlWordToken extends Token +{ + + /** + * The name of the control word. + */ + public String name; + + /** + * The optional parameter of the control word. Absence of a parameter is + * expressed through Integer.MIN_VALUE. + */ + public int param; + + /** + * Constructs a new ControlWordToken with the specified name and without + * a parameter. + * + * @param name the name of the control word + */ + public ControlWordToken(String name) + { + this(name, Integer.MIN_VALUE); + } + + + /** + * Constructs a new ControlWordToken with the specified name and parameter. + * + * @param name the name of the control word + */ + public ControlWordToken(String name, int param) + { + super(Token.CONTROL_WORD); + this.name = name; + this.param = param; + } + +} diff --git a/libjava/classpath/javax/swing/text/rtf/RTFEditorKit.java b/libjava/classpath/javax/swing/text/rtf/RTFEditorKit.java new file mode 100644 index 0000000..b2ebe3d --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/RTFEditorKit.java @@ -0,0 +1,114 @@ +/* RTFEditorKit.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.rtf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.StyledEditorKit; + +/** + * Provides support for RTF data for use in + * {@link javax.swing.JEditorPane}s. + * + * @author Roman Kennke (roman@ontographics.com) + */ +public class RTFEditorKit + extends StyledEditorKit +{ + + /** + * Constructs a new RTFEditorKit. + */ + public RTFEditorKit() + { + super(); + } + + /** + * Returns the MIME content type. In the case of RTFEditorKit this is + * 'text/rtf' + * + * @return the MIME content type for RTFEditorKit + */ + public String getContentType() + { + return "text/rtf"; + } + + /** + * Reads RTF data from stream into doc at the + * specified position pos. + * + * @param stream the {@link InputStream} from where we read RTF data + * @param doc the {@link Document} into which we read the RTF data + * @param pos the position where to start + * + * @throws IOException if an IO error occurs + * @throws BadLocationException if the position is not valid + */ + public void read(InputStream stream, Document doc, int pos) + throws IOException, BadLocationException + { + RTFParser parser = new RTFParser(stream, doc, pos); + parser.parse(); + } + + + /** + * Reads RTF data from reader into doc at the + * specified position pos. + * + * @param reader the {@link Reader} from where we read RTF data + * @param doc the {@link Document} into which we read the RTF data + * @param pos the position where to start + * + * @throws IOException if an IO error occurs + * @throws BadLocationException if the position is not valid + */ + public void read(Reader reader, Document doc, int pos) + throws IOException, BadLocationException + { + RTFParser parser = new RTFParser(reader, doc, pos); + parser.parse(); + } +} diff --git a/libjava/classpath/javax/swing/text/rtf/RTFParseException.java b/libjava/classpath/javax/swing/text/rtf/RTFParseException.java new file mode 100644 index 0000000..2a9c64f --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/RTFParseException.java @@ -0,0 +1,65 @@ +/* RTFParseException.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.rtf; + +/** + * Indicates a parsing error during RTF processing. + * + * @author Roman Kennke (roman@ontographics.com) + */ +class RTFParseException + extends RuntimeException +{ + /** + * Constructs a new RTFParseException without message. + */ + public RTFParseException() + { + super(); + } + + /** + * Constructs a new RTFParseException with the specified message. + */ + public RTFParseException(String message) + { + super(message); + } + +} diff --git a/libjava/classpath/javax/swing/text/rtf/RTFParser.java b/libjava/classpath/javax/swing/text/rtf/RTFParser.java new file mode 100644 index 0000000..4f0f967 --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/RTFParser.java @@ -0,0 +1,195 @@ +/* RTFParser.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.rtf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; + +/** + * Parses an RTF file into a {@link Document}. The parser utilizes + * {@link RTFScanner}. + * + * @author Roman Kennke (roman@ontographics.com) + */ +class RTFParser +{ + + /** + * Our scanner. + */ + private RTFScanner scanner; + + /** + * The document into which we parse. + */ + private Document doc; + + /** + * The current position. + */ + private int pos; + + /** + * Constructs a new RTFParser for the specified document and position, + * without initializing the scanner. This is only used internally. + * + * @param doc the {@link Document} into which we should parse + * @param pos the position to start + */ + private RTFParser(Document doc, int pos) + { + this.doc = doc; + this.pos = pos; + } + + /** + * Constructs a new RTFParser for the specified stream. + * + * @param stream the stream from which we parse + * @param doc the {@link Document} into which we should parse + * @param pos the position to start + */ + public RTFParser(InputStream stream, Document doc, int pos) + { + this(doc, pos); + scanner = new RTFScanner(stream); + } + + /** + * Constructs a new RTFParser for the specified reader. + * + * @param reader the reader from which we parse + * @param doc the {@link Document} into which we should parse + * @param pos the position to start + */ + public RTFParser(Reader reader, Document doc, int pos) + { + this(doc, pos); + scanner = new RTFScanner(reader); + } + + /** + * Returns the {@link Document} in which we parsed the RTF data. + * + * @return the {@link Document} in which we parsed the RTF data + */ + public Document getDocument() + { + return doc; + } + + /** + * Starts the parsing process. + */ + public void parse() + throws IOException, BadLocationException + { + parseFile(); + } + + /** + * The parse rules for <file>. + */ + private void parseFile() + throws IOException, BadLocationException + { + Token t1 = scanner.readToken(); + if (t1.type != Token.LCURLY) + throw new RTFParseException("expected left curly braces"); + + parseHeader(); + parseDocument(); + + Token t2 = scanner.readToken(); + if (t2.type != Token.RCURLY) + throw new RTFParseException("expected right curly braces"); + + } + + /** + * The parse rules for <header>. + * + * TODO: implement this properly + */ + private void parseHeader() + //throws IOException, BadLocationException + { + // TODO add parse rules here + } + + + /** + * The parse rules for <document>. + * + * TODO: implement this properly + */ + private void parseDocument() + throws IOException, BadLocationException + { + // !!! TODO !!! + // This simply emits every TEXT Token as text to the document + // which is plain stupid + + boolean eof = false; + + do { + Token token = scanner.readToken(); + switch (token.type) + { + case Token.TEXT: + TextToken textToken = (TextToken) token; + doc.insertString(pos, textToken.text, null); + pos += textToken.text.length(); + break; + case Token.EOF: + eof = true; + break; + default: + // FIXME + break; + } + } while (!eof); + + } + +} diff --git a/libjava/classpath/javax/swing/text/rtf/RTFScanner.java b/libjava/classpath/javax/swing/text/rtf/RTFScanner.java new file mode 100644 index 0000000..3cdd6e8 --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/RTFScanner.java @@ -0,0 +1,268 @@ +/* RTFScanner.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.rtf; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +/** + * Provides a scanner that scans an {@link InputStream} for tokens of the + * RTF syntax. + * + * This scanner is based upon the RTF specification 1.6 + * available at: + * + * + * RTF specification at MSDN + * + * @author Roman Kennke (roman@ontographics.com) + */ +class RTFScanner +{ + + /** + * The reader from which we read the RTF data. + */ + private Reader in; + + /** + * This is used to constuct strings from the read in chars. + */ + private StringBuffer buffer; + + /** + * Constructs a new RTFScanner without initializing the {@link Reader}. + */ + private RTFScanner() + { + buffer = new StringBuffer(); + } + + /** + * Constructs a new RTFScanner for the given {@link InputStream}. + * The stream is wrapped into an {@link InputStreamReader} and if it's + * not yet buffered then the Reader is wrapped in a {@link BufferedReader} + * + * @param stream the {@link InputStream} to read RTF data from + */ + public RTFScanner(InputStream stream) + { + this(); + InputStreamReader reader = new InputStreamReader(stream); + in = new BufferedReader(reader); + } + + /** + * Constructs a new RTFScanner for the given {@link Reader}. + * + * If the reader is not an instance of {@link BufferedReader} then it + * is wrapped into a BufferedReader. + * + * @param reader the {@link BufferedReader} to read RTF data from + */ + public RTFScanner(Reader reader) + { + this(); + if (reader instanceof BufferedReader) + { + in = reader; + } + else + { + in = new BufferedReader(reader); + } + } + + /** + * Reads in the next {@link Token} from the stream. + * + * @return the read {@link Token} + * + * @throws IOException if the underlying stream has problems + */ + public Token readToken() + throws IOException + { + Token token = null; + + int c = in.read(); + switch(c) + { + case -1: + token = new Token(Token.EOF); + break; + + case '{': + token = new Token(Token.LCURLY); + break; + + case '}': + token = new Token(Token.RCURLY); + break; + + case '\\': + buffer.delete(0, buffer.length()); + buffer.append((char) c); + token = readControlWord(); + break; + + default: + buffer.delete(0, buffer.length()); + buffer.append((char) c); + token = readText(); + break; + } + + return token; + } + + /** + * Reads in a control word and optional parameter. + * + * @return the read in control word as {@link ControlWordToken} + * + * @throws IOException if the underlying stream has problems + */ + private Token readControlWord() + throws IOException + { + // this flag indicates if we are still reading the name or are already + // in the parameter + boolean readingName = true; + String name = null; + String param = null; + + while (true) + { + in.mark(1); + int c = in.read(); + + // check for 'a'..'z' + if (readingName && (c >= 'a') && (c <= 'z')) + { + buffer.append((char) c); + } + else if ((c >= '0') && (c <= '9')) + { + // if the last char was in the name, then finish reading the name + if (readingName) + { + name = buffer.toString(); + buffer.delete(0, buffer.length()); + readingName = false; + } + buffer.append((char) c); + } + else + { + // if we were in the name, then finish this + if (readingName) + { + name = buffer.toString(); + } + // otherwise finish the parameter + else + { + param = buffer.toString(); + } + + // clear up + buffer.delete(0, buffer.length()); + // reset input buffer to last char + in.reset(); + // break while loop + break; + } + } + + ControlWordToken token = null; + + if (param == null) + token = new ControlWordToken(name); + else + token =new ControlWordToken(name, Integer.parseInt(param)); + + return token; + + } + + /** + * Reads in a block of text. + * + * @return the token for the text + */ + private Token readText() + throws IOException + { + + boolean readingText = true; + while (readingText) + { + in.mark(1); + int c = in.read(); + switch(c) + { + case '\\': + case '{': + case '}': + case -1: + readingText = false; + in.reset(); + break; + + default: + buffer.append((char) c); + break; + } + + } + + String text = buffer.toString(); + Token token = new TextToken(text); + + buffer.delete(0, buffer.length()); + + return token; + + } +} diff --git a/libjava/classpath/javax/swing/text/rtf/TextToken.java b/libjava/classpath/javax/swing/text/rtf/TextToken.java new file mode 100644 index 0000000..2d6d527 --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/TextToken.java @@ -0,0 +1,65 @@ +/* TextToken.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.rtf; + +/** + * A special {@link Token} that represents a piece of text in RTF. + * + * @author Roman Kennke (roman@ontographics.com) + */ +class TextToken extends Token +{ + + /** + * The text. + */ + public String text; + + /** + * Constructs a new TextToken with the specified textual data. + * + * @param text the text for this token + */ + public TextToken(String text) + { + super(Token.TEXT); + this.text = text; + } + +} diff --git a/libjava/classpath/javax/swing/text/rtf/Token.java b/libjava/classpath/javax/swing/text/rtf/Token.java new file mode 100644 index 0000000..7d5adaa --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/Token.java @@ -0,0 +1,91 @@ +/* Token.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.rtf; + +/** + * Represents a simple token that the RTFScanner can read. A simple + * only has a type (like LCURLY or RCURLY). More complex tokens may + * attach data to the token. + * + * @author Roman Kennke (roman@ontographics.com) + */ +class Token +{ + + /** + * This special type inidicates the end of the input stream. + */ + public static final int EOF = -1; + + /** + * A left curly brace '{'. + */ + public static final int LCURLY = 1; + + /** + * A right curly brace '}'. + */ + public static final int RCURLY = 2; + + /** + * A control word like '\rtf1'. Tokens with this type are represented + * through the subclass {@link ControlWordToken}. + */ + public static final int CONTROL_WORD = 3; + + /** + * A token that contains text. This is represented through the subclass + * {@link TextToken}. + */ + public static final int TEXT = 4; + + + /** The token type. */ + public int type; + + /** + * Constructs a new Token with the specified type. + * + * @param type the Token type + */ + public Token(int type) + { + this.type = type; + } +} diff --git a/libjava/classpath/javax/swing/tree/AbstractLayoutCache.java b/libjava/classpath/javax/swing/tree/AbstractLayoutCache.java new file mode 100644 index 0000000..9f8e9da --- /dev/null +++ b/libjava/classpath/javax/swing/tree/AbstractLayoutCache.java @@ -0,0 +1,409 @@ +/* AbstractLayoutCache.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.tree; + +import java.awt.Rectangle; +import java.util.Enumeration; + +import javax.swing.event.TreeModelEvent; + +/** + * class AbstractLayoutCache + * + * @author Andrew Selkirk + */ +public abstract class AbstractLayoutCache + implements RowMapper +{ + /** + * class NodeDimensions + */ + public abstract static class NodeDimensions + { + /** + * Creates NodeDimensions object. + */ + public NodeDimensions() + { + // Do nothing here. + } + + /** + * getNodeDimensions + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + * @return Rectangle + */ + public abstract Rectangle getNodeDimensions(Object value0, int value1, + int value2, boolean value3, Rectangle value4); + } + + /** + * nodeDimensions + */ + protected NodeDimensions nodeDimensions; + + /** + * treeModel + */ + protected TreeModel treeModel; + + /** + * treeSelectionModel + */ + protected TreeSelectionModel treeSelectionModel; + + /** + * rootVisible + */ + protected boolean rootVisible; + + /** + * rowHeight + */ + protected int rowHeight; + + /** + * Constructor AbstractLayoutCache + */ + public AbstractLayoutCache() + { + // Do nothing here. + } + + /** + * setNodeDimensions + * + * @param dimensions TODO + */ + public void setNodeDimensions(NodeDimensions dimensions) + { + nodeDimensions = dimensions; + } + + /** + * getNodeDimensions + * + * @return NodeDimensions + */ + public NodeDimensions getNodeDimensions() + { + return nodeDimensions; + } + + /** + * getNodeDimensions + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + * + * @return Rectangle + */ + protected Rectangle getNodeDimensions(Object value, int row, int depth, + boolean expanded, Rectangle bounds) + { + if (bounds == null) + return new Rectangle(); + return null; + // TODO + } + + /** + * Sets the model that provides the tree data. + * + * @param the model + */ + public void setModel(TreeModel model) + { + treeModel = model; + } + + /** + * Returns the model that provides the tree data. + * + * @return the model + */ + public TreeModel getModel() + { + return treeModel; + } + + /** + * setRootVisible + * + * @param visible true if root should be visible, + * false otherwise + */ + public void setRootVisible(boolean visible) + { + rootVisible = visible; + } + + /** + * isRootVisible + * + * @return true if root is visible, + * false otherwise + */ + public boolean isRootVisible() + { + return rootVisible; + } + + /** + * setRowHeight + * + * @param height the row height + */ + public void setRowHeight(int height) + { + rowHeight = height; + } + + /** + * getRowHeight + * + * @return the row height + */ + public int getRowHeight() + { + return rowHeight; + } + + /** + * setSelectionModel + * + * @param model the model + */ + public void setSelectionModel(TreeSelectionModel model) + { + treeSelectionModel = model; + } + + /** + * getSelectionModel + * + * @return the model + */ + public TreeSelectionModel getSelectionModel() + { + return treeSelectionModel; + } + + /** + * getPreferredHeight + * + * @return int + */ + public int getPreferredHeight() + { + return 0; // TODO + } + + /** + * getPreferredWidth + * + * @param value0 TODO + * + * @return int + */ + public int getPreferredWidth(Rectangle value0) + { + return 0; // TODO + } + + /** + * isExpanded + * + * @param value0 TODO + * + * @return boolean + */ + public abstract boolean isExpanded(TreePath value0); + + /** + * getBounds + * + * @param value0 TODO + * @param value1 TODO + * + * @return Rectangle + */ + public abstract Rectangle getBounds(TreePath value0, Rectangle value1); + + /** + * getPathForRow + * + * @param row the row + * + * @return the tree path + */ + public abstract TreePath getPathForRow(int row); + + /** + * getRowForPath + * + * @param path the tree path + * + * @return the row + */ + public abstract int getRowForPath(TreePath path); + + /** + * getPathClosestTo + * + * @param value0 TODO + * @param value1 TODO + * + * @return the tree path + */ + public abstract TreePath getPathClosestTo(int value0, int value1); + + /** + * getVisiblePathsFrom + * + * @param path the tree path + * + * @return Enumeration + */ + public abstract Enumeration getVisiblePathsFrom(TreePath path); + + /** + * getVisibleChildCount + * + * @param path the tree path + * + * @return int + */ + public abstract int getVisibleChildCount(TreePath value0); + + /** + * setExpandedState + * + * @param value0 TODO + * + * @param value1 TODO + */ + public abstract void setExpandedState(TreePath value0, boolean value1); + + /** + * getExpandedState + * + * @param path the tree path + * + * @return boolean + */ + public abstract boolean getExpandedState(TreePath path); + + /** + * getRowCount + * + * @return the number of rows + */ + public abstract int getRowCount(); + + /** + * invalidateSizes + */ + public abstract void invalidateSizes(); + + /** + * invalidatePathBounds + * + * @param path the tree path + */ + public abstract void invalidatePathBounds(TreePath path); + + /** + * treeNodesChanged + * + * @param event the event to send + */ + public abstract void treeNodesChanged(TreeModelEvent event); + + /** + * treeNodesInserted + * + * @param event the event to send + */ + public abstract void treeNodesInserted(TreeModelEvent event); + + /** + * treeNodesRemoved + * + * @param event the event to send + */ + public abstract void treeNodesRemoved(TreeModelEvent event); + + /** + * treeStructureChanged + * + * @param event the event to send + */ + public abstract void treeStructureChanged(TreeModelEvent event); + + /** + * getRowsForPaths + * + * @param paths the tree paths + * + * @return an array of rows + */ + public int[] getRowsForPaths(TreePath[] paths) + { + return null; // TODO + } + + /** + * isFixedRowHeight + * + * @return boolean + */ + protected boolean isFixedRowHeight() + { + return false; // TODO + } +} diff --git a/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java b/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java new file mode 100644 index 0000000..e709e2a --- /dev/null +++ b/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java @@ -0,0 +1,1112 @@ +/* DefaultMutableTreeNode.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.tree; + +import gnu.java.util.EmptyEnumeration; + +import java.io.IOException; +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; +import java.util.Stack; +import java.util.Vector; + + +/** + * DefaultMutableTreeNode + * + * @author Andrew Selkirk + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class DefaultMutableTreeNode + implements Cloneable, MutableTreeNode, Serializable +{ + private static final long serialVersionUID = -4298474751201349152L; + + /** + * EMPTY_ENUMERATION + */ + public static final Enumeration EMPTY_ENUMERATION = + EmptyEnumeration.getInstance(); + + /** + * parent + */ + protected MutableTreeNode parent; + + /** + * children + */ + protected Vector children = new Vector(); + + /** + * userObject + */ + protected transient Object userObject; + + /** + * allowsChildren + */ + protected boolean allowsChildren; + + /** + * Creates a DefaultMutableTreeNode object. + * This node allows to add child nodes. + */ + public DefaultMutableTreeNode() + { + this(null, true); + } + + /** + * Creates a DefaultMutableTreeNode object with the given + * user object attached to it. This node allows to add child nodes. + * + * @param userObject the user object + */ + public DefaultMutableTreeNode(Object userObject) + { + this(userObject, true); + } + + /** + * Creates a DefaultMutableTreeNode object with the given + * user object attached to it. + * + * @param userObject the user object + * @param allowsChildren true if the code allows to add child + * nodes, false otherwise + */ + public DefaultMutableTreeNode(Object userObject, boolean allowsChildren) + { + this.userObject = userObject; + this.allowsChildren = allowsChildren; + } + + /** + * clone + * + * @return Object + */ + public Object clone() + { + try + { + return super.clone(); + // TODO: Do we need to do more here ? + } + catch (CloneNotSupportedException e) + { + // This never happens. + return null; + } + } + + /** + * Returns a string representation of this node + * + * @return a human-readable String representing this node + */ + public String toString() + { + if (userObject == null) + return null; + + return userObject.toString(); + } + + /** + * Adds a new child node to this node. + * + * @param child the child node + * + * @throws IllegalArgumentException if child is null + * @throws IllegalStateException if the node does not allow children + */ + public void add(MutableTreeNode child) + { + if (child == null) + throw new IllegalArgumentException(); + + if (! allowsChildren) + throw new IllegalStateException(); + + children.add(child); + child.setParent(this); + } + + /** + * Returns the parent node of this node. + * + * @return the parent node + */ + public TreeNode getParent() + { + return parent; + } + + /** + * Removes the child with the given index from this node + * + * @param index the index + */ + public void remove(int index) + { + children.remove(index); + } + + /** + * Removes the given child from this node. + * + * @param node the child node + */ + public void remove(MutableTreeNode node) + { + children.remove(node); + } + + /** + * writeObject + * + * @param stream the output stream + * + * @exception IOException If an error occurs + */ + private void writeObject(ObjectOutputStream stream) + throws IOException + { + // TODO: Implement me. + } + + /** + * readObject + * + * @param stream the input stream + * + * @exception IOException If an error occurs + * @exception ClassNotFoundException TODO + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + // TODO: Implement me. + } + + /** + * Inserts given child node at the given index. + * + * @param node the child node + * @param index the index. + */ + public void insert(MutableTreeNode node, int index) + { + children.insertElementAt(node, index); + } + + /** + * Returns a path to this node from the root. + * + * @return an array of tree nodes + */ + public TreeNode[] getPath() + { + return getPathToRoot(this, 0); + } + + /** + * Returns an enumeration containing all children of this node. + * EMPTY_ENUMERATION is returned if this node has no children. + * + * @return an enumeration of tree nodes + */ + public Enumeration children() + { + if (children.size() == 0) + return EMPTY_ENUMERATION; + + return children.elements(); + } + + /** + * Set the parent node for this node. + * + * @param node the parent node + */ + public void setParent(MutableTreeNode node) + { + parent = node; + } + + /** + * Returns the child node at a given index. + * + * @param index the index + * + * @return the child node + */ + public TreeNode getChildAt(int index) + { + return (TreeNode) children.elementAt(index); + } + + /** + * Returns the number of children of this node. + * + * @return the number of children + */ + public int getChildCount() + { + return children.size(); + } + + /** + * Returns the child index for a given node. + * + * @param node this node + * + * @return the index + */ + public int getIndex(TreeNode node) + { + return children.indexOf(node); + } + + /** + * setAllowsChildren + * + * @param allowsChildren TODO + */ + public void setAllowsChildren(boolean allowsChildren) + { + this.allowsChildren = allowsChildren; + } + + /** + * getAllowsChildren + * + * @return boolean + */ + public boolean getAllowsChildren() + { + return allowsChildren; + } + + /** + * Sets the user object for this node + * + * @param userObject the user object + */ + public void setUserObject(Object userObject) + { + this.userObject = userObject; + } + + /** + * Returns the user object attached to this node. null is + * returned when no user object is set. + * + * @return the user object + */ + public Object getUserObject() + { + return userObject; + } + + /** + * Removes this node from its parent. + */ + public void removeFromParent() + { + parent.remove(this); + parent = null; + } + + /** + * Removes all child nodes from this node. + */ + public void removeAllChildren() + { + children.removeAllElements(); + } + + /** + * isNodeAncestor + * + * @param node TODO + * + * @return boolean + */ + public boolean isNodeAncestor(TreeNode node) + { + if (node == null) + return false; + + TreeNode current = this; + + while (current != null + && current != node) + current = current.getParent(); + + return current == node; + } + + /** + * isNodeDescendant + * + * @param node TODO + * + * @return boolean + */ + public boolean isNodeDescendant(DefaultMutableTreeNode node) + { + if (node == null) + return false; + + TreeNode current = node; + + while (current != null + && current != this) + current = current.getParent(); + + return current == this; + } + + /** + * getSharedAncestor + * + * @param node TODO + * + * @return TreeNode + */ + public TreeNode getSharedAncestor(DefaultMutableTreeNode node) + { + TreeNode current = this; + ArrayList list = new ArrayList(); + + while (current != null) + { + list.add(current); + current = current.getParent(); + } + + current = node; + + while (current != null) + { + if (list.contains(current)) + return current; + + current = current.getParent(); + } + + return null; + } + + /** + * isNodeRelated + * + * @param node TODO + * + * @return boolean + */ + public boolean isNodeRelated(DefaultMutableTreeNode node) + { + if (node == null) + return false; + + return node.getRoot() == getRoot(); + } + + /** + * getDepth + * + * @return int + */ + public int getDepth() + { + if ((! allowsChildren) + || children.size() == 0) + return 0; + + Stack stack = new Stack(); + stack.push(new Integer(0)); + TreeNode node = getChildAt(0); + int depth = 0; + int current = 1; + + while (! stack.empty()) + { + if (node.getChildCount() != 0) + { + node = node.getChildAt(0); + stack.push(new Integer(0)); + current++; + } + else + { + if (current > depth) + depth = current; + + int size; + int index; + + do + { + node = node.getParent(); + size = node.getChildCount(); + index = ((Integer) stack.pop()).intValue() + 1; + current--; + } + while (index >= size + && node != this); + + if (index < size) + { + node = node.getChildAt(index); + stack.push(new Integer(index)); + current++; + } + } + } + + return depth; + } + + /** + * getLevel + * + * @return int + */ + public int getLevel() + { + int count = -1; + TreeNode current = this; + + do + { + current = current.getParent(); + count++; + } + while (current != null); + + return count; + } + + /** + * getPathToRoot + * + * @param node TODO + * @param depth TODO + * + * @return TreeNode[] + */ + protected TreeNode[] getPathToRoot(TreeNode node, int depth) + { + if (node == null) + { + if (depth == 0) + return null; + + return new TreeNode[depth]; + } + + TreeNode[] path = getPathToRoot(node.getParent(), depth + 1); + path[path.length - depth - 1] = node; + return path; + } + + /** + * getUserObjectPath + * + * @return Object[] + */ + public Object[] getUserObjectPath() + { + TreeNode[] path = getPathToRoot(this, 0); + Object[] object = new Object[path.length]; + + for (int index = 0; index < path.length; ++index) + object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject(); + + return object; + } + + /** + * Returns the root node by iterating the parents of this node. + * + * @return the root node + */ + public TreeNode getRoot() + { + TreeNode current = this; + TreeNode check = current.getParent(); + + while (check != null) + { + current = check; + check = current.getParent(); + } + + return current; + } + + /** + * Tells whether this node is the root node or not. + * + * @return true if this is the root node, + * falseotherwise + */ + public boolean isRoot() + { + return parent == null; + } + + /** + * getNextNode + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getNextNode() + { + // Return first child. + if (getChildCount() != 0) + return (DefaultMutableTreeNode) getChildAt(0); + + // Return next sibling (if needed the sibling of some parent). + DefaultMutableTreeNode node = this; + DefaultMutableTreeNode sibling; + + do + { + sibling = node.getNextSibling(); + node = (DefaultMutableTreeNode) node.getParent(); + } + while (sibling == null && + node != null); + + // Return sibling. + return sibling; + } + + /** + * getPreviousNode + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getPreviousNode() + { + // Return null if no parent. + if (parent == null) + return null; + + DefaultMutableTreeNode sibling = getPreviousSibling(); + + // Return parent if no sibling. + if (sibling == null) + return (DefaultMutableTreeNode) parent; + + // Return last leaf of sibling. + if (sibling.getChildCount() != 0) + return sibling.getLastLeaf(); + + // Return sibling. + return sibling; + } + + /** + * preorderEnumeration + * + * @return Enumeration + */ + public Enumeration preorderEnumeration() + { + return new PreorderEnumeration(this); + } + + /** + * postorderEnumeration + * + * @return Enumeration + */ + public Enumeration postorderEnumeration() + { + return new PostorderEnumeration(this); + } + + /** + * breadthFirstEnumeration + * + * @return Enumeration + */ + public Enumeration breadthFirstEnumeration() + { + return new BreadthFirstEnumeration(this); + } + + /** + * depthFirstEnumeration + * + * @return Enumeration + */ + public Enumeration depthFirstEnumeration() + { + return postorderEnumeration(); + } + + /** + * pathFromAncestorEnumeration + * + * @param node TODO + * + * @return Enumeration + */ + public Enumeration pathFromAncestorEnumeration(TreeNode node) + { + if (node == null) + throw new IllegalArgumentException(); + + TreeNode parent = this; + Vector nodes = new Vector(); + nodes.add(this); + + while (parent != node && parent != null) + { + parent = parent.getParent(); + nodes.add(0, parent); + } + + if (parent != node) + throw new IllegalArgumentException(); + + return nodes.elements(); + } + + /** + * isNodeChild + * + * @param node TODO + * + * @return boolean + */ + public boolean isNodeChild(TreeNode node) + { + if (node == null) + return false; + + return node.getParent() == this; + } + + /** + * getFirstChild + * + * @return TreeNode + */ + public TreeNode getFirstChild() + { + return (TreeNode) children.firstElement(); + } + + /** + * getLastChild + * + * @return TreeNode + */ + public TreeNode getLastChild() + { + return (TreeNode) children.lastElement(); + } + + /** + * getChildAfter + * + * @param node TODO + * + * @return TreeNode + */ + public TreeNode getChildAfter(TreeNode node) + { + if (node == null + || node.getParent() != this) + throw new IllegalArgumentException(); + + int index = getIndex(node) + 1; + + if (index == getChildCount()) + return null; + + return getChildAt(index); + } + + /** + * getChildBefore + * + * @param node TODO + * + * @return TreeNode + */ + public TreeNode getChildBefore(TreeNode node) + { + if (node == null + || node.getParent() != this) + throw new IllegalArgumentException(); + + int index = getIndex(node) - 1; + + if (index < 0) + return null; + + return getChildAt(index); + } + + /** + * isNodeSibling + * + * @param node TODO + * + * @return boolean + */ + public boolean isNodeSibling(TreeNode node) + { + if (node == null) + return false; + + return (node.getParent() == getParent() + && getParent() != null); + } + + /** + * getSiblingCount + * + * @return int + */ + public int getSiblingCount() + { + if (parent == null) + return 1; + + return parent.getChildCount(); + } + + /** + * getNextSibling + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getNextSibling() + { + if (parent == null) + return null; + + int index = parent.getIndex(this) + 1; + + if (index == parent.getChildCount()) + return null; + + return (DefaultMutableTreeNode) parent.getChildAt(index); + } + + /** + * getPreviousSibling + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getPreviousSibling() + { + if (parent == null) + return null; + + int index = parent.getIndex(this) - 1; + + if (index < 0) + return null; + + return (DefaultMutableTreeNode) parent.getChildAt(index); + } + + /** + * isLeaf + * + * @return boolean + */ + public boolean isLeaf() + { + return children.size() == 0; + } + + /** + * getFirstLeaf + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getFirstLeaf() + { + TreeNode current = this; + + while (current.getChildCount() > 0) + current = current.getChildAt(0); + + return (DefaultMutableTreeNode) current; + } + + /** + * getLastLeaf + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getLastLeaf() + { + TreeNode current = this; + int size = current.getChildCount(); + + while (size > 0) + { + current = current.getChildAt(size - 1); + size = current.getChildCount(); + } + + return (DefaultMutableTreeNode) current; + } + + /** + * getNextLeaf + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getNextLeaf() + { + if (parent == null) + return null; + + // TODO: Fix implementation. + return null; + //return parent.getChildAfter(this); + } + + /** + * getPreviousLeaf + * + * @return DefaultMutableTreeNode + */ + public DefaultMutableTreeNode getPreviousLeaf() + { + if (parent == null) + return null; + + // TODO: Fix implementation. + return null; + //return parent.getChildBefore(this); + } + + /** + * getLeafCount + * + * @return int + */ + public int getLeafCount() + { + int count = 0; + Enumeration e = depthFirstEnumeration(); + + while (e.hasMoreElements()) + { + TreeNode current = (TreeNode) e.nextElement(); + + if (current.isLeaf()) + count++; + } + + return count; + } + + /** Provides an enumeration of a tree in breadth-first traversal + * order. + */ + static class BreadthFirstEnumeration implements Enumeration + { + + LinkedList queue = new LinkedList(); + + BreadthFirstEnumeration(TreeNode node) + { + queue.add(node); + } + + public boolean hasMoreElements() + { + return !queue.isEmpty(); + } + + public Object nextElement() + { + if(queue.isEmpty()) + throw new NoSuchElementException("No more elements left."); + + TreeNode node = (TreeNode) queue.removeFirst(); + + Enumeration children = node.children(); + while (children.hasMoreElements()) + queue.add(children.nextElement()); + + return node; + } + } + + /** Provides an enumeration of a tree traversing it + * preordered. + */ + static class PreorderEnumeration implements Enumeration + { + TreeNode next; + + Stack childrenEnums = new Stack(); + + PreorderEnumeration(TreeNode node) + { + next = node; + childrenEnums.push(node.children()); + } + + public boolean hasMoreElements() + { + return next != null; + } + + public Object nextElement() + { + if( next == null ) + throw new NoSuchElementException("No more elements left."); + + Object current = next; + + Enumeration children = (Enumeration) childrenEnums.peek(); + + // Retrieves the next element. + next = traverse(children); + + return current; + } + + private TreeNode traverse(Enumeration children) + { + // If more children are available step down. + if( children.hasMoreElements() ) + { + TreeNode child = (TreeNode) children.nextElement(); + childrenEnums.push(child.children()); + + return child; + } + + // If no children are left, we return to a higher level. + childrenEnums.pop(); + + // If there are no more levels left, there is no next + // element to return. + if ( childrenEnums.isEmpty() ) + return null; + else + { + return traverse((Enumeration) childrenEnums.peek()); + } + } + } + + /** Provides an enumeration of a tree traversing it + * postordered (= depth-first). + */ + static class PostorderEnumeration implements Enumeration + { + + Stack nodes = new Stack(); + Stack childrenEnums = new Stack(); + + PostorderEnumeration(TreeNode node) + { + nodes.push(node); + childrenEnums.push(node.children()); + } + + public boolean hasMoreElements() + { + return !nodes.isEmpty(); + } + + public Object nextElement() + { + if( nodes.isEmpty() ) + throw new NoSuchElementException("No more elements left!"); + + Enumeration children = (Enumeration) childrenEnums.peek(); + + return traverse(children); + } + + private Object traverse(Enumeration children) + { + if ( children.hasMoreElements() ) + { + TreeNode node = (TreeNode) children.nextElement(); + nodes.push(node); + + Enumeration newChildren = node.children(); + childrenEnums.push(newChildren); + + return traverse(newChildren); + } + else + { + childrenEnums.pop(); + + // Returns the node whose children + // have all been visited. (= postorder) + Object next = nodes.peek(); + nodes.pop(); + + return next; + } + } + + } + +} diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java b/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java new file mode 100644 index 0000000..e509d2c --- /dev/null +++ b/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java @@ -0,0 +1,516 @@ +/* DefaultTreeCellEditor.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.tree; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EventObject; + +import javax.swing.Icon; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.border.Border; +import javax.swing.event.CellEditorListener; +import javax.swing.event.EventListenerList; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; + +/** + * DefaultTreeCellEditor + * @author Andrew Selkirk + */ +public class DefaultTreeCellEditor + implements ActionListener, TreeCellEditor, TreeSelectionListener +{ + /** + * EditorContainer + */ + public class EditorContainer extends Container + { + /** + * Creates an EditorContainer object. + */ + public EditorContainer() + { + // Do nothing here. + } + + /** + * This method only exists for API compatibility and is useless as it does + * nothing. It got probably introduced by accident. + */ + public void EditorContainer() + { + // Do nothing here. + } + + /** + * getPreferredSize + * @return Dimension + */ + public Dimension getPreferredSize() + { + return null; // TODO + } + + /** + * paint + * @param value0 TODO + */ + public void paint(Graphics value0) + { + // TODO + } + + /** + * doLayout + */ + public void doLayout() + { + // TODO + } + } + + /** + * DefaultTextField + */ + public class DefaultTextField extends JTextField + { + /** + * border + */ + protected Border border; + + /** + * Creates a DefaultTextField object. + * + * @param border the border to use + */ + public DefaultTextField(Border border) + { + this.border = border; + } + + /** + * getFont + * @return Font + */ + public Font getFont() + { + return null; // TODO + } + + /** + * Returns the border of the text field. + * + * @return the border + */ + public Border getBorder() + { + return border; + } + + /** + * getPreferredSize + * @return Dimension + */ + public Dimension getPreferredSize() + { + return null; // TODO + } + } + + private EventListenerList listenerList = new EventListenerList(); + + /** + * realEditor + */ + protected TreeCellEditor realEditor; + + /** + * renderer + */ + protected DefaultTreeCellRenderer renderer; + + /** + * editingContainer + */ + protected Container editingContainer; + + /** + * editingComponent + */ + protected transient Component editingComponent; + + /** + * canEdit + */ + protected boolean canEdit; + + /** + * offset + */ + protected transient int offset; + + /** + * tree + */ + protected transient JTree tree; + + /** + * lastPath + */ + protected transient TreePath lastPath; + + /** + * timer + */ + protected transient javax.swing.Timer timer; // TODO + + /** + * lastRow + */ + protected transient int lastRow; + + /** + * borderSelectionColor + */ + protected Color borderSelectionColor; + + /** + * editingIcon + */ + protected transient Icon editingIcon; + + /** + * font + */ + protected Font font; + + /** + * Constructor DefaultTreeCellEditor + * @param value0 TODO + * @param value1 TODO + */ + public DefaultTreeCellEditor(JTree value0, DefaultTreeCellRenderer value1) + { + // TODO + } + + /** + * Constructor DefaultTreeCellEditor + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public DefaultTreeCellEditor(JTree value0, DefaultTreeCellRenderer value1, + TreeCellEditor value2) + { + // TODO + } + + /** + * writeObject + * @param value0 TODO + * @exception IOException TODO + */ + private void writeObject(ObjectOutputStream value0) throws IOException + { + // TODO + } + + /** + * readObject + * @param value0 TODO + * @exception IOException TODO + * @exception ClassNotFoundException TODO + */ + private void readObject(ObjectInputStream value0) + throws IOException, ClassNotFoundException + { + // TODO + } + + /** + * setBorderSelectionColor + * @param value0 TODO + */ + public void setBorderSelectionColor(Color value0) + { + // TODO + } + + /** + * getBorderSelectionColor + * @return Color + */ + public Color getBorderSelectionColor() + { + return null; // TODO + } + + /** + * setFont + * @param value0 TODO + */ + public void setFont(Font value0) + { + // TODO + } + + /** + * getFont + * @return Font + */ + public Font getFont() + { + return null; // TODO + } + + /** + * getTreeCellEditorComponent + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + * @param value5 TODO + * @return Component + */ + public Component getTreeCellEditorComponent(JTree value0, Object value1, + boolean value2, boolean value3, + boolean value4, int value5) + { + return null; // TODO + } + + /** + * getCellEditorValue + * @return Object + */ + public Object getCellEditorValue() + { + return null; // TODO + } + + /** + * isCellEditable + * @param value0 TODO + * @return boolean + */ + public boolean isCellEditable(EventObject value0) + { + return false; // TODO + } + + /** + * shouldSelectCell + * @param value0 TODO + * @return boolean + */ + public boolean shouldSelectCell(EventObject value0) + { + return false; // TODO + } + + /** + * stopCellEditing + * @return boolean + */ + public boolean stopCellEditing() + { + return false; // TODO + } + + /** + * cancelCellEditing + */ + public void cancelCellEditing() + { + // TODO + } + + /** + * Adds a CellEditorListener object to this editor. + * + * @param listener the listener to add + */ + public void addCellEditorListener(CellEditorListener listener) + { + listenerList.add(CellEditorListener.class, listener); + } + + /** + * Removes a CellEditorListener object. + * + * @param listener the listener to remove + */ + public void removeCellEditorListener(CellEditorListener listener) + { + listenerList.remove(CellEditorListener.class, listener); + } + + /** + * Returns all added CellEditorListener objects to this editor. + * + * @return an array of listeners + * + * @since 1.4 + */ + public CellEditorListener[] getCellEditorListeners() + { + return (CellEditorListener[]) listenerList.getListeners(CellEditorListener.class); + } + + /** + * valueChanged + * @param value0 TODO + */ + public void valueChanged(TreeSelectionEvent value0) + { + // TODO + } + + /** + * actionPerformed + * @param value0 TODO + */ + public void actionPerformed(ActionEvent value0) + { + // TODO + } + + /** + * setTree + * @param value0 TODO + */ + protected void setTree(JTree value0) + { + // TODO + } + + /** + * shouldStartEditingTimer + * @param value0 TODO + * @return boolean + */ + protected boolean shouldStartEditingTimer(EventObject value0) + { + return false; // TODO + } + + /** + * startEditingTimer + */ + protected void startEditingTimer() + { + // TODO + } + + /** + * canEditImmediately + * @param value0 TODO + * @return boolean + */ + protected boolean canEditImmediately(EventObject value0) + { + return false; // TODO + } + + /** + * inHitRegion + * @param value0 TODO + * @param value1 TODO + * @return boolean + */ + protected boolean inHitRegion(int value0, int value1) + { + return false; // TODO + } + + /** + * determineOffset + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + * @param value5 TODO + */ + protected void determineOffset(JTree value0, Object value1, boolean value2, + boolean value3, boolean value4, int value5) + { + // TODO + } + + /** + * prepareForEditing + */ + protected void prepareForEditing() + { + // TODO + } + + /** + * createContainer + * @return Container + */ + protected Container createContainer() + { + return null; // TODO + } + + /** + * createTreeCellEditor + * @return TreeCellEditor + */ + protected TreeCellEditor createTreeCellEditor() + { + return null; // TODO + } +} diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java b/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java new file mode 100644 index 0000000..db69c60 --- /dev/null +++ b/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java @@ -0,0 +1,591 @@ +/* DefaultTreeCellRenderer.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.tree; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JTree; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.UIResource; + +/** + * DefaultTreeCellRenderer + * + * @author Andrew Selkirk + */ +public class DefaultTreeCellRenderer + extends JLabel + implements TreeCellRenderer +{ + // ------------------------------------------------------------- + // Variables -------------------------------------------------- + // ------------------------------------------------------------- + + /** + * selected + */ + protected boolean selected; + + /** + * hasFocus + */ + protected boolean hasFocus; + + /** + * drawsFocusBorderAroundIcon + */ + private boolean drawsFocusBorderAroundIcon; + + /** + * closedIcon + */ + protected transient Icon closedIcon; + + /** + * leafIcon + */ + protected transient Icon leafIcon; + + /** + * openIcon + */ + protected transient Icon openIcon; + + /** + * textSelectionColor + */ + protected Color textSelectionColor; + + /** + * textNonSelectionColor + */ + protected Color textNonSelectionColor; + + /** + * backgroundSelectionColor + */ + protected Color backgroundSelectionColor; + + /** + * backgroundNonSelectionColor + */ + protected Color backgroundNonSelectionColor; + + /** + * borderSelectionColor + */ + protected Color borderSelectionColor; + + + // ------------------------------------------------------------- + // Initialization --------------------------------------------- + // ------------------------------------------------------------- + + /** + * Constructor DefaultTreeCellRenderer + */ + public DefaultTreeCellRenderer() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + setLeafIcon(getDefaultLeafIcon()); + setOpenIcon(getDefaultOpenIcon()); + setClosedIcon(getDefaultClosedIcon()); + + setTextNonSelectionColor(defaults.getColor("Tree.textForeground")); + setTextSelectionColor(defaults.getColor("Tree.selectionForeground")); + setBackgroundNonSelectionColor(defaults + .getColor("Tree.nonSelectionBackground")); + setBackgroundSelectionColor(defaults + .getColor("Tree.selectionBackground")); + setBorderSelectionColor(defaults + .getColor("Tree.selectionBorderColor")); + } + + // ------------------------------------------------------------- + // Methods ---------------------------------------------------- + // ------------------------------------------------------------- + + /** + * getDefaultOpenIcon + * + * @returns Icon + */ + public Icon getDefaultOpenIcon() + { + return UIManager.getLookAndFeelDefaults().getIcon("Tree.openIcon"); + } + + /** + * getDefaultClosedIcon + * + * @returns Icon + */ + public Icon getDefaultClosedIcon() + { + return UIManager.getLookAndFeelDefaults().getIcon("Tree.closedIcon"); + } + + /** + * getDefaultLeafIcon + * + * @returns Icon + */ + public Icon getDefaultLeafIcon() + { + return UIManager.getLookAndFeelDefaults().getIcon("Tree.leafIcon"); + } + + /** + * setOpenIcon + * + * @param value0 TODO + */ + public void setOpenIcon(Icon i) + { + openIcon = i; + } + + /** + * getOpenIcon + * + * @returns Icon + */ + public Icon getOpenIcon() + { + return openIcon; + } + + /** + * setClosedIcon + * + * @param value0 TODO + */ + public void setClosedIcon(Icon i) + { + closedIcon = i; + } + + /** + * getClosedIcon + * + * @returns Icon + */ + public Icon getClosedIcon() + { + return closedIcon; + } + + /** + * setLeafIcon + * + * @param value0 TODO + */ + public void setLeafIcon(Icon i) + { + leafIcon = i; + } + + /** + * getLeafIcon + * + * @returns Icon + */ + public Icon getLeafIcon() + { + return leafIcon; + } + + /** + * setTextSelectionColor + * + * @param value0 TODO + */ + public void setTextSelectionColor(Color c) + { + textSelectionColor = c; + } + + /** + * getTextSelectionColor + * + * @returns Color + */ + public Color getTextSelectionColor() + { + return textSelectionColor; + } + + /** + * setTextNonSelectionColor + * + * @param value0 TODO + */ + public void setTextNonSelectionColor(Color c) + { + textNonSelectionColor = c; + } + + /** + * getTextNonSelectionColor + * + * @returns Color + */ + public Color getTextNonSelectionColor() + { + return textNonSelectionColor; + } + + /** + * setBackgroundSelectionColor + * + * @param value0 TODO + */ + public void setBackgroundSelectionColor(Color c) + { + backgroundSelectionColor = c; + } + + /** + * getBackgroundSelectionColor + * + * @returns Color + */ + public Color getBackgroundSelectionColor() + { + return backgroundSelectionColor; + } + + /** + * setBackgroundNonSelectionColor + * + * @param value0 TODO + */ + public void setBackgroundNonSelectionColor(Color c) + { + backgroundNonSelectionColor = c; + } + + /** + * getBackgroundNonSelectionColor + * + * @returns Color + */ + public Color getBackgroundNonSelectionColor() + { + return backgroundNonSelectionColor; + } + + /** + * setBorderSelectionColor + * + * @param value0 TODO + */ + public void setBorderSelectionColor(Color c) + { + borderSelectionColor = c; + } + + /** + * getBorderSelectionColor + * + * @returns Color + */ + public Color getBorderSelectionColor() + { + return borderSelectionColor; + } + + /** + * setFont + * + * @param value0 TODO + */ + public void setFont(Font f) + { + if (f != null && f instanceof UIResource) + f = null; + super.setFont(f); + } + + /** + * setBackground + * + * @param value0 TODO + */ + public void setBackground(Color c) + { + if (c != null && c instanceof UIResource) + c = null; + super.setBackground(c); + } + + /** + * getTreeCellRendererComponent + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + * @param value5 TODO + * @param value6 TODO + * @returns Component + */ + public Component getTreeCellRendererComponent(JTree tree, Object val, + boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) + { + if (val instanceof Icon) + setIcon((Icon) val); + else + { + setText(val.toString()); + setIcon(null); + this.selected = selected; + this.hasFocus = hasFocus; + setHorizontalAlignment(LEFT); + setOpaque(true); + setVerticalAlignment(TOP); + setEnabled(true); + super.setFont(UIManager.getLookAndFeelDefaults().getFont("Tree.font")); + } + + if (selected) + { + super.setBackground(getBackgroundSelectionColor()); + setForeground(getTextSelectionColor()); + } + else + { + super.setBackground(getBackgroundNonSelectionColor()); + setForeground(getTextNonSelectionColor()); + } + + return this; + } + + /** + * getFont + * + * @return the current Font + */ + public Font getFont() + { + return super.getFont(); + } + + /** + * paint + * + * @param value0 TODO + */ + public void paint(Graphics g) + { + super.paint(g); + } + + /** + * getPreferredSize + * + * @returns Dimension + */ + public Dimension getPreferredSize() + { + return null; // TODO + } // getPreferredSize() + + /** + * validate + */ + public void validate() + { + // Overridden for performance reasons. + } // validate() + + /** + * revalidate + */ + public void revalidate() + { + // Overridden for performance reasons. + } // revalidate() + + /** + * repaint + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + * @param value3 TODO + * @param value4 TODO + */ + public void repaint(long value0, int value1, int value2, int value3, + int value4) + { + // Overridden for performance reasons. + } // repaint() + + /** + * repaint + * + * @param value0 TODO + */ + public void repaint(Rectangle value0) + { + // Overridden for performance reasons. + } // repaint() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + protected void firePropertyChange(String value0, Object value1, + Object value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, byte value1, byte value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, char value1, char value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, short value1, short value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, int value1, int value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, long value1, long value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, float value1, float value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, double value1, double value2) + { + // Overridden for performance reasons. + } // firePropertyChange() + + /** + * firePropertyChange + * + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void firePropertyChange(String value0, boolean v1, boolean v2) + { + // Overridden for performance reasons. + } // firePropertyChange() + +} // DefaultTreeCellRenderer diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeModel.java b/libjava/classpath/javax/swing/tree/DefaultTreeModel.java new file mode 100644 index 0000000..3278ffa --- /dev/null +++ b/libjava/classpath/javax/swing/tree/DefaultTreeModel.java @@ -0,0 +1,455 @@ +/* DefaultTreeModel.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.tree; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * DefaultTreeModel + * @author Andrew Selkirk + */ +public class DefaultTreeModel + implements Serializable, TreeModel +{ + static final long serialVersionUID = -2621068368932566998L; + + /** + * root + */ + protected TreeNode root = null; + + /** + * listenerList + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * asksAllowsChildren + */ + protected boolean asksAllowsChildren; + + /** + * Constructor DefaultTreeModel + * @param value0 TODO + */ + public DefaultTreeModel(TreeNode root) + { + if (root == null) + root = new DefaultMutableTreeNode(); + setRoot(root); + } + + /** + * Constructor DefaultTreeModel + * @param value0 TODO + * @param value1 TODO + */ + public DefaultTreeModel(TreeNode root, boolean asksAllowsChildren) + { + setRoot(root); + this.asksAllowsChildren = asksAllowsChildren; + } + + /** + * writeObject + * @param value0 TODO + * @exception IOException TODO + */ + private void writeObject(ObjectOutputStream value0) throws IOException + { + // TODO + } + + /** + * readObject + * @param value0 TODO + * @exception IOException TODO + * @exception ClassNotFoundException TODO + */ + private void readObject(ObjectInputStream value0) throws IOException, + ClassNotFoundException + { + // TODO + } + + /** + * asksAllowsChildren + * @return boolean + */ + public boolean asksAllowsChildren() + { + return asksAllowsChildren; + } + + /** + * setAsksAllowsChildren + * @param value0 TODO + */ + public void setAsksAllowsChildren(boolean value) + { + asksAllowsChildren = value; // TODO + } + + /** + * setRoot + * @param value0 TODO + */ + public void setRoot(TreeNode root) + { + // Sanity Check + if (root == null) + { + throw new IllegalArgumentException("null root"); + } + // Set new root + this.root = root; + + // TODO + } + + /** + * getRoot + * @return Object + */ + public Object getRoot() + { + return root; + } + + /** + * getIndexOfChild + * @param value0 TODO + * @param value1 TODO + * @return int + */ + public int getIndexOfChild(Object parent, Object child) + { + return 0; // TODO + } + + /** + * getChild + * @param value0 TODO + * @param value1 TODO + * @return Object + */ + public Object getChild(Object node, int idx) + { + if (node instanceof TreeNode) + return ((TreeNode) node).getChildAt(idx); + else + return null; + } + + /** + * getChildCount + * @param value0 TODO + * @return int + */ + public int getChildCount(Object node) + { + if (node instanceof TreeNode) + return ((TreeNode) node).getChildCount(); + else + return 0; + } + + /** + * isLeaf + * @param value0 TODO + * @return boolean + */ + public boolean isLeaf(Object node) + { + if (node instanceof TreeNode) + return ((TreeNode) node).isLeaf(); + else + return true; + } + + /** + * reload + */ + public void reload() + { + // TODO + } + + /** + * reload + * @param value0 TODO + */ + public void reload(TreeNode value0) + { + // TODO + } + + /** + * valueForPathChanged + * @param value0 TODO + * @param value1 TODO + */ + public void valueForPathChanged(TreePath value0, Object value1) + { + // TODO + } + + /** + * insertNodeInto + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void insertNodeInto(MutableTreeNode value0, MutableTreeNode value1, + int value2) + { + // TODO + } + + /** + * removeNodeFromParent + * @param value0 TODO + */ + public void removeNodeFromParent(MutableTreeNode value0) + { + // TODO + } + + /** + * nodeChanged + * @param value0 TODO + */ + public void nodeChanged(TreeNode value0) + { + // TODO + } + + /** + * nodesWereInserted + * @param value0 TODO + * @param value1 TODO + */ + public void nodesWereInserted(TreeNode value0, int[] value1) + { + // TODO + } + + /** + * nodesWereRemoved + * @param value0 TODO + * @param value1 TODO + * @param value2 TODO + */ + public void nodesWereRemoved(TreeNode value0, int[] value1, Object[] value2) + { + // TODO + } + + /** + * nodesChanged + * @param value0 TODO + * @param value1 TODO + */ + public void nodesChanged(TreeNode value0, int[] value1) + { + // TODO + } + + /** + * nodeStructureChanged + * @param value0 TODO + */ + public void nodeStructureChanged(TreeNode value0) + { + // TODO + } + + /** + * getPathToRoot + * @param value0 TODO + * @return TreeNode[] + */ + public TreeNode[] getPathToRoot(TreeNode value0) + { + return null; // TODO + } + + /** + * getPathToRoot + * @param value0 TODO + * @param value1 TODO + * @return TreeNode[] + */ + protected TreeNode[] getPathToRoot(TreeNode value0, int value1) + { + return null; // TODO + } + + /** + * Registers a listere to the model. + * + * @param listener the listener to add + */ + public void addTreeModelListener(TreeModelListener listener) + { + listenerList.add(TreeModelListener.class, listener); + } + + /** + * Removes a listener from the model. + * + * @param listener the listener to remove + */ + public void removeTreeModelListener(TreeModelListener listener) + { + listenerList.remove(TreeModelListener.class, listener); + } + + /** + * Returns all registered TreeModelListener listeners. + * + * @return an array of listeners. + * + * @since 1.4 + */ + public TreeModelListener[] getTreeModelListeners() + { + return (TreeModelListener[]) listenerList + .getListeners(TreeModelListener.class); + } + + /** + * fireTreeNodesChanged + * + * @param source the node being changed + * @param path the path to the root node + * @param childIndices the indices of the changed elements + * @param children the changed elements + */ + protected void fireTreeNodesChanged(Object source, Object[] path, + int[] childIndices, Object[] children) + { + TreeModelEvent event = new TreeModelEvent(source, path, childIndices, + children); + TreeModelListener[] listeners = getTreeModelListeners(); + + for (int i = listeners.length - 1; i >= 0; --i) + listeners[i].treeNodesChanged(event); + } + + /** + * fireTreeNodesInserted + * + * @param source the node where new nodes got inserted + * @param path the path to the root node + * @param childIndices the indices of the new elements + * @param children the new elements + */ + protected void fireTreeNodesInserted(Object source, Object[] path, + int[] childIndices, Object[] children) + { + TreeModelEvent event = new TreeModelEvent(source, path, childIndices, + children); + TreeModelListener[] listeners = getTreeModelListeners(); + + for (int i = listeners.length - 1; i >= 0; --i) + listeners[i].treeNodesInserted(event); + } + + /** + * fireTreeNodesRemoved + * + * @param source the node where nodes got removed- + * @param path the path to the root node + * @param childIndices the indices of the removed elements + * @param children the removed elements + */ + protected void fireTreeNodesRemoved(Object source, Object[] path, + int[] childIndices, Object[] children) + { + TreeModelEvent event = new TreeModelEvent(source, path, childIndices, + children); + TreeModelListener[] listeners = getTreeModelListeners(); + + for (int i = listeners.length - 1; i >= 0; --i) + listeners[i].treeNodesRemoved(event); + } + + /** + * fireTreeStructureChanged + * + * @param source the node where the model has changed + * @param path the path to the root node + * @param childIndices the indices of the affected elements + * @param children the affected elements + */ + protected void fireTreeStructureChanged(Object source, Object[] path, + int[] childIndices, Object[] children) + { + TreeModelEvent event = new TreeModelEvent(source, path, childIndices, + children); + TreeModelListener[] listeners = getTreeModelListeners(); + + for (int i = listeners.length - 1; i >= 0; --i) + listeners[i].treeStructureChanged(event); + } + + /** + * Returns the registered listeners of a given type. + * + * @param listenerType the listener type to return + * + * @return an array of listeners + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } +} diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeSelectionModel.java b/libjava/classpath/javax/swing/tree/DefaultTreeSelectionModel.java new file mode 100644 index 0000000..de27dad --- /dev/null +++ b/libjava/classpath/javax/swing/tree/DefaultTreeSelectionModel.java @@ -0,0 +1,754 @@ +/* DefaultTreeSelectionModel.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.tree; + +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.EventListener; +import java.util.Vector; + +import javax.swing.DefaultListSelectionModel; +import javax.swing.event.EventListenerList; +import javax.swing.event.SwingPropertyChangeSupport; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; + +/** + * DefaultTreeSelectionModel + * + * @author Andrew Selkirk + */ +public class DefaultTreeSelectionModel + implements Cloneable, Serializable, TreeSelectionModel +{ + static final long serialVersionUID = 3288129636638950196L; + + /** + * SELECTION_MODE_PROPERTY + */ + public static final String SELECTION_MODE_PROPERTY = "selectionMode"; + + /** + * Our Swing property change support. + */ + protected SwingPropertyChangeSupport changeSupport; + + /** + * The current selection. + */ + protected TreePath[] selection; + + /** + * Our TreeSelectionListeners. + */ + protected EventListenerList listenerList; + + /** + * The current RowMapper. + */ + protected transient RowMapper rowMapper; + + /** + * The current listSelectionModel. + */ + protected DefaultListSelectionModel listSelectionModel; + + /** + * The current selection mode. + */ + protected int selectionMode; + + /** + * The path that has been added last. + */ + protected TreePath leadPath; + + /** + * The index of the last added path. + */ + protected int leadIndex; + + /** + * The row of the last added path according to the RowMapper. + */ + protected int leadRow; + + /** + * Constructs a new DefaultTreeSelectionModel. + */ + public DefaultTreeSelectionModel() + { + setSelectionMode(DISCONTIGUOUS_TREE_SELECTION); + listenerList = new EventListenerList(); + } + + /** + * Creates a clone of this DefaultTreeSelectionModel with the same + * selection. + * + * @exception CloneNotSupportedException should not be thrown here + * + * @return a clone of this DefaultTreeSelectionModel + */ + public Object clone() throws CloneNotSupportedException + { + return null; // TODO + } + + /** + * Returns a string that shows this object's properties. + * + * @return a string that shows this object's properties + */ + public String toString() + { + return null; // TODO + } + + /** + * writeObject + * + * @param value0 TODO + * @exception IOException TODO + */ + private void writeObject(ObjectOutputStream value0) throws IOException + { + // TODO + } + + /** + * readObject + * + * @param value0 TODO + * @exception IOException TODO + * @exception ClassNotFoundException TODO + */ + private void readObject(ObjectInputStream value0) throws IOException, + ClassNotFoundException + { + // TODO + } + + /** + * Sets the RowMapper that should be used to map between paths and their + * rows. + * + * @param rowMapper the RowMapper to set + * + * @see RowMapper + */ + public void setRowMapper(RowMapper rowMapper) + { + // TODO + } + + /** + * Returns the RowMapper that is currently used to map between paths and + * their rows. + * + * @return the current RowMapper + * + * @see RowMapper + */ + public RowMapper getRowMapper() + { + return rowMapper; + } + + /** + * Sets the current selection mode. Possible values are + * {@link #SINGLE_TREE_SELECTION}, {@link #CONTIGUOUS_TREE_SELECTION} and + * {@link #DISCONTIGUOUS_TREE_SELECTION}. + * + * @param mode the selection mode to be set + * + * @see #getSelectionMode + * @see #SINGLE_TREE_SELECTION + * @see #CONTIGUOUS_TREE_SELECTION + * @see #DISCONTIGUOUS_TREE_SELECTION + */ + public void setSelectionMode(int mode) + { + selectionMode = mode; + } + + /** + * Returns the current selection mode. + * + * @return the current selection mode + * + * @see #setSelectionMode + * @see #SINGLE_TREE_SELECTION + * @see #CONTIGUOUS_TREE_SELECTION + * @see #DISCONTIGUOUS_TREE_SELECTION + */ + public int getSelectionMode() + { + return selectionMode; + } + + /** + * Sets this path as the only selection. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param path the path to set as selection + */ + public void setSelectionPath(TreePath path) + { + selection = new TreePath[] { + path }; + } + + /** + * Sets the paths as selection. This method checks for duplicates and + * removes them. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param paths the paths to set as selection + */ + public void setSelectionPaths(TreePath[] paths) + { + // TODO + } + + /** + * Adds a path to the list of selected paths. This method checks if the path + * is already selected and doesn't add the same path twice. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param path the path to add to the selection + */ + public void addSelectionPath(TreePath path) + { + if (!isPathSelected(path)) + { + if (isSelectionEmpty()) + setSelectionPath(path); + else + { + TreePath[] temp = new TreePath[selection.length + 1]; + System.arraycopy(selection, 0, temp, 0, selection.length); + temp[temp.length - 1] = path; + selection = new TreePath[temp.length]; + System.arraycopy(temp, 0, selection, 0, temp.length); + } + leadPath = path; + fireValueChanged(new TreeSelectionEvent(this, path, true, + leadPath, path)); + } + } + + /** + * Adds the paths to the list of selected paths. This method checks if the + * paths are already selected and doesn't add the same path twice. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param paths the paths to add to the selection + */ + public void addSelectionPaths(TreePath[] paths) + { + if (paths != null) + { + TreePath v0 = null; + for (int i = 0; i < paths.length; i++) + { + v0 = paths[i]; + if (!isPathSelected(v0)) + { + if (isSelectionEmpty()) + setSelectionPath(v0); + else + { + TreePath[] temp = new TreePath[selection.length + 1]; + System.arraycopy(selection, 0, temp, 0, + selection.length); + temp[temp.length - 1] = v0; + selection = new TreePath[temp.length]; + System.arraycopy(temp, 0, selection, 0, temp.length); + } + leadPath = paths[paths.length - 1]; + fireValueChanged(new TreeSelectionEvent(this, v0, true, + leadPath, paths[0])); + } + } + } + } + + /** + * Removes the path from the selection. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param path the path to remove + */ + public void removeSelectionPath(TreePath path) + { + int index = -1; + if (isPathSelected(path)) + { + for (int i = 0; i < selection.length; i++) + { + if (selection[i].equals(path)) + { + index = i; + break; + } + } + TreePath[] temp = new TreePath[selection.length - 1]; + System.arraycopy(selection, 0, temp, 0, index); + System.arraycopy(selection, index + 1, temp, index, + selection.length - index - 1); + selection = new TreePath[temp.length]; + System.arraycopy(temp, 0, selection, 0, temp.length); + + fireValueChanged(new TreeSelectionEvent(this, path, false, + leadPath, path)); + } + } + + /** + * Removes the paths from the selection. + * + * If this changes the selection the registered TreeSelectionListeners are + * notified. + * + * @param paths the paths to remove + */ + public void removeSelectionPaths(TreePath[] paths) + { + if (paths != null) + { + int index = -1; + TreePath v0 = null; + for (int i = 0; i < paths.length; i++) + { + v0 = paths[i]; + if (isPathSelected(v0)) + { + for (int x = 0; x < selection.length; x++) + { + if (selection[i].equals(v0)) + { + index = x; + break; + } + } + TreePath[] temp = new TreePath[selection.length - 1]; + System.arraycopy(selection, 0, temp, 0, index); + System.arraycopy(selection, index + 1, temp, index, + selection.length - index - 1); + selection = new TreePath[temp.length]; + System.arraycopy(temp, 0, selection, 0, temp.length); + + fireValueChanged(new TreeSelectionEvent(this, v0, false, + leadPath, paths[0])); + } + } + } + } + + /** + * Returns the first path in the selection. This is especially useful when + * the selectionMode is {@link #SINGLE_TREE_SELECTION}. + * + * @return the first path in the selection + */ + public TreePath getSelectionPath() + { + if ((selection == null) || (selection.length == 0)) + return null; + else + return selection[0]; + } + + /** + * Returns the complete selection. + * + * @return the complete selection + */ + public TreePath[] getSelectionPaths() + { + return selection; + } + + /** + * Returns the number of paths in the selection. + * + * @return the number of paths in the selection + */ + public int getSelectionCount() + { + if (selection == null) + return 0; + else + return selection.length; + } + + /** + * Checks if a given path is in the selection. + * + * @param path the path to check + * + * @return true if the path is in the selection, + * false otherwise + */ + public boolean isPathSelected(TreePath path) + { + if (selection == null) + return false; + + for (int i = 0; i < selection.length; i++) + { + if (selection[i].equals(path)) + return true; + } + return false; + } + + /** + * Checks if the selection is empty. + * + * @return true if the selection is empty, false + * otherwise + */ + public boolean isSelectionEmpty() + { + return ((selection == null) || (selection.length == 0)); + } + + /** + * Removes all paths from the selection. + */ + public void clearSelection() + { + leadPath = null; + selection = null; + } + + /** + * Adds a TreeSelectionListener object to this model. + * + * @param listener the listener to add + */ + public void addTreeSelectionListener(TreeSelectionListener listener) + { + listenerList.add(TreeSelectionListener.class, listener); + } + + /** + * Removes a TreeSelectionListener object from this model. + * + * @param listener the listener to remove + */ + public void removeTreeSelectionListener(TreeSelectionListener listener) + { + listenerList.remove(TreeSelectionListener.class, listener); + } + + /** + * Returns all TreeSelectionListener added to this model. + * + * @return an array of listeners + * + * @since 1.4 + */ + public TreeSelectionListener[] getTreeSelectionListeners() + { + return (TreeSelectionListener[]) + getListeners(TreeSelectionListener.class); + } + + /** + * fireValueChanged + * + * @param event the event to fire. + */ + protected void fireValueChanged(TreeSelectionEvent event) + { + TreeSelectionListener[] listeners = getTreeSelectionListeners(); + + for (int i = 0; i < listeners.length; ++i) + listeners[i].valueChanged(event); + } + + /** + * Returns all added listeners of a special type. + * + * @param listenerType the listener type + * + * @return an array of listeners + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Returns the currently selected rows. + * + * @return the currently selected rows + */ + public int[] getSelectionRows() + { + if (rowMapper == null) + return null; + else + return rowMapper.getRowsForPaths(selection); + } + + /** + * Returns the smallest row index from the selection. + * + * @return the smallest row index from the selection + */ + public int getMinSelectionRow() + { + if ((rowMapper == null) || (selection == null) + || (selection.length == 0)) + return -1; + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + int minRow = Integer.MAX_VALUE; + for (int index = 0; index < rows.length; index++) + minRow = Math.min(minRow, rows[index]); + return minRow; + } + } + + /** + * Returns the largest row index from the selection. + * + * @return the largest row index from the selection + */ + public int getMaxSelectionRow() + { + if ((rowMapper == null) || (selection == null) + || (selection.length == 0)) + return -1; + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + int maxRow = -1; + for (int index = 0; index < rows.length; index++) + maxRow = Math.max(maxRow, rows[index]); + return maxRow; + } + } + + /** + * Checks if a particular row is selected. + * + * @param row the index of the row to check + * + * @return true if the row is in this selection, + * false otherwise + */ + public boolean isRowSelected(int row) + { + return false; // TODO + } + + /** + * Updates the mappings from TreePaths to row indices. + */ + public void resetRowSelection() + { + // TODO + } + + /** + * getLeadSelectionRow + * + * @return int + */ + public int getLeadSelectionRow() + { + if ((rowMapper == null) || (leadPath == null)) + return -1; + else + return rowMapper.getRowsForPaths(new TreePath[] { + leadPath })[0]; + } + + /** + * getLeadSelectionPath + * + * @return TreePath + */ + public TreePath getLeadSelectionPath() + { + return leadPath; + } + + /** + * Adds a PropertyChangeListener object to this model. + * + * @param listener the listener to add. + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * Removes a PropertyChangeListener object from this model. + * + * @param listener the listener to remove. + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns all added PropertyChangeListener objects. + * + * @return an array of listeners. + * + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return changeSupport.getPropertyChangeListeners(); + } + + /** + * Makes sure the currently selected paths are valid according to the + * current selectionMode. + * + * If the selectionMode is set to {@link #CONTIGUOUS_TREE_SELECTION} and the + * selection isn't contiguous then the selection is reset to the first set + * of contguous paths. + * + * If the selectionMode is set to {@link #SINGLE_TREE_SELECTION} and the + * selection has more than one path, the selection is reset to the contain + * only the first path. + */ + protected void insureRowContinuity() + { + // TODO + } + + /** + * Returns true if the paths are contiguous or we have no + * RowMapper assigned. + * + * @param paths the paths to check for continuity + * @return true if the paths are contiguous or we have no + * RowMapper assigned + */ + protected boolean arePathsContiguous(TreePath[] paths) + { + return false; // TODO + } + + /** + * Checks if the paths can be added. This returns true if: + *