From 5a504f5de0b8c710be509ef09f39d2f26c1ee061 Mon Sep 17 00:00:00 2001 From: fedejeanne Date: Mon, 8 Jul 2024 15:04:12 +0200 Subject: [PATCH] First commit: Swing port for SWT (doesn't work but it compiles) --- binaries/.classpath_swing | 35 + binaries/.settings/org.eclipse.jdt.core.prefs | 2 +- .../.settings/org.eclipse.pde.api.tools.prefs | 26 +- .../.project | 132 + .../META-INF/MANIFEST.MF | 29 + bundles/org.eclipse.swt/.classpath | 2 + .../swing/org/eclipse/swt/awt/SWT_AWT.java | 227 + .../eclipse/swt/accessibility/Accessible.java | 346 + .../org/eclipse/swt/browser/Browser.java | 2408 +- .../org/eclipse/swt/browser/Browser.java | 844 + .../org/eclipse/swt/custom/CTabFolder.java | 4 + .../org/eclipse/swt/custom/HTMLWriter.java | 647 +- .../common/org/eclipse/swt/custom/IME.java | 22 + .../eclipse/swt/custom/MouseNavigator.java | 537 +- .../org/eclipse/swt/custom/RTFWriter.java | 439 +- .../org/eclipse/swt/custom/StyledText.java | 21732 ++++++++-------- .../custom/StyledTextDropTargetEffect.java | 391 +- .../swt/custom/StyledTextRenderer.java | 4054 ++- .../swt/custom/StyledTextWriterBase.java | 486 +- .../org/eclipse/swt/custom/StyledText.java | 8121 ++++++ .../eclipse/swt/custom/StyledTextContent.java | 206 + .../eclipse/swt/custom/StyledTextEvent.java | 51 + .../swt/custom/StyledTextListener.java | 80 + .../swt/custom/StyledTextPrintOptions.java | 86 + .../swt/custom/StyledTextRenderer.java | 1480 ++ .../eclipse/swt/dnd/ByteArrayTransfer.java | 179 + .../swing/org/eclipse/swt/dnd/Clipboard.java | 614 + .../eclipse/swt/dnd/DragAndDropEffect.java | 20 + .../swing/org/eclipse/swt/dnd/DragSource.java | 535 + .../swing/org/eclipse/swt/dnd/DropTarget.java | 454 + .../org/eclipse/swt/dnd/FileTransfer.java | 131 + .../org/eclipse/swt/dnd/HTMLTransfer.java | 113 + .../eclipse/swt/dnd/NoDragAndDropEffect.java | 11 + .../org/eclipse/swt/dnd/RTFTransfer.java | 122 + .../org/eclipse/swt/dnd/TextTransfer.java | 93 + .../swing/org/eclipse/swt/dnd/Transfer.java | 194 + .../org/eclipse/swt/dnd/TransferData.java | 68 + .../org/eclipse/swt/dnd/URLTransfer.java | 121 + .../common/org/eclipse/swt/opengl/GLData.java | 246 +- .../org/eclipse/swt/internal/Platform.java | 11 + .../swt/internal/swing/ArrowButton.java | 87 + .../swing/BrowserLocationChangedEvent.java | 25 + .../swing/BrowserLocationChangingEvent.java | 35 + .../eclipse/swt/internal/swing/CBrowser.java | 289 + .../eclipse/swt/internal/swing/CButton.java | 507 + .../eclipse/swt/internal/swing/CCombo.java | 629 + .../swt/internal/swing/CComboButton.java | 150 + .../swt/internal/swing/CComposite.java | 216 + .../eclipse/swt/internal/swing/CControl.java | 102 + .../eclipse/swt/internal/swing/CCoolBar.java | 94 + .../eclipse/swt/internal/swing/CCoolItem.java | 57 + .../swt/internal/swing/CExpandBar.java | 189 + .../swt/internal/swing/CExpandItem.java | 52 + .../org/eclipse/swt/internal/swing/CGC.java | 250 + .../eclipse/swt/internal/swing/CGroup.java | 174 + .../eclipse/swt/internal/swing/CLabel.java | 248 + .../org/eclipse/swt/internal/swing/CLink.java | 266 + .../org/eclipse/swt/internal/swing/CList.java | 393 + .../swt/internal/swing/CProgressBar.java | 113 + .../org/eclipse/swt/internal/swing/CSash.java | 173 + .../eclipse/swt/internal/swing/CScale.java | 143 + .../swt/internal/swing/CScrollable.java | 23 + .../eclipse/swt/internal/swing/CShell.java | 1176 + .../eclipse/swt/internal/swing/CSlider.java | 143 + .../eclipse/swt/internal/swing/CSpinner.java | 270 + .../swt/internal/swing/CTabFolder.java | 164 + .../eclipse/swt/internal/swing/CTabItem.java | 73 + .../eclipse/swt/internal/swing/CTable.java | 1029 + .../swt/internal/swing/CTableColumn.java | 105 + .../swt/internal/swing/CTableItem.java | 262 + .../org/eclipse/swt/internal/swing/CText.java | 700 + .../eclipse/swt/internal/swing/CToolBar.java | 121 + .../eclipse/swt/internal/swing/CToolItem.java | 264 + .../org/eclipse/swt/internal/swing/CTree.java | 964 + .../swt/internal/swing/CTreeColumn.java | 97 + .../eclipse/swt/internal/swing/CTreeItem.java | 245 + .../swt/internal/swing/Compatibility.java | 35 + .../swing/ComponentBorderResizer.java | 154 + .../swing/DefaultMutableTreeTableNode.java | 85 + .../swing/DefaultTreeTableCellRenderer.java | 53 + .../internal/swing/DisabledStatePanel.java | 150 + .../eclipse/swt/internal/swing/JCoolBar.java | 517 + .../swt/internal/swing/JCoolBarItem.java | 217 + .../swt/internal/swing/JCoolBarLayout.java | 97 + .../swt/internal/swing/JExpandPane.java | 251 + .../swt/internal/swing/JFontChooser.java | 298 + .../swt/internal/swing/JIconRadioButton.java | 47 + .../swt/internal/swing/JMultiLineLabel.java | 231 + .../swt/internal/swing/JStateCheckBox.java | 78 + .../eclipse/swt/internal/swing/JTracker.java | 515 + .../swt/internal/swing/JTreeTable.java | 783 + .../swt/internal/swing/LookAndFeelUtils.java | 207 + .../swt/internal/swing/NullGraphics2D.java | 242 + .../swt/internal/swing/TextFilterEvent.java | 48 + .../internal/swing/TreeTableCellRenderer.java | 16 + .../swt/internal/swing/TreeTableNode.java | 22 + .../swt/internal/swing/UIThreadUtils.java | 238 + .../internal/swing/UnmanagedScrollPane.java | 39 + .../org/eclipse/swt/internal/swing/Utils.java | 568 + .../org/eclipse/swt/printing/PrintDialog.java | 370 + .../org/eclipse/swt/printing/Printer.java | 1118 + .../org/eclipse/swt/program/Program.java | 251 + .../org/eclipse/swt/swtswing/SWT_Swing.java | 172 + .../org/eclipse/swt/graphics/Drawable.java | 24 +- .../org/eclipse/swt/graphics/_Drawable.java | 84 + .../eclipse/swt/printing/_PrinterData.java | 164 + .../common/org/eclipse/swt/widgets/Item.java | 46 +- .../org/eclipse/swt/widgets/Monitor.java | 55 +- .../org/eclipse/swt/widgets/Synchronizer.java | 147 +- .../org/eclipse/swt/widgets/__Monitor.java | 117 + .../swing/org/eclipse/swt/graphics/Color.java | 284 + .../org/eclipse/swt/graphics/Cursor.java | 446 + .../org/eclipse/swt/graphics/Device.java | 829 + .../org/eclipse/swt/graphics/DeviceData.java | 23 + .../swing/org/eclipse/swt/graphics/Font.java | 279 + .../org/eclipse/swt/graphics/FontData.java | 445 + .../org/eclipse/swt/graphics/FontMetrics.java | 198 + .../swing/org/eclipse/swt/graphics/GC.java | 3880 +++ .../org/eclipse/swt/graphics/GCData.java | 48 + .../swing/org/eclipse/swt/graphics/Image.java | 1867 ++ .../org/eclipse/swt/graphics/ImageLoader.java | 334 + .../swing/org/eclipse/swt/graphics/Path.java | 489 + .../org/eclipse/swt/graphics/Pattern.java | 227 + .../org/eclipse/swt/graphics/Region.java | 600 + .../org/eclipse/swt/graphics/TextLayout.java | 1726 ++ .../org/eclipse/swt/graphics/Transform.java | 324 + .../swt/graphics/resources/HelpCursor.gif | Bin 0 -> 176 bytes .../graphics/resources/HelpCursor.properties | 13 + .../swt/graphics/resources/NoCursor.gif | Bin 0 -> 1341 bytes .../graphics/resources/NoCursor.properties | 2 + .../swt/graphics/resources/UpCursor.gif | Bin 0 -> 377 bytes .../graphics/resources/UpCursor.properties | 2 + .../org/eclipse/swt/internal/BidiUtil.java | 108 + .../org/eclipse/swt/internal/ImageList.java | 443 + .../swing/org/eclipse/swt/widgets/Button.java | 915 + .../swing/org/eclipse/swt/widgets/Canvas.java | 352 + .../swing/org/eclipse/swt/widgets/Caret.java | 641 + .../org/eclipse/swt/widgets/ColorDialog.java | 151 + .../swing/org/eclipse/swt/widgets/Combo.java | 1176 + .../org/eclipse/swt/widgets/Composite.java | 1428 + .../org/eclipse/swt/widgets/Control.java | 4818 ++++ .../org/eclipse/swt/widgets/CoolBar.java | 1088 + .../org/eclipse/swt/widgets/CoolItem.java | 577 + .../org/eclipse/swt/widgets/Decorations.java | 1611 ++ .../eclipse/swt/widgets/DirectoryDialog.java | 178 + .../org/eclipse/swt/widgets/Display.java | 2628 ++ .../org/eclipse/swt/widgets/ExpandBar.java | 342 + .../org/eclipse/swt/widgets/ExpandItem.java | 299 + .../org/eclipse/swt/widgets/FileDialog.java | 314 + .../org/eclipse/swt/widgets/FontDialog.java | 235 + .../swing/org/eclipse/swt/widgets/Group.java | 412 + .../swing/org/eclipse/swt/widgets/Label.java | 564 + .../swing/org/eclipse/swt/widgets/Link.java | 284 + .../swing/org/eclipse/swt/widgets/List.java | 1031 + .../swing/org/eclipse/swt/widgets/Menu.java | 1179 + .../org/eclipse/swt/widgets/MenuItem.java | 1186 + .../org/eclipse/swt/widgets/MessageBox.java | 230 + .../org/eclipse/swt/widgets/ProgressBar.java | 187 + .../swing/org/eclipse/swt/widgets/Sash.java | 248 + .../swing/org/eclipse/swt/widgets/Scale.java | 353 + .../org/eclipse/swt/widgets/ScrollBar.java | 940 + .../org/eclipse/swt/widgets/Scrollable.java | 422 + .../swing/org/eclipse/swt/widgets/Shell.java | 2033 ++ .../swing/org/eclipse/swt/widgets/Slider.java | 470 + .../org/eclipse/swt/widgets/Spinner.java | 1051 + .../org/eclipse/swt/widgets/TabFolder.java | 504 + .../org/eclipse/swt/widgets/TabItem.java | 306 + .../swing/org/eclipse/swt/widgets/Table.java | 3479 +++ .../org/eclipse/swt/widgets/TableColumn.java | 686 + .../org/eclipse/swt/widgets/TableItem.java | 962 + .../swing/org/eclipse/swt/widgets/Text.java | 1796 ++ .../org/eclipse/swt/widgets/ToolBar.java | 575 + .../org/eclipse/swt/widgets/ToolItem.java | 910 + .../org/eclipse/swt/widgets/ToolTip.java | 567 + .../org/eclipse/swt/widgets/Tracker.java | 1236 + .../org/eclipse/swt/widgets/TrayItem.java | 471 + .../swing/org/eclipse/swt/widgets/Tree.java | 3697 +++ .../org/eclipse/swt/widgets/TreeColumn.java | 649 + .../org/eclipse/swt/widgets/TreeItem.java | 1250 + .../swing/org/eclipse/swt/widgets/Widget.java | 2208 ++ .../org.eclipse.swt.snippets/.classpath_swing | 7 + examples/org.eclipse.swt.snippets/.project | 5 + 182 files changed, 106171 insertions(+), 15613 deletions(-) create mode 100644 binaries/.classpath_swing create mode 100644 binaries/org.eclipse.swt.swing.win32.x86_64/.project create mode 100644 binaries/org.eclipse.swt.swing.win32.x86_64/META-INF/MANIFEST.MF create mode 100644 bundles/org.eclipse.swt/Eclipse SWT AWT/swing/org/eclipse/swt/awt/SWT_AWT.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/IME.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/DragAndDropEffect.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/DragSource.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/DropTarget.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/HTMLTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/Platform.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ArrowButton.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/BrowserLocationChangedEvent.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/BrowserLocationChangingEvent.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CBrowser.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CButton.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCombo.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComboButton.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComposite.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CControl.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGC.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGroup.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLabel.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLink.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CList.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CProgressBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSash.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CScale.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CScrollable.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CShell.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSlider.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSpinner.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabFolder.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTable.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTableColumn.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTableItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CText.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTree.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTreeColumn.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTreeItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/Compatibility.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ComponentBorderResizer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultMutableTreeTableNode.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultTreeTableCellRenderer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DisabledStatePanel.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBarItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBarLayout.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JExpandPane.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JFontChooser.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JIconRadioButton.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JMultiLineLabel.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JStateCheckBox.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JTracker.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JTreeTable.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/LookAndFeelUtils.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/NullGraphics2D.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/TextFilterEvent.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/TreeTableCellRenderer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/TreeTableNode.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/UIThreadUtils.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/UnmanagedScrollPane.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/Utils.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Printing/swing/org/eclipse/swt/printing/PrintDialog.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Printing/swing/org/eclipse/swt/printing/Printer.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Program/swing/org/eclipse/swt/program/Program.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT Swing/swing/org/eclipse/swt/swtswing/SWT_Swing.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/_Drawable.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/printing/_PrinterData.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/__Monitor.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Color.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/ImageLoader.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.gif create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.gif create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.properties create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/UpCursor.gif create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/UpCursor.properties create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/internal/BidiUtil.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/internal/ImageList.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Button.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Canvas.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/MenuItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/MessageBox.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scale.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Shell.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeItem.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java create mode 100644 examples/org.eclipse.swt.snippets/.classpath_swing diff --git a/binaries/.classpath_swing b/binaries/.classpath_swing new file mode 100644 index 00000000000..b3dd4fb4d8b --- /dev/null +++ b/binaries/.classpath_swing @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/binaries/.settings/org.eclipse.jdt.core.prefs b/binaries/.settings/org.eclipse.jdt.core.prefs index ee1fd8be6de..2be8cf05004 100644 --- a/binaries/.settings/org.eclipse.jdt.core.prefs +++ b/binaries/.settings/org.eclipse.jdt.core.prefs @@ -44,7 +44,7 @@ org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning -org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled diff --git a/binaries/.settings/org.eclipse.pde.api.tools.prefs b/binaries/.settings/org.eclipse.pde.api.tools.prefs index 970d959820b..3c076d647fb 100644 --- a/binaries/.settings/org.eclipse.pde.api.tools.prefs +++ b/binaries/.settings/org.eclipse.pde.api.tools.prefs @@ -46,11 +46,11 @@ FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error -ILLEGAL_EXTEND=Ignore -ILLEGAL_IMPLEMENT=Ignore -ILLEGAL_INSTANTIATE=Ignore -ILLEGAL_OVERRIDE=Ignore -ILLEGAL_REFERENCE=Ignore +ILLEGAL_EXTEND=Warning +ILLEGAL_IMPLEMENT=Warning +ILLEGAL_INSTANTIATE=Warning +ILLEGAL_OVERRIDE=Warning +ILLEGAL_REFERENCE=Warning INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error @@ -63,14 +63,14 @@ INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error -INVALID_ANNOTATION=Error -INVALID_JAVADOC_TAG=Error -INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error -LEAK_EXTEND=Error -LEAK_FIELD_DECL=Error -LEAK_IMPLEMENT=Error -LEAK_METHOD_PARAM=Error -LEAK_METHOD_RETURN_TYPE=Error +INVALID_ANNOTATION=Warning +INVALID_JAVADOC_TAG=Warning +INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Warning +LEAK_EXTEND=Warning +LEAK_FIELD_DECL=Warning +LEAK_IMPLEMENT=Warning +LEAK_METHOD_PARAM=Warning +LEAK_METHOD_RETURN_TYPE=Warning METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error diff --git a/binaries/org.eclipse.swt.swing.win32.x86_64/.project b/binaries/org.eclipse.swt.swing.win32.x86_64/.project new file mode 100644 index 00000000000..060e026f44f --- /dev/null +++ b/binaries/org.eclipse.swt.swing.win32.x86_64/.project @@ -0,0 +1,132 @@ + + + org.eclipse.swt.swing.win32.x86_64 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.pde.api.tools.apiAnalysisNature + + + + .classpath + 1 + PARENT-1-PROJECT_LOC/.classpath_swing + + + .settings + 2 + PARENT-1-PROJECT_LOC/.settings + + + Eclipse SWT + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT + + + Eclipse SWT AWT + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20AWT + + + Eclipse SWT Accessibility + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Accessibility + + + Eclipse SWT Browser + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Browser + + + Eclipse SWT Custom Widgets + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Custom%20Widgets + + + Eclipse SWT Drag and Drop + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Drag%20and%20Drop + + + Eclipse SWT OLE Win32 + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20OLE%20Win32 + + + Eclipse SWT OpenGL + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20OpenGL + + + Eclipse SWT PI + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20PI + + + Eclipse SWT Printing + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Printing + + + Eclipse SWT Program + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Program + + + Eclipse SWT Tests + 2 + PARENT-2-PROJECT_LOC/bundles/org.eclipse.swt/Eclipse%20SWT%20Tests + + + Eclipse SWT Tests + 2 + PARENT-2-PROJECT_LOC/bundles/org.eclipse.swt/Eclipse%20SWT%20Tests + + + Eclipse SWT WebKit + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20WebKit + + + Eclipse SWING + 2 + SWT_HOST_PLUGIN/Eclipse%20SWT%20Swing + + + .settings/.api_filters + 1 + PROJECT_LOC/.settings/.api_filters + + + + + SWT_HOST_PLUGIN + $%7BPARENT-2-PROJECT_LOC%7D/bundles/org.eclipse.swt + + + diff --git a/binaries/org.eclipse.swt.swing.win32.x86_64/META-INF/MANIFEST.MF b/binaries/org.eclipse.swt.swing.win32.x86_64/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..63adf105711 --- /dev/null +++ b/binaries/org.eclipse.swt.swing.win32.x86_64/META-INF/MANIFEST.MF @@ -0,0 +1,29 @@ +Manifest-Version: 1.0 +Fragment-Host: org.eclipse.swt;bundle-version="[3.127.0,4.0.0)" +Bundle-Name: %fragmentName +Bundle-Vendor: %providerName +Bundle-SymbolicName: org.eclipse.swt.swing; singleton:=true +Bundle-Version: 3.127.0.qualifier +Bundle-ManifestVersion: 2 +Bundle-Localization: fragment +Export-Package: + org.eclipse.swt, + org.eclipse.swt.accessibility, + org.eclipse.swt.awt, + org.eclipse.swt.browser, + org.eclipse.swt.custom, + org.eclipse.swt.dnd, + org.eclipse.swt.events, + org.eclipse.swt.graphics, + org.eclipse.swt.layout, + org.eclipse.swt.opengl, + org.eclipse.swt.printing, + org.eclipse.swt.program, + org.eclipse.swt.widgets, + org.eclipse.swt.internal; x-friends:="org.eclipse.ui", + org.eclipse.swt.internal.image; x-internal:=true +Eclipse-PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=x86_64)) +SWT-WS: swing +SWT-OS: win32 +SWT-Arch: x86_64 +Automatic-Module-Name: org.eclipse.swt.swing diff --git a/bundles/org.eclipse.swt/.classpath b/bundles/org.eclipse.swt/.classpath index 12be8d4f662..e3ee7b56661 100644 --- a/bundles/org.eclipse.swt/.classpath +++ b/bundles/org.eclipse.swt/.classpath @@ -2,4 +2,6 @@ + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT AWT/swing/org/eclipse/swt/awt/SWT_AWT.java b/bundles/org.eclipse.swt/Eclipse SWT AWT/swing/org/eclipse/swt/awt/SWT_AWT.java new file mode 100644 index 00000000000..a4e7c8dad51 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT AWT/swing/org/eclipse/swt/awt/SWT_AWT.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.awt; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/* SWT Imports */ +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.internal.Library; +import org.eclipse.swt.internal.swing.CComposite; +import org.eclipse.swt.internal.swing.Utils; + +/* AWT Imports */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Canvas; +import java.awt.Frame; +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.Toolkit; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowEvent; +import java.awt.event.FocusEvent; + +/** + * This class provides a bridge between SWT and AWT, so that it + * is possible to embed AWT components in SWT and vice versa. + * + * @since 3.0 + */ +public class SWT_AWT { + + /** + * Key for looking up the embedded frame for a Composite using + * getData(). + */ + static String EMBEDDED_FRAME_KEY = "org.eclipse.swt.awt.SWT_AWT.embeddedFrame"; + +/** + * Returns a java.awt.Frame which is the embedded frame + * associated with the specified composite. + * + * @param parent the parent Composite of the java.awt.Frame + * @return a java.awt.Frame the embedded frame or null. + * + * @exception IllegalArgumentException + * + * @since 3.2 + */ +public static Frame getFrame (Composite parent) { + if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if ((parent.getStyle () & SWT.EMBEDDED) == 0) return null; + return (Frame)parent.getData(EMBEDDED_FRAME_KEY); +} + +/** + * Creates a new java.awt.Frame. This frame is the root for + * the AWT components that will be embedded within the composite. In order + * for the embedding to succeed, the composite must have been created + * with the SWT.EMBEDDED style. + *

+ * IMPORTANT: As of JDK1.5, the embedded frame does not receive mouse events. + * When a lightweight component is added as a child of the embedded frame, + * the cursor does not change. In order to work around both these problems, it is + * strongly recommended that a heavyweight component such as java.awt.Panel + * be added to the frame as the root of all components. + *

+ * + * @param parent the parent Composite of the new java.awt.Frame + * @return a java.awt.Frame to be the parent of the embedded AWT components + * + * @exception IllegalArgumentException + * + * @since 3.0 + */ +public static Frame new_Frame (final Composite parent) { + if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if ((parent.getStyle () & SWT.EMBEDDED) == 0) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + final Container container = ((CComposite)parent.handle).getClientArea(); + final Frame frame = new Frame() { + public void setLayout(LayoutManager mgr) { + if(container != null) { + container.setLayout(mgr); + } + } + protected void addImpl(Component comp, Object constraints, int index) { + container.add(comp, constraints, index); + } + }; + container.setLayout(new BorderLayout(0, 0)); + parent.setData(EMBEDDED_FRAME_KEY, frame); +// frame.addNotify(); + + /* + * Generate the appropriate events to activate and deactivate + * the embedded frame. This is needed in order to make keyboard + * focus work properly for lightweights. + */ + Listener listener = new Listener () { + public void handleEvent (Event e) { + switch (e.type) { + case SWT.Dispose: + parent.setVisible(false); + EventQueue.invokeLater(new Runnable () { + public void run () { + frame.dispose (); + } + }); + break; + case SWT.Activate: + EventQueue.invokeLater(new Runnable () { + public void run () { + if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) { + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED)); + frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_GAINED)); + } else { + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED)); + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_GAINED_FOCUS)); + } + } + }); + break; + case SWT.Deactivate: + EventQueue.invokeLater(new Runnable () { + public void run () { + if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) { + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED)); + frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_LOST)); + } else { + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_LOST_FOCUS)); + frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED)); + } + } + }); + break; + } + } + }; + parent.addListener (SWT.Activate, listener); + parent.addListener (SWT.Deactivate, listener); + parent.addListener (SWT.Dispose, listener); + + parent.getDisplay().asyncExec(new Runnable() { + public void run () { + if (parent.isDisposed()) return; + final Rectangle clientArea = parent.getClientArea(); + EventQueue.invokeLater(new Runnable () { + public void run () { + frame.setSize (clientArea.width, clientArea.height); + frame.validate (); + } + }); + } + }); + return frame; +} + +/** + * Creates a new Shell. This Shell is the root for + * the SWT widgets that will be embedded within the AWT canvas. + * + * @param display the display for the new Shell + * @param parent the parent java.awt.Canvas of the new Shell + * @return a Shell to be the parent of the embedded SWT widgets + * + * @exception IllegalArgumentException + * + * @since 3.0 + */ +public static Shell new_Shell (final Display display, final Canvas parent) { + if (display == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + Utils.notImplemented(); return null; +// int handle = 0; +// try { +// loadLibrary (); +// handle = getAWTHandle (parent); +// } catch (Throwable e) { +// SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e); +// } +// if (handle == 0) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, " [peer not created]"); +// +// final Shell shell = Shell.win32_new (display, handle); +// parent.addComponentListener(new ComponentAdapter () { +// public void componentResized (ComponentEvent e) { +// display.syncExec (new Runnable () { +// public void run () { +// Dimension dim = parent.getSize (); +// shell.setSize (dim.width, dim.height); +// } +// }); +// } +// }); +// shell.setVisible (true); +// return shell; +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java new file mode 100644 index 00000000000..6608a5b0e45 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java @@ -0,0 +1,346 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.accessibility; + + +import java.util.Vector; + +import javax.accessibility.AccessibleContext; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; + +/** + * Instances of this class provide a bridge between application + * code and assistive technology clients. Many platforms provide + * default accessible behavior for most widgets, and this class + * allows that default behavior to be overridden. Applications + * can get the default Accessible object for a control by sending + * it getAccessible, and then add an accessible listener + * to override simple items like the name and help string, or they + * can add an accessible control listener to override complex items. + * As a rule of thumb, an application would only want to use the + * accessible control listener to implement accessibility for a + * custom control. + * + * @see Control#getAccessible + * @see AccessibleListener + * @see AccessibleEvent + * @see AccessibleControlListener + * @see AccessibleControlEvent + * + * @since 2.0 + */ +public class Accessible { + Control control; + AccessibleContext accessibleContext; + Vector accessibleListeners = new Vector(); + Vector accessibleControlListeners = new Vector(); + Vector textListeners = new Vector (); + + Accessible(Control control) { + this.control = control; + accessibleContext = control.handle.getAccessibleContext(); + } + + /** + * Invokes platform specific functionality to allocate a new accessible object. + *

+ * IMPORTANT: This method is not part of the public + * API for Accessible. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

+ * + * @param control the control to get the accessible object for + * @return the platform specific accessible object + */ + public static Accessible internal_new_Accessible(Control control) { + return new Accessible(control); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for certain strings, + * such as name, description, help, or keyboard shortcut. The + * listener is notified by sending it one of the messages defined + * in the AccessibleListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for a name, description, help, or keyboard shortcut string + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleListener + * @see #removeAccessibleListener + */ + public void addAccessibleListener(AccessibleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + accessibleListeners.addElement(listener); + } + + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for certain strings, + * such as name, description, help, or keyboard shortcut. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for a name, description, help, or keyboard shortcut string + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleListener + * @see #addAccessibleListener + */ + public void removeAccessibleListener(AccessibleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + accessibleListeners.removeElement(listener); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for custom control + * specific information. The listener is notified by sending it + * one of the messages defined in the AccessibleControlListener + * interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom control specific information + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleControlListener + * @see #removeAccessibleControlListener + */ + public void addAccessibleControlListener(AccessibleControlListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + accessibleControlListeners.addElement(listener); + } + + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for custom control + * specific information. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for custom control specific information + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleControlListener + * @see #addAccessibleControlListener + */ + public void removeAccessibleControlListener(AccessibleControlListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + accessibleControlListeners.removeElement(listener); + } + + /** + * Adds the listener to the collection of listeners who will + * be notified when an accessible client asks for custom text control + * specific information. The listener is notified by sending it + * one of the messages defined in the AccessibleTextListener + * interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom text control specific information + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleTextListener + * @see #removeAccessibleTextListener + * + * @since 3.0 + */ + public void addAccessibleTextListener (AccessibleTextListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + textListeners.addElement (listener); + } + + /** + * Removes the listener from the collection of listeners who will + * be notified when an accessible client asks for custom text control + * specific information. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for custom text control specific information + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @see AccessibleTextListener + * @see #addAccessibleTextListener + * + * @since 3.0 + */ + public void removeAccessibleTextListener (AccessibleTextListener listener) { + checkWidget (); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + textListeners.removeElement (listener); + } + + /** + * Returns the control for this Accessible object. + * + * @return the receiver's control + * @since 3.0 + */ + public Control getControl() { + return control; + } + + /** + * Sends a message to accessible clients that the child selection + * within a custom container control has changed. + * + * @exception SWTException + * + * @since 3.0 + */ + public void selectionChanged () { + } + + /** + * Sends a message to accessible clients that the text + * caret has moved within a custom control. + * + * @param index the new caret index within the control + * + * @exception SWTException + * + * @since 3.0 + */ + public void textCaretMoved (int index) { + } + + /** + * Sends a message to accessible clients that the text + * within a custom control has changed. + * + * @param type the type of change, one of ACC.NOTIFY_TEXT_INSERT + * or ACC.NOTIFY_TEXT_DELETE + * @param startIndex the text index within the control where the insertion or deletion begins + * @param length the non-negative length in characters of the insertion or deletion + * + * @exception SWTException + * + * @see ACC#TEXT_INSERT + * @see ACC#TEXT_DELETE + * + * @since 3.0 + */ + public void textChanged (int type, int startIndex, int length) { + } + + /** + * Sends a message to accessible clients that the text + * selection has changed within a custom control. + * + * @exception SWTException + * + * @since 3.0 + */ + public void textSelectionChanged () { + } + + /** + * Sends a message to accessible clients indicating that the focus + * has changed within a custom control. + * + * @param childID an identifier specifying a child of the control + * + * @exception SWTException + */ + public void setFocus(int childID) { + } + + /** + * Invokes platform specific functionality to dispose an accessible object. + *

+ * IMPORTANT: This method is not part of the public + * API for Accessible. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

+ */ + public void internal_dispose_Accessible() { + } + + /* checkWidget was copied from Widget, and rewritten to work in this package */ + void checkWidget () { + if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS); + if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED); + } + + /* isValidThread was copied from Widget, and rewritten to work in this package */ + boolean isValidThread () { + return control.getDisplay ().getThread () == Thread.currentThread () || SwingUtilities.isEventDispatchThread(); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java index 0bcc46d6cc6..b590e1db2f6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java @@ -1,1204 +1,1204 @@ -/******************************************************************************* - * Copyright (c) 2003, 2022 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.swt.browser; - -import org.eclipse.swt.*; -import org.eclipse.swt.widgets.*; - -/** - * Instances of this class implement the browser user interface - * metaphor. It allows the user to visualize and navigate through - * HTML documents. - *

- * Note that although this class is a subclass of Composite, - * it does not make sense to set a layout on it. - *

- *
- *
Styles:
- *
NONE, WEBKIT
- *
Events:
- *
CloseWindowListener, LocationListener, OpenWindowListener, ProgressListener, StatusTextListener, TitleListener, VisibilityWindowListener
- *
- *

- * IMPORTANT: This class is not intended to be subclassed. - *

- * - * @see Browser snippets - * @see SWT Examples: ControlExample, BrowserExample - * @see Sample code and further information - * - * @since 3.0 - * @noextend This class is not intended to be subclassed by clients. - */ - -public class Browser extends Composite { - WebBrowser webBrowser; - int userStyle; - boolean isClosing; - - static int DefaultType = SWT.DEFAULT; - - static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$ - static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$ - static final String PROPERTY_DEFAULTTYPE = "org.eclipse.swt.browser.DefaultType"; //$NON-NLS-1$ - -/** - * Constructs a new instance of this class given its parent - * and a style value describing its behavior and appearance. - *

- * The style value is either one of the style constants defined in - * class SWT which is applicable to instances of this - * class, or must be built by bitwise OR'ing together - * (that is, using the int "|" operator) two or more - * of those SWT style constants. The class description - * lists the style constants that are applicable to the class. - * Style bits are also inherited from superclasses. - *

- * - * @param parent a widget which will be the parent of the new instance (cannot be null) - * @param style the style of widget to construct - * - * @exception IllegalArgumentException - * @exception SWTException - * @exception SWTError - * - * @see Widget#getStyle - * - * @since 3.0 - */ -public Browser (Composite parent, int style) { - super (checkParent (parent), checkStyle (style)); - userStyle = style; - - String platform = SWT.getPlatform (); - if ("gtk".equals (platform)) { //$NON-NLS-1$ - parent.getDisplay ().setData (NO_INPUT_METHOD, null); - } - - style = getStyle (); - webBrowser = new BrowserFactory ().createWebBrowser (style); - if (webBrowser != null) { - webBrowser.setBrowser (this); - webBrowser.create (parent, style); - return; - } - dispose (); - - String errMsg = " because there is no underlying browser available.\n"; - switch (SWT.getPlatform()) { - case "gtk": - errMsg = errMsg + "Please ensure that WebKit with its GTK 3.x/4.x bindings is installed."; - break; - case "cocoa": - errMsg = errMsg + "SWT failed to load the WebKit library.\n"; - break; - case "win32": - errMsg = errMsg + "SWT uses either IE or WebKit. Either the SWT.WEBKIT flag is passed and the WebKit library was not " - + "loaded properly by SWT, or SWT failed to load IE.\n"; - break; - default: - break; - } - SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg); -} - -static Composite checkParent (Composite parent) { - String platform = SWT.getPlatform (); - if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$ - - /* - * Note. Mozilla provides all IM support needed for text input in web pages. - * If SWT creates another input method context for the widget it will cause - * indeterminate results to happen (hangs and crashes). The fix is to prevent - * SWT from creating an input method context for the Browser widget. - */ - if (parent != null && !parent.isDisposed ()) { - Display display = parent.getDisplay (); - if (display != null) { - if (display.getThread () == Thread.currentThread ()) { - display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$ - } - } - } - return parent; -} - -static int checkStyle(int style) { - String platform = SWT.getPlatform (); - if (DefaultType == SWT.DEFAULT) { - /* - * Some Browser clients that explicitly specify the native renderer to use (by - * creating a Browser with SWT.WEBKIT) may also need to specify that all - * "default" Browser instances (those created with style SWT.NONE) should use - * this renderer as well. This may be needed in order to avoid incompatibilities - * that can arise from having multiple native renderers loaded within the same - * process. A client can do this by setting the - * "org.eclipse.swt.browser.DefaultType" java system property to a value like - * "ie" or "webkit". - */ - - /* - * Plug-ins need an opportunity to set the org.eclipse.swt.browser.DefaultType - * system property before the first Browser is created. To facilitate this, - * reflection is used to reference non-existent class - * org.eclipse.swt.browser.BrowserInitializer the first time a Browser is created. - * A client wishing to use this hook can do so by creating a fragment of - * org.eclipse.swt that implements this class and sets the system property in its - * static initializer. - */ - try { - Class.forName ("org.eclipse.swt.browser.BrowserInitializer"); //$NON-NLS-1$ - } catch (ClassNotFoundException e) { - /* no fragment is providing this class, which is the typical case */ - } - - String value = System.getProperty (PROPERTY_DEFAULTTYPE); - if (value != null) { - int index = 0; - int length = value.length(); - do { - int newIndex = value.indexOf(',', index); - if (newIndex == -1) { - newIndex = length; - } - String current = value.substring(index, newIndex).trim(); - if (current.equalsIgnoreCase ("webkit")) { //$NON-NLS-1$ - DefaultType = SWT.WEBKIT; - break; - } else if (current.equalsIgnoreCase ("edge") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$ - DefaultType = SWT.EDGE; - } else if (current.equalsIgnoreCase ("ie") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$ - DefaultType = SWT.NONE; - break; - } - index = newIndex + 1; - } while (index < length); - } - if (DefaultType == SWT.DEFAULT) { - DefaultType = SWT.NONE; - } - } - /* If particular backend isn't specified, use the value from the system property. */ - if ((style & (SWT.WEBKIT | SWT.EDGE)) == 0) { - style |= DefaultType; - } - if ("win32".equals (platform) && (style & SWT.EDGE) != 0) { //$NON-NLS-1$ - /* Hack to enable Browser to receive focus. */ - style |= SWT.EMBEDDED; - } - return style; -} - -@Override -protected void checkWidget () { - super.checkWidget (); -} - -/** - * Clears all session cookies from all current Browser instances. - * - * @since 3.2 - */ -public static void clearSessions () { - WebBrowser.clearSessions (); -} - -/** - * Returns the value of a cookie that is associated with a URL. - * Note that cookies are shared amongst all Browser instances. - * - * @param name the cookie name - * @param url the URL that the cookie is associated with - * @return the cookie value, or null if no such cookie exists - * - * @exception IllegalArgumentException - * - * @since 3.5 - */ -public static String getCookie (String name, String url) { - if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return WebBrowser.GetCookie (name, url); -} - -/** - * Sets a cookie on a URL. Note that cookies are shared amongst all Browser instances. - * - * The value parameter must be a cookie header string that - * complies with RFC 2109. - * The value is passed through to the native browser unchanged. - *

- * Example value strings: - * foo=bar (basic session cookie) - * foo=bar; path=/; domain=.eclipse.org (session cookie) - * foo=bar; expires=Tue, 01-Jan-2030 00:00:01 GMT (persistent cookie) - * foo=; expires=Thu, 01-Jan-1970 00:00:01 GMT (deletes cookie foo) - * - * @param value the cookie value - * @param url the URL to associate the cookie with - * @return true if the cookie was successfully set and false otherwise - * - * @exception IllegalArgumentException

- * - * @since 3.5 - */ -public static boolean setCookie (String value, String url) { - if (value == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return WebBrowser.SetCookie (value, url, true); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when authentication is required. - *

- * This notification occurs when a page requiring authentication is - * encountered. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.5 - */ -public void addAuthenticationListener (AuthenticationListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addAuthenticationListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when the window hosting the receiver should be closed. - *

- * This notification occurs when a javascript command such as - * window.close gets executed by a Browser. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addCloseWindowListener (CloseWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addCloseWindowListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when the current location has changed or is about to change. - *

- * This notification typically occurs when the application navigates - * to a new location with {@link #setUrl(String)} or when the user - * activates a hyperlink. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addLocationListener (LocationListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addLocationListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when a new window needs to be created. - *

- * This notification occurs when a javascript command such as - * window.open gets executed by a Browser. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addOpenWindowListener (OpenWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addOpenWindowListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when a progress is made during the loading of the current - * URL or when the loading of the current URL has been completed. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addProgressListener (ProgressListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addProgressListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when the status text is changed. - *

- * The status text is typically displayed in the status bar of - * a browser application. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addStatusTextListener (StatusTextListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addStatusTextListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when the title of the current document is available - * or has changed. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addTitleListener (TitleListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addTitleListener (listener); -} - -/** - * Adds the listener to the collection of listeners who will be - * notified when a window hosting the receiver needs to be displayed - * or hidden. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void addVisibilityWindowListener (VisibilityWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.addVisibilityWindowListener (listener); -} - -/** - * Navigate to the previous session history item. - * - * @return true if the operation was successful and false otherwise - * - * @exception SWTException - * - * @see #forward - * - * @since 3.0 - */ -public boolean back () { - checkWidget(); - return webBrowser.back (); -} - -@Override -protected void checkSubclass () { - String name = getClass ().getName (); - int index = name.lastIndexOf ('.'); - if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) { - SWT.error (SWT.ERROR_INVALID_SUBCLASS); - } -} - -/** - * Executes the specified script. - *

- * Executes a script containing javascript commands in the context of the current document. - * If document-defined functions or properties are accessed by the script then this method - * should not be invoked until the document has finished loading (ProgressListener.completed() - * gives notification of this). - * - * @param script the script with javascript commands - * - * @return true if the operation was successful and false otherwise - * - * @exception IllegalArgumentException

- * - * @exception SWTException - * - * @see ProgressListener#completed(ProgressEvent) - * - * @since 3.1 - */ -public boolean execute (String script) { - checkWidget(); - if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return webBrowser.execute (script); -} - -/** - * Attempts to dispose the receiver, but allows the dispose to be vetoed - * by the user in response to an onbeforeunload listener - * in the Browser's current page. - * - * @return true if the receiver was disposed, and false otherwise - * - * @exception SWTException - * - * @see #dispose() - * - * @since 3.6 - */ -public boolean close () { - checkWidget(); - if (webBrowser.close ()) { - isClosing = true; - dispose (); - isClosing = false; - return true; - } - return false; -} - -/** - * Returns the result, if any, of executing the specified script. - *

- * Evaluates a script containing javascript commands in the context of - * the current document. If document-defined functions or properties - * are accessed by the script then this method should not be invoked - * until the document has finished loading (ProgressListener.completed() - * gives notification of this). - *

- * If the script returns a value with a supported type then a java - * representation of the value is returned. The supported - * javascript -> java mappings are: - *

- * - * An SWTException is thrown if the return value has an - * unsupported type, or if evaluating the script causes a javascript - * error to be thrown. - * - * @param script the script with javascript commands - * - * @return the return value, if any, of executing the script - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @see Browser#evaluate(String,boolean) - * @see ProgressListener#completed(ProgressEvent) - * - * @since 3.5 - */ -public Object evaluate (String script) throws SWTException { - checkWidget(); - return evaluate (script, false); -} - -/** - * Returns the result, if any, of executing the specified script. - *

- * Evaluates a script containing javascript commands. - * When trusted is true script is executed in the context of Chrome - * with Chrome security privileges. - * When trusted is false script is executed in the context of the - * current document with normal privileges. - *

- * If document-defined functions or properties are accessed by the script then - * this method should not be invoked until the document has finished loading - * (ProgressListener.completed() gives notification of this). - *

- * If the script returns a value with a supported type then a java - * representation of the value is returned. The supported - * javascript -> java mappings are: - *

- * An SWTException is thrown if the return value has an - * unsupported type, or if evaluating the script causes a javascript - * error to be thrown. - * - * @param script the script with javascript commands - * @param trusted true or false depending on the security context to be used - * - * @return the return value, if any, of executing the script - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @see ProgressListener#completed(ProgressEvent) - */ -public Object evaluate (String script, boolean trusted) throws SWTException { - checkWidget(); - if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return webBrowser.evaluate (script, trusted); -} - -/** - * Navigate to the next session history item. - * - * @return true if the operation was successful and false otherwise - * - * @exception SWTException - * - * @see #back - * - * @since 3.0 - */ -public boolean forward () { - checkWidget(); - return webBrowser.forward (); -} - -/** - * Returns the type of native browser being used by this instance. - * Examples: "ie", "webkit" - * - * @return the type of the native browser - * - * @since 3.5 - */ -public String getBrowserType () { - checkWidget(); - return webBrowser.getBrowserType (); -} - -/** - * Returns true if javascript will be allowed to run in pages - * subsequently viewed in the receiver, and false otherwise. - * Note that this may not reflect the javascript enablement on the currently- - * viewed page if setJavascriptEnabled() has been invoked during - * its lifetime. - * - * @return the receiver's javascript enabled state - * - * @exception SWTException - * - * @see #setJavascriptEnabled - * - * @since 3.5 - */ -public boolean getJavascriptEnabled () { - checkWidget(); - return webBrowser.jsEnabledOnNextPage; -} - -@Override -public int getStyle () { - /* - * If SWT.BORDER was specified at creation time then getStyle() should answer - * it even though it is removed for IE on win32 in checkStyle(). - */ - return super.getStyle () | (userStyle & SWT.BORDER); -} - -/** - * Returns a string with HTML that represents the content of the current page. - * - * @return HTML representing the current page or an empty String - * if this is empty.
- *

Note, the exact return value is platform dependent. - * For example on Windows, the returned string is the proccessed webpage - * with javascript executed and missing html tags added. - * On Linux and OS X, this returns the original HTML before the browser has - * processed it.

- * - * @exception SWTException - * - * @since 3.4 - */ -public String getText () { - checkWidget(); - return webBrowser.getText (); -} - -/** - * Returns the current URL. - * - * @return the current URL or an empty String if there is no current URL - * - * @exception SWTException - * - * @see #setUrl - * - * @since 3.0 - */ -public String getUrl () { - checkWidget(); - return webBrowser.getUrl (); -} - -/** - * Returns the JavaXPCOM nsIWebBrowser for the receiver, or null - * if it is not available. In order for an nsIWebBrowser to be returned all - * of the following must be true: - * - * @return the receiver's JavaXPCOM nsIWebBrowser or null - * - * @since 3.3 - * @deprecated SWT.MOZILLA is deprecated and XULRunner as a browser renderer is no longer supported. - */ -@Deprecated -public Object getWebBrowser () { - checkWidget(); - return webBrowser.getWebBrowser (); -} - -/** - * Returns true if the receiver can navigate to the - * previous session history item, and false otherwise. - * - * @return the receiver's back command enabled state - * - * @exception SWTException - * - * @see #back - */ -public boolean isBackEnabled () { - checkWidget(); - return webBrowser.isBackEnabled (); -} - -@Override -public boolean isFocusControl () { - checkWidget(); - if (webBrowser.isFocusControl ()) return true; - return super.isFocusControl (); -} - -/** - * Returns true if the receiver can navigate to the - * next session history item, and false otherwise. - * - * @return the receiver's forward command enabled state - * - * @exception SWTException - * - * @see #forward - */ -public boolean isForwardEnabled () { - checkWidget(); - return webBrowser.isForwardEnabled (); -} - -/** - * Refresh the current page. - * - * @exception SWTException - * - * @since 3.0 - */ -public void refresh () { - checkWidget(); - webBrowser.refresh (); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when authentication is required. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.5 - */ -public void removeAuthenticationListener (AuthenticationListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeAuthenticationListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when the window hosting the receiver should be closed. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeCloseWindowListener (CloseWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeCloseWindowListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when the current location is changed or about to be changed. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeLocationListener (LocationListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeLocationListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when a new window needs to be created. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeOpenWindowListener (OpenWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeOpenWindowListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when a progress is made during the loading of the current - * URL or when the loading of the current URL has been completed. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeProgressListener (ProgressListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeProgressListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when the status text is changed. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeStatusTextListener (StatusTextListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeStatusTextListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when the title of the current document is available - * or has changed. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeTitleListener (TitleListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeTitleListener (listener); -} - -/** - * Removes the listener from the collection of listeners who will - * be notified when a window hosting the receiver needs to be displayed - * or hidden. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @since 3.0 - */ -public void removeVisibilityWindowListener (VisibilityWindowListener listener) { - checkWidget(); - if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - webBrowser.removeVisibilityWindowListener (listener); -} - -/** - * Sets whether javascript will be allowed to run in pages subsequently - * viewed in the receiver. Note that setting this value does not affect - * the running of javascript in the current page. - * - * @param enabled the receiver's new javascript enabled state - * - * @exception SWTException - * - * @since 3.5 - */ -public void setJavascriptEnabled (boolean enabled) { - checkWidget(); - webBrowser.jsEnabledOnNextPage = enabled; -} - -/** - * Renders a string containing HTML. The rendering of the content occurs asynchronously. - * The rendered page will be given trusted permissions; to render the page with untrusted - * permissions use setText(String html, boolean trusted) instead. - *

- * The html parameter is Unicode-encoded since it is a java String. - * As a result, the HTML meta tag charset should not be set. The charset is implied - * by the String itself. - * - * @param html the HTML content to be rendered - * - * @return true if the operation was successful and false otherwise. - * - * @exception IllegalArgumentException

- * - * @exception SWTException - * - * @see #setText(String,boolean) - * @see #setUrl - * - * @since 3.0 - */ -public boolean setText (String html) { - checkWidget(); - return setText (html, true); -} - -/** - * Renders a string containing HTML. The rendering of the content occurs asynchronously. - * The rendered page can be given either trusted or untrusted permissions. - *

- * The html parameter is Unicode-encoded since it is a java String. - * As a result, the HTML meta tag charset should not be set. The charset is implied - * by the String itself. - *

- * The trusted parameter affects the permissions that will be granted to the rendered - * page. Specifying true for trusted gives the page permissions equivalent - * to a page on the local file system, while specifying false for trusted - * gives the page permissions equivalent to a page from the internet. Page content should - * be specified as trusted if the invoker created it or trusts its source, since this would - * allow (for instance) style sheets on the local file system to be referenced. Page - * content should be specified as untrusted if its source is not trusted or is not known. - * - * @param html the HTML content to be rendered - * @param trusted false if the rendered page should be granted restricted - * permissions and true otherwise - * - * @return true if the operation was successful and false otherwise. - * - * @exception IllegalArgumentException

- * - * @exception SWTException - * - * @see #setText(String) - * @see #setUrl - * - * @since 3.6 - */ -public boolean setText (String html, boolean trusted) { - checkWidget(); - if (html == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return webBrowser.setText (html, trusted); -} - -/** - * Begins loading a URL. The loading of its content occurs asynchronously. - * - * @param url the URL to be loaded - * - * @return true if the operation was successful and false otherwise. - * - * @exception IllegalArgumentException - * - * @exception SWTException - * - * @see #getUrl - * @see #setUrl(String,String,String[]) - * - * @since 3.0 - */ -public boolean setUrl (String url) { - checkWidget(); - return setUrl (url, null, null); -} - -/** - * Begins loading a URL. The loading of its content occurs asynchronously. - *

- * If the URL causes an HTTP request to be initiated then the provided - * postData and header arguments, if any, are - * sent with the request. A value in the headers argument - * must be a name-value pair with a colon separator in order to be sent - * (for example: "user-agent: custom"). - * - * @param url the URL to be loaded - * @param postData post data to be sent with the request, or null - * @param headers header lines to be sent with the request, or null - * - * @return true if the operation was successful and false otherwise. - * - * @exception IllegalArgumentException

- * - * @exception SWTException - * - * @since 3.6 - */ -public boolean setUrl (String url, String postData, String[] headers) { - checkWidget(); - if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return webBrowser.setUrl (url, postData, headers); -} - -/** - * Stop any loading and rendering activity. - * - * @exception SWTException - * - * @since 3.0 - */ -public void stop () { - checkWidget(); - webBrowser.stop (); -} -} +///******************************************************************************* +// * Copyright (c) 2003, 2022 IBM Corporation and others. +// * +// * This program and the accompanying materials +// * are made available under the terms of the Eclipse Public License 2.0 +// * which accompanies this distribution, and is available at +// * https://www.eclipse.org/legal/epl-2.0/ +// * +// * SPDX-License-Identifier: EPL-2.0 +// * +// * Contributors: +// * IBM Corporation - initial API and implementation +// *******************************************************************************/ +//package org.eclipse.swt.browser; +// +//import org.eclipse.swt.*; +//import org.eclipse.swt.widgets.*; +// +///** +// * Instances of this class implement the browser user interface +// * metaphor. It allows the user to visualize and navigate through +// * HTML documents. +// *

+// * Note that although this class is a subclass of Composite, +// * it does not make sense to set a layout on it. +// *

+// *
+// *
Styles:
+// *
NONE, WEBKIT
+// *
Events:
+// *
CloseWindowListener, LocationListener, OpenWindowListener, ProgressListener, StatusTextListener, TitleListener, VisibilityWindowListener
+// *
+// *

+// * IMPORTANT: This class is not intended to be subclassed. +// *

+// * +// * @see Browser snippets +// * @see SWT Examples: ControlExample, BrowserExample +// * @see Sample code and further information +// * +// * @since 3.0 +// * @noextend This class is not intended to be subclassed by clients. +// */ +// +//public class Browser extends Composite { +// WebBrowser webBrowser; +// int userStyle; +// boolean isClosing; +// +// static int DefaultType = SWT.DEFAULT; +// +// static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$ +// static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$ +// static final String PROPERTY_DEFAULTTYPE = "org.eclipse.swt.browser.DefaultType"; //$NON-NLS-1$ +// +///** +// * Constructs a new instance of this class given its parent +// * and a style value describing its behavior and appearance. +// *

+// * The style value is either one of the style constants defined in +// * class SWT which is applicable to instances of this +// * class, or must be built by bitwise OR'ing together +// * (that is, using the int "|" operator) two or more +// * of those SWT style constants. The class description +// * lists the style constants that are applicable to the class. +// * Style bits are also inherited from superclasses. +// *

+// * +// * @param parent a widget which will be the parent of the new instance (cannot be null) +// * @param style the style of widget to construct +// * +// * @exception IllegalArgumentException +// * @exception SWTException +// * @exception SWTError +// * +// * @see Widget#getStyle +// * +// * @since 3.0 +// */ +//public Browser (Composite parent, int style) { +// super (checkParent (parent), checkStyle (style)); +// userStyle = style; +// +// String platform = SWT.getPlatform (); +// if ("gtk".equals (platform)) { //$NON-NLS-1$ +// parent.getDisplay ().setData (NO_INPUT_METHOD, null); +// } +// +// style = getStyle (); +// webBrowser = new BrowserFactory ().createWebBrowser (style); +// if (webBrowser != null) { +// webBrowser.setBrowser (this); +// webBrowser.create (parent, style); +// return; +// } +// dispose (); +// +// String errMsg = " because there is no underlying browser available.\n"; +// switch (SWT.getPlatform()) { +// case "gtk": +// errMsg = errMsg + "Please ensure that WebKit with its GTK 3.x/4.x bindings is installed."; +// break; +// case "cocoa": +// errMsg = errMsg + "SWT failed to load the WebKit library.\n"; +// break; +// case "win32": +// errMsg = errMsg + "SWT uses either IE or WebKit. Either the SWT.WEBKIT flag is passed and the WebKit library was not " +// + "loaded properly by SWT, or SWT failed to load IE.\n"; +// break; +// default: +// break; +// } +// SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg); +//} +// +//static Composite checkParent (Composite parent) { +// String platform = SWT.getPlatform (); +// if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$ +// +// /* +// * Note. Mozilla provides all IM support needed for text input in web pages. +// * If SWT creates another input method context for the widget it will cause +// * indeterminate results to happen (hangs and crashes). The fix is to prevent +// * SWT from creating an input method context for the Browser widget. +// */ +// if (parent != null && !parent.isDisposed ()) { +// Display display = parent.getDisplay (); +// if (display != null) { +// if (display.getThread () == Thread.currentThread ()) { +// display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$ +// } +// } +// } +// return parent; +//} +// +//static int checkStyle(int style) { +// String platform = SWT.getPlatform (); +// if (DefaultType == SWT.DEFAULT) { +// /* +// * Some Browser clients that explicitly specify the native renderer to use (by +// * creating a Browser with SWT.WEBKIT) may also need to specify that all +// * "default" Browser instances (those created with style SWT.NONE) should use +// * this renderer as well. This may be needed in order to avoid incompatibilities +// * that can arise from having multiple native renderers loaded within the same +// * process. A client can do this by setting the +// * "org.eclipse.swt.browser.DefaultType" java system property to a value like +// * "ie" or "webkit". +// */ +// +// /* +// * Plug-ins need an opportunity to set the org.eclipse.swt.browser.DefaultType +// * system property before the first Browser is created. To facilitate this, +// * reflection is used to reference non-existent class +// * org.eclipse.swt.browser.BrowserInitializer the first time a Browser is created. +// * A client wishing to use this hook can do so by creating a fragment of +// * org.eclipse.swt that implements this class and sets the system property in its +// * static initializer. +// */ +// try { +// Class.forName ("org.eclipse.swt.browser.BrowserInitializer"); //$NON-NLS-1$ +// } catch (ClassNotFoundException e) { +// /* no fragment is providing this class, which is the typical case */ +// } +// +// String value = System.getProperty (PROPERTY_DEFAULTTYPE); +// if (value != null) { +// int index = 0; +// int length = value.length(); +// do { +// int newIndex = value.indexOf(',', index); +// if (newIndex == -1) { +// newIndex = length; +// } +// String current = value.substring(index, newIndex).trim(); +// if (current.equalsIgnoreCase ("webkit")) { //$NON-NLS-1$ +// DefaultType = SWT.WEBKIT; +// break; +// } else if (current.equalsIgnoreCase ("edge") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$ +// DefaultType = SWT.EDGE; +// } else if (current.equalsIgnoreCase ("ie") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$ +// DefaultType = SWT.NONE; +// break; +// } +// index = newIndex + 1; +// } while (index < length); +// } +// if (DefaultType == SWT.DEFAULT) { +// DefaultType = SWT.NONE; +// } +// } +// /* If particular backend isn't specified, use the value from the system property. */ +// if ((style & (SWT.WEBKIT | SWT.EDGE)) == 0) { +// style |= DefaultType; +// } +// if ("win32".equals (platform) && (style & SWT.EDGE) != 0) { //$NON-NLS-1$ +// /* Hack to enable Browser to receive focus. */ +// style |= SWT.EMBEDDED; +// } +// return style; +//} +// +//@Override +//protected void checkWidget () { +// super.checkWidget (); +//} +// +///** +// * Clears all session cookies from all current Browser instances. +// * +// * @since 3.2 +// */ +//public static void clearSessions () { +// WebBrowser.clearSessions (); +//} +// +///** +// * Returns the value of a cookie that is associated with a URL. +// * Note that cookies are shared amongst all Browser instances. +// * +// * @param name the cookie name +// * @param url the URL that the cookie is associated with +// * @return the cookie value, or null if no such cookie exists +// * +// * @exception IllegalArgumentException +// * +// * @since 3.5 +// */ +//public static String getCookie (String name, String url) { +// if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return WebBrowser.GetCookie (name, url); +//} +// +///** +// * Sets a cookie on a URL. Note that cookies are shared amongst all Browser instances. +// * +// * The value parameter must be a cookie header string that +// * complies with RFC 2109. +// * The value is passed through to the native browser unchanged. +// *

+// * Example value strings: +// * foo=bar (basic session cookie) +// * foo=bar; path=/; domain=.eclipse.org (session cookie) +// * foo=bar; expires=Tue, 01-Jan-2030 00:00:01 GMT (persistent cookie) +// * foo=; expires=Thu, 01-Jan-1970 00:00:01 GMT (deletes cookie foo) +// * +// * @param value the cookie value +// * @param url the URL to associate the cookie with +// * @return true if the cookie was successfully set and false otherwise +// * +// * @exception IllegalArgumentException

+// * +// * @since 3.5 +// */ +//public static boolean setCookie (String value, String url) { +// if (value == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return WebBrowser.SetCookie (value, url, true); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when authentication is required. +// *

+// * This notification occurs when a page requiring authentication is +// * encountered. +// *

+// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.5 +// */ +//public void addAuthenticationListener (AuthenticationListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addAuthenticationListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when the window hosting the receiver should be closed. +// *

+// * This notification occurs when a javascript command such as +// * window.close gets executed by a Browser. +// *

+// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addCloseWindowListener (CloseWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addCloseWindowListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when the current location has changed or is about to change. +// *

+// * This notification typically occurs when the application navigates +// * to a new location with {@link #setUrl(String)} or when the user +// * activates a hyperlink. +// *

+// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addLocationListener (LocationListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addLocationListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when a new window needs to be created. +// *

+// * This notification occurs when a javascript command such as +// * window.open gets executed by a Browser. +// *

+// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addOpenWindowListener (OpenWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addOpenWindowListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when a progress is made during the loading of the current +// * URL or when the loading of the current URL has been completed. +// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addProgressListener (ProgressListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addProgressListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when the status text is changed. +// *

+// * The status text is typically displayed in the status bar of +// * a browser application. +// *

+// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addStatusTextListener (StatusTextListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addStatusTextListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when the title of the current document is available +// * or has changed. +// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addTitleListener (TitleListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addTitleListener (listener); +//} +// +///** +// * Adds the listener to the collection of listeners who will be +// * notified when a window hosting the receiver needs to be displayed +// * or hidden. +// * +// * @param listener the listener which should be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void addVisibilityWindowListener (VisibilityWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.addVisibilityWindowListener (listener); +//} +// +///** +// * Navigate to the previous session history item. +// * +// * @return true if the operation was successful and false otherwise +// * +// * @exception SWTException +// * +// * @see #forward +// * +// * @since 3.0 +// */ +//public boolean back () { +// checkWidget(); +// return webBrowser.back (); +//} +// +//@Override +//protected void checkSubclass () { +// String name = getClass ().getName (); +// int index = name.lastIndexOf ('.'); +// if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) { +// SWT.error (SWT.ERROR_INVALID_SUBCLASS); +// } +//} +// +///** +// * Executes the specified script. +// *

+// * Executes a script containing javascript commands in the context of the current document. +// * If document-defined functions or properties are accessed by the script then this method +// * should not be invoked until the document has finished loading (ProgressListener.completed() +// * gives notification of this). +// * +// * @param script the script with javascript commands +// * +// * @return true if the operation was successful and false otherwise +// * +// * @exception IllegalArgumentException

+// * +// * @exception SWTException +// * +// * @see ProgressListener#completed(ProgressEvent) +// * +// * @since 3.1 +// */ +//public boolean execute (String script) { +// checkWidget(); +// if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return webBrowser.execute (script); +//} +// +///** +// * Attempts to dispose the receiver, but allows the dispose to be vetoed +// * by the user in response to an onbeforeunload listener +// * in the Browser's current page. +// * +// * @return true if the receiver was disposed, and false otherwise +// * +// * @exception SWTException +// * +// * @see #dispose() +// * +// * @since 3.6 +// */ +//public boolean close () { +// checkWidget(); +// if (webBrowser.close ()) { +// isClosing = true; +// dispose (); +// isClosing = false; +// return true; +// } +// return false; +//} +// +///** +// * Returns the result, if any, of executing the specified script. +// *

+// * Evaluates a script containing javascript commands in the context of +// * the current document. If document-defined functions or properties +// * are accessed by the script then this method should not be invoked +// * until the document has finished loading (ProgressListener.completed() +// * gives notification of this). +// *

+// * If the script returns a value with a supported type then a java +// * representation of the value is returned. The supported +// * javascript -> java mappings are: +// *

+// * +// * An SWTException is thrown if the return value has an +// * unsupported type, or if evaluating the script causes a javascript +// * error to be thrown. +// * +// * @param script the script with javascript commands +// * +// * @return the return value, if any, of executing the script +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @see Browser#evaluate(String,boolean) +// * @see ProgressListener#completed(ProgressEvent) +// * +// * @since 3.5 +// */ +//public Object evaluate (String script) throws SWTException { +// checkWidget(); +// return evaluate (script, false); +//} +// +///** +// * Returns the result, if any, of executing the specified script. +// *

+// * Evaluates a script containing javascript commands. +// * When trusted is true script is executed in the context of Chrome +// * with Chrome security privileges. +// * When trusted is false script is executed in the context of the +// * current document with normal privileges. +// *

+// * If document-defined functions or properties are accessed by the script then +// * this method should not be invoked until the document has finished loading +// * (ProgressListener.completed() gives notification of this). +// *

+// * If the script returns a value with a supported type then a java +// * representation of the value is returned. The supported +// * javascript -> java mappings are: +// *

+// * An SWTException is thrown if the return value has an +// * unsupported type, or if evaluating the script causes a javascript +// * error to be thrown. +// * +// * @param script the script with javascript commands +// * @param trusted true or false depending on the security context to be used +// * +// * @return the return value, if any, of executing the script +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @see ProgressListener#completed(ProgressEvent) +// */ +//public Object evaluate (String script, boolean trusted) throws SWTException { +// checkWidget(); +// if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return webBrowser.evaluate (script, trusted); +//} +// +///** +// * Navigate to the next session history item. +// * +// * @return true if the operation was successful and false otherwise +// * +// * @exception SWTException +// * +// * @see #back +// * +// * @since 3.0 +// */ +//public boolean forward () { +// checkWidget(); +// return webBrowser.forward (); +//} +// +///** +// * Returns the type of native browser being used by this instance. +// * Examples: "ie", "webkit" +// * +// * @return the type of the native browser +// * +// * @since 3.5 +// */ +//public String getBrowserType () { +// checkWidget(); +// return webBrowser.getBrowserType (); +//} +// +///** +// * Returns true if javascript will be allowed to run in pages +// * subsequently viewed in the receiver, and false otherwise. +// * Note that this may not reflect the javascript enablement on the currently- +// * viewed page if setJavascriptEnabled() has been invoked during +// * its lifetime. +// * +// * @return the receiver's javascript enabled state +// * +// * @exception SWTException +// * +// * @see #setJavascriptEnabled +// * +// * @since 3.5 +// */ +//public boolean getJavascriptEnabled () { +// checkWidget(); +// return webBrowser.jsEnabledOnNextPage; +//} +// +//@Override +//public int getStyle () { +// /* +// * If SWT.BORDER was specified at creation time then getStyle() should answer +// * it even though it is removed for IE on win32 in checkStyle(). +// */ +// return super.getStyle () | (userStyle & SWT.BORDER); +//} +// +///** +// * Returns a string with HTML that represents the content of the current page. +// * +// * @return HTML representing the current page or an empty String +// * if this is empty.
+// *

Note, the exact return value is platform dependent. +// * For example on Windows, the returned string is the proccessed webpage +// * with javascript executed and missing html tags added. +// * On Linux and OS X, this returns the original HTML before the browser has +// * processed it.

+// * +// * @exception SWTException +// * +// * @since 3.4 +// */ +//public String getText () { +// checkWidget(); +// return webBrowser.getText (); +//} +// +///** +// * Returns the current URL. +// * +// * @return the current URL or an empty String if there is no current URL +// * +// * @exception SWTException +// * +// * @see #setUrl +// * +// * @since 3.0 +// */ +//public String getUrl () { +// checkWidget(); +// return webBrowser.getUrl (); +//} +// +///** +// * Returns the JavaXPCOM nsIWebBrowser for the receiver, or null +// * if it is not available. In order for an nsIWebBrowser to be returned all +// * of the following must be true: +// * +// * @return the receiver's JavaXPCOM nsIWebBrowser or null +// * +// * @since 3.3 +// * @deprecated SWT.MOZILLA is deprecated and XULRunner as a browser renderer is no longer supported. +// */ +//@Deprecated +//public Object getWebBrowser () { +// checkWidget(); +// return webBrowser.getWebBrowser (); +//} +// +///** +// * Returns true if the receiver can navigate to the +// * previous session history item, and false otherwise. +// * +// * @return the receiver's back command enabled state +// * +// * @exception SWTException +// * +// * @see #back +// */ +//public boolean isBackEnabled () { +// checkWidget(); +// return webBrowser.isBackEnabled (); +//} +// +//@Override +//public boolean isFocusControl () { +// checkWidget(); +// if (webBrowser.isFocusControl ()) return true; +// return super.isFocusControl (); +//} +// +///** +// * Returns true if the receiver can navigate to the +// * next session history item, and false otherwise. +// * +// * @return the receiver's forward command enabled state +// * +// * @exception SWTException +// * +// * @see #forward +// */ +//public boolean isForwardEnabled () { +// checkWidget(); +// return webBrowser.isForwardEnabled (); +//} +// +///** +// * Refresh the current page. +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void refresh () { +// checkWidget(); +// webBrowser.refresh (); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when authentication is required. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.5 +// */ +//public void removeAuthenticationListener (AuthenticationListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeAuthenticationListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when the window hosting the receiver should be closed. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeCloseWindowListener (CloseWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeCloseWindowListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when the current location is changed or about to be changed. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeLocationListener (LocationListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeLocationListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when a new window needs to be created. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeOpenWindowListener (OpenWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeOpenWindowListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when a progress is made during the loading of the current +// * URL or when the loading of the current URL has been completed. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeProgressListener (ProgressListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeProgressListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when the status text is changed. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeStatusTextListener (StatusTextListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeStatusTextListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when the title of the current document is available +// * or has changed. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeTitleListener (TitleListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeTitleListener (listener); +//} +// +///** +// * Removes the listener from the collection of listeners who will +// * be notified when a window hosting the receiver needs to be displayed +// * or hidden. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void removeVisibilityWindowListener (VisibilityWindowListener listener) { +// checkWidget(); +// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// webBrowser.removeVisibilityWindowListener (listener); +//} +// +///** +// * Sets whether javascript will be allowed to run in pages subsequently +// * viewed in the receiver. Note that setting this value does not affect +// * the running of javascript in the current page. +// * +// * @param enabled the receiver's new javascript enabled state +// * +// * @exception SWTException +// * +// * @since 3.5 +// */ +//public void setJavascriptEnabled (boolean enabled) { +// checkWidget(); +// webBrowser.jsEnabledOnNextPage = enabled; +//} +// +///** +// * Renders a string containing HTML. The rendering of the content occurs asynchronously. +// * The rendered page will be given trusted permissions; to render the page with untrusted +// * permissions use setText(String html, boolean trusted) instead. +// *

+// * The html parameter is Unicode-encoded since it is a java String. +// * As a result, the HTML meta tag charset should not be set. The charset is implied +// * by the String itself. +// * +// * @param html the HTML content to be rendered +// * +// * @return true if the operation was successful and false otherwise. +// * +// * @exception IllegalArgumentException

+// * +// * @exception SWTException +// * +// * @see #setText(String,boolean) +// * @see #setUrl +// * +// * @since 3.0 +// */ +//public boolean setText (String html) { +// checkWidget(); +// return setText (html, true); +//} +// +///** +// * Renders a string containing HTML. The rendering of the content occurs asynchronously. +// * The rendered page can be given either trusted or untrusted permissions. +// *

+// * The html parameter is Unicode-encoded since it is a java String. +// * As a result, the HTML meta tag charset should not be set. The charset is implied +// * by the String itself. +// *

+// * The trusted parameter affects the permissions that will be granted to the rendered +// * page. Specifying true for trusted gives the page permissions equivalent +// * to a page on the local file system, while specifying false for trusted +// * gives the page permissions equivalent to a page from the internet. Page content should +// * be specified as trusted if the invoker created it or trusts its source, since this would +// * allow (for instance) style sheets on the local file system to be referenced. Page +// * content should be specified as untrusted if its source is not trusted or is not known. +// * +// * @param html the HTML content to be rendered +// * @param trusted false if the rendered page should be granted restricted +// * permissions and true otherwise +// * +// * @return true if the operation was successful and false otherwise. +// * +// * @exception IllegalArgumentException

+// * +// * @exception SWTException +// * +// * @see #setText(String) +// * @see #setUrl +// * +// * @since 3.6 +// */ +//public boolean setText (String html, boolean trusted) { +// checkWidget(); +// if (html == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return webBrowser.setText (html, trusted); +//} +// +///** +// * Begins loading a URL. The loading of its content occurs asynchronously. +// * +// * @param url the URL to be loaded +// * +// * @return true if the operation was successful and false otherwise. +// * +// * @exception IllegalArgumentException +// * +// * @exception SWTException +// * +// * @see #getUrl +// * @see #setUrl(String,String,String[]) +// * +// * @since 3.0 +// */ +//public boolean setUrl (String url) { +// checkWidget(); +// return setUrl (url, null, null); +//} +// +///** +// * Begins loading a URL. The loading of its content occurs asynchronously. +// *

+// * If the URL causes an HTTP request to be initiated then the provided +// * postData and header arguments, if any, are +// * sent with the request. A value in the headers argument +// * must be a name-value pair with a colon separator in order to be sent +// * (for example: "user-agent: custom"). +// * +// * @param url the URL to be loaded +// * @param postData post data to be sent with the request, or null +// * @param headers header lines to be sent with the request, or null +// * +// * @return true if the operation was successful and false otherwise. +// * +// * @exception IllegalArgumentException

+// * +// * @exception SWTException +// * +// * @since 3.6 +// */ +//public boolean setUrl (String url, String postData, String[] headers) { +// checkWidget(); +// if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// return webBrowser.setUrl (url, postData, headers); +//} +// +///** +// * Stop any loading and rendering activity. +// * +// * @exception SWTException +// * +// * @since 3.0 +// */ +//public void stop () { +// checkWidget(); +// webBrowser.stop (); +//} +//} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java new file mode 100644 index 00000000000..f59bdc3c7cc --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java @@ -0,0 +1,844 @@ +/******************************************************************************* + * Copyright (c) 2003, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.browser; + +import java.awt.*; +import java.util.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.internal.swing.*; +import org.eclipse.swt.widgets.*; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; + +/** + * Instances of this class implement the browser user interface + * metaphor. It allows the user to visualize and navigate through + * HTML documents. + *

+ * Note that although this class is a subclass of Composite, + * it does not make sense to set a layout on it. + *

+ * IMPORTANT: This class is not intended to be subclassed. + *

+ * + * @since 3.0 + */ +public class Browser extends Composite { + + /* External Listener management */ + CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0]; + LocationListener[] locationListeners = new LocationListener[0]; + OpenWindowListener[] openWindowListeners = new OpenWindowListener[0]; + ProgressListener[] progressListeners = new ProgressListener[0]; + StatusTextListener[] statusTextListeners = new StatusTextListener[0]; + TitleListener[] titleListeners = new TitleListener[0]; + VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0]; + WebBrowser webBrowser; // TODO (visjee) SWING + + static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ + + /* Package Name */ + static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$ + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

+ * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

+ * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException + * @exception SWTException + * @exception SWTError + * + * @see Widget#getStyle + * + * @since 3.0 + */ +public Browser(Composite parent, int style) { + super(parent, style &~ SWT.BORDER); +} + +/** + * Clears all session cookies from all current Browser instances. + * + * @since 3.2 + */ +public static void clearSessions () { + Utils.notImplemented(); +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when the window hosting the receiver should be closed. + *

+ * This notification occurs when a javascript command such as + * window.close gets executed by a Browser. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addCloseWindowListener(CloseWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1]; + System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length); + closeWindowListeners = newCloseWindowListeners; + closeWindowListeners[closeWindowListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when the current location has changed or is about to change. + *

+ * This notification typically occurs when the application navigates + * to a new location with {@link #setUrl(String)} or when the user + * activates a hyperlink. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addLocationListener(LocationListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1]; + System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length); + locationListeners = newLocationListeners; + locationListeners[locationListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when a new window needs to be created. + *

+ * This notification occurs when a javascript command such as + * window.open gets executed by a Browser. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addOpenWindowListener(OpenWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1]; + System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length); + openWindowListeners = newOpenWindowListeners; + openWindowListeners[openWindowListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when a progress is made during the loading of the current + * URL or when the loading of the current URL has been completed. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addProgressListener(ProgressListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1]; + System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length); + progressListeners = newProgressListeners; + progressListeners[progressListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when the status text is changed. + *

+ * The status text is typically displayed in the status bar of + * a browser application. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addStatusTextListener(StatusTextListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1]; + System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length); + statusTextListeners = newStatusTextListeners; + statusTextListeners[statusTextListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when the title of the current document is available + * or has changed. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addTitleListener(TitleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1]; + System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length); + titleListeners = newTitleListeners; + titleListeners[titleListeners.length - 1] = listener; +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when a window hosting the receiver needs to be displayed + * or hidden. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void addVisibilityWindowListener(VisibilityWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1]; + System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, visibilityWindowListeners.length); + visibilityWindowListeners = newVisibilityWindowListeners; + visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener; +} + +/** + * Navigate to the previous session history item. + * + * @return true if the operation was successful and false otherwise + * + * @exception SWTException + * + * @see #forward + * + * @since 3.0 + */ +public boolean back() { + checkWidget(); + return ((CBrowser)handle).back(); +} + +@Override +protected void checkSubclass() { + String name = getClass().getName(); + int index = name.lastIndexOf('.'); + if (!name.substring(0, index + 1).equals(PACKAGE_PREFIX)) { + SWT.error(SWT.ERROR_INVALID_SUBCLASS); + } +} + +@Override +protected Container createHandle () { + return (Container)CBrowser.Factory.newInstance(this, getStyle()); +} + +/** + * Execute the specified script. + * + *

+ * Execute a script containing javascript commands in the context of the current document. + * + * @param script the script with javascript commands + * + * @return true if the operation was successful and false otherwise + * + * @exception IllegalArgumentException

+ * + * @exception SWTException + * + * @since 3.1 + */ +public boolean execute(String script) { + checkWidget(); + if (script == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + // TODO: impossible to implement. Check in future versions of Java... + return false; +} + +/** + * Navigate to the next session history item. + * + * @return true if the operation was successful and false otherwise + * + * @exception SWTException + * + * @see #back + * + * @since 3.0 + */ +public boolean forward() { + checkWidget(); + return ((CBrowser)handle).forward(); +} + +/** + * Returns true if the receiver can navigate to the + * previous session history item, and false otherwise. + * + * @return the receiver's back command enabled state + * + * @exception SWTException + * + * @see #back + */ +public boolean isBackEnabled() { + checkWidget(); + return ((CBrowser)handle).isBackEnabled(); +} + +/** + * Returns true if the receiver can navigate to the + * next session history item, and false otherwise. + * + * @return the receiver's forward command enabled state + * + * @exception SWTException + * + * @see #forward + */ +public boolean isForwardEnabled() { + checkWidget(); + return ((CBrowser)handle).isForwardEnabled(); +} + +/** + * Returns the current URL. + * + * @return the current URL or an empty String if there is no current URL + * + * @exception SWTException + * + * @see #setUrl + * + * @since 3.0 + */ +public String getUrl() { + checkWidget(); + return ((CBrowser)handle).getURL(); +} + +/** + * Refresh the current page. + * + * @exception SWTException + * + * @since 3.0 + */ +public void refresh() { + checkWidget(); + ((CBrowser)handle).refresh(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the window hosting the receiver should be closed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeCloseWindowListener(CloseWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (closeWindowListeners.length == 0) return; + int index = -1; + for (int i = 0; i < closeWindowListeners.length; i++) { + if (listener == closeWindowListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (closeWindowListeners.length == 1) { + closeWindowListeners = new CloseWindowListener[0]; + return; + } + CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1]; + System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, index); + System.arraycopy(closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length - index - 1); + closeWindowListeners = newCloseWindowListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the current location is changed or about to be changed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeLocationListener(LocationListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (locationListeners.length == 0) return; + int index = -1; + for (int i = 0; i < locationListeners.length; i++) { + if (listener == locationListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (locationListeners.length == 1) { + locationListeners = new LocationListener[0]; + return; + } + LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1]; + System.arraycopy(locationListeners, 0, newLocationListeners, 0, index); + System.arraycopy(locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index - 1); + locationListeners = newLocationListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when a new window needs to be created. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeOpenWindowListener(OpenWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (openWindowListeners.length == 0) return; + int index = -1; + for (int i = 0; i < openWindowListeners.length; i++) { + if (listener == openWindowListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (openWindowListeners.length == 1) { + openWindowListeners = new OpenWindowListener[0]; + return; + } + OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1]; + System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, index); + System.arraycopy(openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length - index - 1); + openWindowListeners = newOpenWindowListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when a progress is made during the loading of the current + * URL or when the loading of the current URL has been completed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeProgressListener(ProgressListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (progressListeners.length == 0) return; + int index = -1; + for (int i = 0; i < progressListeners.length; i++) { + if (listener == progressListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (progressListeners.length == 1) { + progressListeners = new ProgressListener[0]; + return; + } + ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1]; + System.arraycopy(progressListeners, 0, newProgressListeners, 0, index); + System.arraycopy(progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index - 1); + progressListeners = newProgressListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the status text is changed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeStatusTextListener(StatusTextListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (statusTextListeners.length == 0) return; + int index = -1; + for (int i = 0; i < statusTextListeners.length; i++) { + if (listener == statusTextListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (statusTextListeners.length == 1) { + statusTextListeners = new StatusTextListener[0]; + return; + } + StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1]; + System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, index); + System.arraycopy(statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length - index - 1); + statusTextListeners = newStatusTextListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the title of the current document is available + * or has changed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeTitleListener(TitleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (titleListeners.length == 0) return; + int index = -1; + for (int i = 0; i < titleListeners.length; i++) { + if (listener == titleListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (titleListeners.length == 1) { + titleListeners = new TitleListener[0]; + return; + } + TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1]; + System.arraycopy(titleListeners, 0, newTitleListeners, 0, index); + System.arraycopy(titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1); + titleListeners = newTitleListeners; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when a window hosting the receiver needs to be displayed + * or hidden. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @since 3.0 + */ +public void removeVisibilityWindowListener(VisibilityWindowListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (visibilityWindowListeners.length == 0) return; + int index = -1; + for (int i = 0; i < visibilityWindowListeners.length; i++) { + if (listener == visibilityWindowListeners[i]){ + index = i; + break; + } + } + if (index == -1) return; + if (visibilityWindowListeners.length == 1) { + visibilityWindowListeners = new VisibilityWindowListener[0]; + return; + } + VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1]; + System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index); + System.arraycopy(visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index, visibilityWindowListeners.length - index - 1); + visibilityWindowListeners = newVisibilityWindowListeners; +} + +/** + * Renders HTML. + * + *

+ * The html parameter is Unicode encoded since it is a java String. + * As a result, the HTML meta tag charset should not be set. The charset is implied + * by the String itself. + * + * @param html the HTML content to be rendered + * + * @return true if the operation was successful and false otherwise. + * + * @exception IllegalArgumentException

+ * + * @exception SWTException + * + * @see #setUrl + * + * @since 3.0 + */ +public boolean setText(String html) { + checkWidget(); + if (html == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return ((CBrowser)handle).setText(html); +} + +/** + * Loads a URL. + * + * @param url the URL to be loaded + * + * @return true if the operation was successful and false otherwise. + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * @see #getUrl + * + * @since 3.0 + */ +public boolean setUrl(String url) { + checkWidget(); + if (url == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return ((CBrowser)handle).setURL(url); +} + +/** + * Stop any loading and rendering activity. + * + * @exception SWTException + * + * @since 3.0 + */ +public void stop() { + checkWidget(); + ((CBrowser)handle).stop(); +} + +@Override +public void processEvent(EventObject e) { + if(e instanceof BrowserLocationChangingEvent) { +// if(!hooks(SWT.Verify)) { super.processEvent(e); return; } + } else if(e instanceof BrowserLocationChangedEvent) { +// if(!hooks(SWT.Verify)) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof BrowserLocationChangingEvent) { + BrowserLocationChangingEvent browserLocationChangingEvent = (BrowserLocationChangingEvent)e; + LocationEvent newEvent = new LocationEvent(Browser.this); + newEvent.display = getDisplay(); + newEvent.widget = Browser.this; + newEvent.location = browserLocationChangingEvent.getURL(); + newEvent.doit = true; + for (int i = 0; i < locationListeners.length; i++) { + locationListeners[i].changing(newEvent); + } + if(!newEvent.doit) { + browserLocationChangingEvent.consume(); + } + } else if(e instanceof BrowserLocationChangedEvent) { + BrowserLocationChangedEvent browserLocationChangedEvent = (BrowserLocationChangedEvent)e; + LocationEvent newEvent = new LocationEvent(Browser.this); + newEvent.display = getDisplay(); + newEvent.widget = Browser.this; + newEvent.location = browserLocationChangedEvent.getURL(); + for (int i = 0; i < locationListeners.length; i++) { + locationListeners[i].changed(newEvent); + } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public boolean traverse(int traversal, Event event) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java index cfae6bb330f..e0eae21d971 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java @@ -828,6 +828,10 @@ void destroyItem (CTabItem item) { notifyItemCountChange(); } +private void requestLayout() { + throw new UnsupportedOperationException("Not implemented yet"); +} + /** * Returns true if the receiver's border is visible. * diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/HTMLWriter.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/HTMLWriter.java index e10873d14b0..c90627131a2 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/HTMLWriter.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/HTMLWriter.java @@ -10,9 +10,6 @@ *******************************************************************************/ package org.eclipse.swt.custom; -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; - /** * The HTMLWriter class is used to write styled content as HTML. * The implementation creates a very-very simple HTML, as compatible @@ -27,326 +24,332 @@ *
  • The {@link StyleRange} properties inside the line are written the {@code } elements.
  • * */ +// TODO (visjee) SWING class HTMLWriter extends StyledTextWriterBase { - private String tag; - private boolean multiline; - - public HTMLWriter(StyledText styledText, int start, int length, StyledTextContent content) { - super(styledText, start, length); - String text = content.getTextRange(start, length); - multiline = text.contains("\n"); - tag = multiline ? "div" : "span"; - writeHeader(); - } - - @Override - public void close() { - if (!isClosed()) { - write(""); - write(""); - super.close(); - } - } - - @Override - void writeHeader() { - StringBuilder outerDivStyle = new StringBuilder(); - StringBuilder innerDivStyle = new StringBuilder(); - - appendStyle(outerDivStyle, "background-color:", styledText.getMarginColor(), ";"); - appendStyle(innerDivStyle, "color:", styledText.getForeground(), ";"); - appendStyle(innerDivStyle, "background-color:", styledText.getBackground(), ";"); - - appendStyle(outerDivStyle, "padding:" - + styledText.getTopMargin() + "px " - + styledText.getRightMargin() + "px " - + styledText.getBottomMargin() + "px " - + styledText.getLeftMargin() + "px;"); - - String language = appendFont(innerDivStyle, styledText.getFont(), 0); - - int indent = styledText.getIndent(); - if (indent != 0) { - appendStyle(innerDivStyle, "text-indent:", indent, "px;"); - } - - if (styledText.getWordWrap()) { - // Sequences of white space are preserved. - // Lines are broken at newline characters, at
    , and as necessary to fill line boxes. - appendStyle(innerDivStyle, "white-space:pre-wrap;"); - } else { - // Sequences of white space are preserved. - // Lines are only broken at newline characters in the source and at
    elements. - appendStyle(innerDivStyle, "white-space:pre;"); - } - - appendAlignAndJustify(innerDivStyle, styledText.getAlignment(), styledText.getJustify()); - - if (styledText.getOrientation() == SWT.RIGHT_TO_LEFT || styledText.getTextDirection() == SWT.RIGHT_TO_LEFT) { - appendStyle(innerDivStyle, "direction:rtl;"); - } - - write("<"+ tag+" style='" + outerDivStyle + "'>"); - if (language == null || language.isEmpty()) { - write("<"+ tag+" style='" + innerDivStyle + "'>"); - } else { - write("<"+ tag+" lang='" + language + "' style='" + innerDivStyle + "'>"); - } - } - - @Override - public void writeLineDelimiter(String lineDelimiter) { - if (isClosed()) { - SWT.error(SWT.ERROR_IO); - } - // We don't write the newline, otherwise it would be rendered because of the `white-space:pre;`. - } - - @Override - String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { - StringBuilder paragraphStyle = new StringBuilder(); - - appendAlignAndJustify(paragraphStyle, alignment, justify); - - appendStyle(paragraphStyle, "background-color:", lineBackground, ";"); - - if (indent != 0) { - appendStyle(paragraphStyle, "text-indent:", indent, "px;"); - } - - if (verticalIndent == 0) { - appendStyle(paragraphStyle, "margin:0;"); - } else { - // Set the margin-top to verticalIndent, everything else zero. - appendStyle(paragraphStyle, "margin:", verticalIndent, " 0 0 0;"); - } - - if (!multiline) { - return ""; - } - if (paragraphStyle.length() == 0) { - write("

    "); - } else { - write("

    "); - } - - // This is what will be used to close the line - return "

    "; - } - - @Override - void writeEmptyLine() { - write("
    "); - } - - @Override - String writeSpanStart(StyleRange style) { - StringBuilder spanStyle = new StringBuilder(); - - appendStyle(spanStyle, "color:", style.foreground, ";"); - appendStyle(spanStyle, "background-color:", style.background, ";"); - - appendFont(spanStyle, style.font, style.fontStyle); - - if (style.rise != 0) { - appendStyle(spanStyle, "position:relative;bottom:", style.rise, "pt;"); - } - - String borderColor = style.borderColor != null ? " " + colorToHex(style.borderColor) : ""; - switch (style.borderStyle) { - case SWT.BORDER: // intentional fall-trough - // In Eclipse the default border is solid - case SWT.BORDER_SOLID: - appendStyle(spanStyle, "border:solid 1pt", borderColor, ";"); - break; - case SWT.BORDER_DASH: - appendStyle(spanStyle, "border:dashed 1pt", borderColor, ";"); - break; - case SWT.BORDER_DOT: - appendStyle(spanStyle, "border:dotted 1pt", borderColor, ";"); - break; - default: - break; - } - - if (style.underline) { - appendStyle(spanStyle, "text-decoration:underline;"); - appendStyle(spanStyle, "text-decoration-color:", style.underlineColor, ";"); - switch (style.underlineStyle) { - case SWT.UNDERLINE_SINGLE: - appendStyle(spanStyle, "text-decoration-style:solid;"); - break; - case SWT.UNDERLINE_DOUBLE: - appendStyle(spanStyle, "text-decoration-style:double;"); - break; - case SWT.UNDERLINE_ERROR: - appendStyle(spanStyle, "text-decoration-style:wavy;"); - break; - case SWT.UNDERLINE_SQUIGGLE: - appendStyle(spanStyle, "text-decoration-style:wavy;"); - break; - case SWT.UNDERLINE_LINK: - appendStyle(spanStyle, "text-decoration-style:solid;"); - if (style.underlineColor == null) { - // If the color of the link underline was not explicitly overridden, then is is blue. - appendStyle(spanStyle, "text-decoration-color:#0066cc;"); - } - if (style.foreground == null) { - // If the color of the link text was not explicitly overridden, then is is blue. - appendStyle(spanStyle, "color:#0066cc;"); - } - break; - default: - break; - } - } - - // Both underline and line-through use text-decoration-color. - // If we want the underline color to be different than the strikeout color we need two spans. - StringBuilder spanStyle2; - if (style.strikeout) { - spanStyle2 = new StringBuilder(); - appendStyle(spanStyle2, "text-decoration:line-through;"); - appendStyle(spanStyle2, "text-decoration-color:", style.strikeoutColor, ";"); - } else { - spanStyle2 = null; - } - - if (spanStyle.length() != 0) { - write(""); - } - if (spanStyle2 != null) { - write(""); - } - - // This is what will be used to close the span - StringBuilder toCloseSpan = new StringBuilder(); - if (spanStyle2 != null) { - toCloseSpan.append(""); - } - if (spanStyle.length() != 0) { - toCloseSpan.append(""); - } - return toCloseSpan.toString(); - } - - // ==== Helper methods ==== - - @Override - String escapeText(String string) { - // The resulting string is at least as long as the original. - StringBuilder result = new StringBuilder(string.length()); - string.chars().forEach(ch -> { - switch (ch) { - case '&': - result.append("&"); - break; - case '"': - result.append("""); - break; - case '<': - result.append("<"); - break; - case '>': - result.append(">"); - break; - default: - result.append((char) ch); - } - }); - return result.toString(); - } - - // TODO: do we also want support for alpha? - private static String colorToHex(Color color) { - if (color == null) { - return null; - } - return String.format("#%02x%02x%02x", - color.getRed(), - color.getGreen(), - color.getBlue()); - } - - private static void appendStyle(StringBuilder buffer, String value) { - buffer.append(value); - } - - private static void appendStyle(StringBuilder buffer, String prefix, String value, String postfix) { - buffer.append(prefix); - buffer.append(value); - buffer.append(postfix); - } - - private static void appendStyle(StringBuilder buffer, String prefix, int value, String postfix) { - buffer.append(prefix); - buffer.append(value); - buffer.append(postfix); - } - - private static void appendStyle(StringBuilder buffer, String prefix, Color value, String postfix) { - if (value != null) { - buffer.append(prefix); - buffer.append(colorToHex(value)); - buffer.append(postfix); - } - } - - // Return a locale id, if one was present in the font - private static String appendFont(StringBuilder buffer, Font font, int fontStyle) { - String language = null; - - if (font != null) { - FontData[] fd = font.getFontData(); - if (fd != null && fd.length > 0) { - FontData fdata = fd[0]; - String name = fdata.getName(); - if (name != null && !name.isEmpty()) { - appendStyle(buffer, "font-family:\"", fdata.getName(), "\";"); - } - appendStyle(buffer, "font-size:", fdata.getHeight(), "pt;"); - language = fdata.getLocale(); - // The style in the font wins. - // Quote from {@link StyleRange#fontStyle}: - // "Note: the font style is not used if the font attribute is set" - fontStyle = fdata.getStyle(); - } - } - - if (fontStyle != 0) { - if ((fontStyle & SWT.ITALIC) == SWT.ITALIC) { - appendStyle(buffer, "font-style:italic;"); - } - if ((fontStyle & SWT.BOLD) == SWT.BOLD) { - appendStyle(buffer, "font-weight:bold;"); - } - } - - return language; - } - private static void appendAlignAndJustify(StringBuilder buffer, int alignment, boolean justify) { - // `text-align` is used for general paragraph alignment, but when it is used for justify - // we need to set `text-align-last` to control the behavior of the last line. - String textAlignKey; - if (justify) { - appendStyle(buffer, "text-align:justify;"); - textAlignKey = "text-align-last:"; - } else { - textAlignKey = "text-align:"; - } - switch (alignment) { - case SWT.LEFT: - // This is the default, no need to write anything out. - break; - case SWT.CENTER: - appendStyle(buffer, textAlignKey, "center", ";"); - break; - case SWT.RIGHT: - appendStyle(buffer, textAlignKey, "right", ";"); - break; - default: - break; - } + public HTMLWriter(int start, int length) { + super(start, length); + // TODO Auto-generated constructor stub } +// private String tag; +// private boolean multiline; +// +// public HTMLWriter(StyledText styledText, int start, int length, StyledTextContent content) { +// super(styledText, start, length); +// String text = content.getTextRange(start, length); +// multiline = text.contains("\n"); +// tag = multiline ? "div" : "span"; +// writeHeader(); +// } +// +// @Override +// public void close() { +// if (!isClosed()) { +// write(""); +// write(""); +// super.close(); +// } +// } +// +// @Override +// void writeHeader() { +// StringBuilder outerDivStyle = new StringBuilder(); +// StringBuilder innerDivStyle = new StringBuilder(); +// +// appendStyle(outerDivStyle, "background-color:", styledText.getMarginColor(), ";"); +// appendStyle(innerDivStyle, "color:", styledText.getForeground(), ";"); +// appendStyle(innerDivStyle, "background-color:", styledText.getBackground(), ";"); +// +// appendStyle(outerDivStyle, "padding:" +// + styledText.getTopMargin() + "px " +// + styledText.getRightMargin() + "px " +// + styledText.getBottomMargin() + "px " +// + styledText.getLeftMargin() + "px;"); +// +// String language = appendFont(innerDivStyle, styledText.getFont(), 0); +// +// int indent = styledText.getIndent(); +// if (indent != 0) { +// appendStyle(innerDivStyle, "text-indent:", indent, "px;"); +// } +// +// if (styledText.getWordWrap()) { +// // Sequences of white space are preserved. +// // Lines are broken at newline characters, at
    , and as necessary to fill line boxes. +// appendStyle(innerDivStyle, "white-space:pre-wrap;"); +// } else { +// // Sequences of white space are preserved. +// // Lines are only broken at newline characters in the source and at
    elements. +// appendStyle(innerDivStyle, "white-space:pre;"); +// } +// +// appendAlignAndJustify(innerDivStyle, styledText.getAlignment(), styledText.getJustify()); +// +// if (styledText.getOrientation() == SWT.RIGHT_TO_LEFT || styledText.getTextDirection() == SWT.RIGHT_TO_LEFT) { +// appendStyle(innerDivStyle, "direction:rtl;"); +// } +// +// write("<"+ tag+" style='" + outerDivStyle + "'>"); +// if (language == null || language.isEmpty()) { +// write("<"+ tag+" style='" + innerDivStyle + "'>"); +// } else { +// write("<"+ tag+" lang='" + language + "' style='" + innerDivStyle + "'>"); +// } +// } +// +// @Override +// public void writeLineDelimiter(String lineDelimiter) { +// if (isClosed()) { +// SWT.error(SWT.ERROR_IO); +// } +// // We don't write the newline, otherwise it would be rendered because of the `white-space:pre;`. +// } +// +// @Override +// String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { +// StringBuilder paragraphStyle = new StringBuilder(); +// +// appendAlignAndJustify(paragraphStyle, alignment, justify); +// +// appendStyle(paragraphStyle, "background-color:", lineBackground, ";"); +// +// if (indent != 0) { +// appendStyle(paragraphStyle, "text-indent:", indent, "px;"); +// } +// +// if (verticalIndent == 0) { +// appendStyle(paragraphStyle, "margin:0;"); +// } else { +// // Set the margin-top to verticalIndent, everything else zero. +// appendStyle(paragraphStyle, "margin:", verticalIndent, " 0 0 0;"); +// } +// +// if (!multiline) { +// return ""; +// } +// if (paragraphStyle.length() == 0) { +// write("

    "); +// } else { +// write("

    "); +// } +// +// // This is what will be used to close the line +// return "

    "; +// } +// +// @Override +// void writeEmptyLine() { +// write("
    "); +// } +// +// @Override +// String writeSpanStart(StyleRange style) { +// StringBuilder spanStyle = new StringBuilder(); +// +// appendStyle(spanStyle, "color:", style.foreground, ";"); +// appendStyle(spanStyle, "background-color:", style.background, ";"); +// +// appendFont(spanStyle, style.font, style.fontStyle); +// +// if (style.rise != 0) { +// appendStyle(spanStyle, "position:relative;bottom:", style.rise, "pt;"); +// } +// +// String borderColor = style.borderColor != null ? " " + colorToHex(style.borderColor) : ""; +// switch (style.borderStyle) { +// case SWT.BORDER: // intentional fall-trough +// // In Eclipse the default border is solid +// case SWT.BORDER_SOLID: +// appendStyle(spanStyle, "border:solid 1pt", borderColor, ";"); +// break; +// case SWT.BORDER_DASH: +// appendStyle(spanStyle, "border:dashed 1pt", borderColor, ";"); +// break; +// case SWT.BORDER_DOT: +// appendStyle(spanStyle, "border:dotted 1pt", borderColor, ";"); +// break; +// default: +// break; +// } +// +// if (style.underline) { +// appendStyle(spanStyle, "text-decoration:underline;"); +// appendStyle(spanStyle, "text-decoration-color:", style.underlineColor, ";"); +// switch (style.underlineStyle) { +// case SWT.UNDERLINE_SINGLE: +// appendStyle(spanStyle, "text-decoration-style:solid;"); +// break; +// case SWT.UNDERLINE_DOUBLE: +// appendStyle(spanStyle, "text-decoration-style:double;"); +// break; +// case SWT.UNDERLINE_ERROR: +// appendStyle(spanStyle, "text-decoration-style:wavy;"); +// break; +// case SWT.UNDERLINE_SQUIGGLE: +// appendStyle(spanStyle, "text-decoration-style:wavy;"); +// break; +// case SWT.UNDERLINE_LINK: +// appendStyle(spanStyle, "text-decoration-style:solid;"); +// if (style.underlineColor == null) { +// // If the color of the link underline was not explicitly overridden, then is is blue. +// appendStyle(spanStyle, "text-decoration-color:#0066cc;"); +// } +// if (style.foreground == null) { +// // If the color of the link text was not explicitly overridden, then is is blue. +// appendStyle(spanStyle, "color:#0066cc;"); +// } +// break; +// default: +// break; +// } +// } +// +// // Both underline and line-through use text-decoration-color. +// // If we want the underline color to be different than the strikeout color we need two spans. +// StringBuilder spanStyle2; +// if (style.strikeout) { +// spanStyle2 = new StringBuilder(); +// appendStyle(spanStyle2, "text-decoration:line-through;"); +// appendStyle(spanStyle2, "text-decoration-color:", style.strikeoutColor, ";"); +// } else { +// spanStyle2 = null; +// } +// +// if (spanStyle.length() != 0) { +// write(""); +// } +// if (spanStyle2 != null) { +// write(""); +// } +// +// // This is what will be used to close the span +// StringBuilder toCloseSpan = new StringBuilder(); +// if (spanStyle2 != null) { +// toCloseSpan.append(""); +// } +// if (spanStyle.length() != 0) { +// toCloseSpan.append(""); +// } +// return toCloseSpan.toString(); +// } +// +// // ==== Helper methods ==== +// +// @Override +// String escapeText(String string) { +// // The resulting string is at least as long as the original. +// StringBuilder result = new StringBuilder(string.length()); +// string.chars().forEach(ch -> { +// switch (ch) { +// case '&': +// result.append("&"); +// break; +// case '"': +// result.append("""); +// break; +// case '<': +// result.append("<"); +// break; +// case '>': +// result.append(">"); +// break; +// default: +// result.append((char) ch); +// } +// }); +// return result.toString(); +// } +// +// // TODO: do we also want support for alpha? +// private static String colorToHex(Color color) { +// if (color == null) { +// return null; +// } +// return String.format("#%02x%02x%02x", +// color.getRed(), +// color.getGreen(), +// color.getBlue()); +// } +// +// private static void appendStyle(StringBuilder buffer, String value) { +// buffer.append(value); +// } +// +// private static void appendStyle(StringBuilder buffer, String prefix, String value, String postfix) { +// buffer.append(prefix); +// buffer.append(value); +// buffer.append(postfix); +// } +// +// private static void appendStyle(StringBuilder buffer, String prefix, int value, String postfix) { +// buffer.append(prefix); +// buffer.append(value); +// buffer.append(postfix); +// } +// +// private static void appendStyle(StringBuilder buffer, String prefix, Color value, String postfix) { +// if (value != null) { +// buffer.append(prefix); +// buffer.append(colorToHex(value)); +// buffer.append(postfix); +// } +// } +// +// // Return a locale id, if one was present in the font +// private static String appendFont(StringBuilder buffer, Font font, int fontStyle) { +// String language = null; +// +// if (font != null) { +// FontData[] fd = font.getFontData(); +// if (fd != null && fd.length > 0) { +// FontData fdata = fd[0]; +// String name = fdata.getName(); +// if (name != null && !name.isEmpty()) { +// appendStyle(buffer, "font-family:\"", fdata.getName(), "\";"); +// } +// appendStyle(buffer, "font-size:", fdata.getHeight(), "pt;"); +// language = fdata.getLocale(); +// // The style in the font wins. +// // Quote from {@link StyleRange#fontStyle}: +// // "Note: the font style is not used if the font attribute is set" +// fontStyle = fdata.getStyle(); +// } +// } +// +// if (fontStyle != 0) { +// if ((fontStyle & SWT.ITALIC) == SWT.ITALIC) { +// appendStyle(buffer, "font-style:italic;"); +// } +// if ((fontStyle & SWT.BOLD) == SWT.BOLD) { +// appendStyle(buffer, "font-weight:bold;"); +// } +// } +// +// return language; +// } +// +// private static void appendAlignAndJustify(StringBuilder buffer, int alignment, boolean justify) { +// // `text-align` is used for general paragraph alignment, but when it is used for justify +// // we need to set `text-align-last` to control the behavior of the last line. +// String textAlignKey; +// if (justify) { +// appendStyle(buffer, "text-align:justify;"); +// textAlignKey = "text-align-last:"; +// } else { +// textAlignKey = "text-align:"; +// } +// switch (alignment) { +// case SWT.LEFT: +// // This is the default, no need to write anything out. +// break; +// case SWT.CENTER: +// appendStyle(buffer, textAlignKey, "center", ";"); +// break; +// case SWT.RIGHT: +// appendStyle(buffer, textAlignKey, "right", ";"); +// break; +// default: +// break; +// } +// } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/IME.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/IME.java new file mode 100644 index 00000000000..743a9616802 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/IME.java @@ -0,0 +1,22 @@ +package org.eclipse.swt.custom; + +//TODO implement +public class IME { + + public int getCommitCount() { + throw new UnsupportedOperationException("Not implemented yet"); + } + + public int getCompositionOffset() { + throw new UnsupportedOperationException("Not implemented yet"); + } + + public boolean getWideCaret() { + throw new UnsupportedOperationException("Not implemented yet"); + } + + public int getCaretOffset() { + throw new UnsupportedOperationException("Not implemented yet"); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/MouseNavigator.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/MouseNavigator.java index 06dd7c56715..1d4c93ac424 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/MouseNavigator.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/MouseNavigator.java @@ -13,10 +13,6 @@ */ package org.eclipse.swt.custom; -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; -import org.eclipse.swt.widgets.*; - /** * This class add the following behaviour to StyledText widgets: *

    @@ -26,271 +22,272 @@ * * @since 3.110 */ +// TODO (visjee) SWING class MouseNavigator { - private final StyledText parent; - boolean navigationActivated = false; - private GC gc; - private static final int CIRCLE_RADIUS = 15; - private static final int CENTRAL_POINT_RADIUS = 2; - private Point originalMouseLocation; - private final Listener mouseDownListener, mouseUpListener, paintListener, mouseMoveListener, focusOutListener; - private boolean hasHBar, hasVBar; - private Cursor previousCursor; - - MouseNavigator(final StyledText styledText) { - if (styledText == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (styledText.isDisposed()) { - SWT.error(SWT.ERROR_WIDGET_DISPOSED); - } - parent = styledText; - - mouseDownListener = event -> { - onMouseDown(event); - }; - parent.addListener(SWT.MouseDown, mouseDownListener); - - mouseUpListener = event -> { - onMouseUp(event); - }; - parent.addListener(SWT.MouseUp, mouseUpListener); - - paintListener = event -> { - onPaint(event); - }; - parent.addListener(SWT.Paint, paintListener); - - mouseMoveListener = event -> { - onMouseMove(event); - }; - parent.addListener(SWT.MouseMove, mouseMoveListener); - - focusOutListener = event -> { - onFocusOut(event); - }; - parent.addListener(SWT.FocusOut, focusOutListener); - } - - void onMouseDown(Event e) { - if ((e.button != 2) || navigationActivated) { - return; - } - - if (!parent.isVisible() || !parent.getEnabled() || parent.middleClickPressed) { - return; - } - - // Widget has no bar or bars are not enabled - initBarState(); - - if (!hasHBar && !hasVBar) { - return; - } - - navigationActivated = true; - previousCursor = parent.getCursor(); - parent.setCursor(parent.getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); - originalMouseLocation = getMouseLocation(); - parent.redraw(); - } - - private void initBarState() { - hasHBar = computeHasHorizontalBar(); - hasVBar = computeHasVerticalBar(); - } - - private boolean computeHasHorizontalBar() { - final ScrollBar horizontalBar = parent.getHorizontalBar(); - final boolean hasHorizontalBar = horizontalBar != null && horizontalBar.isVisible(); - final boolean exceedHorizontalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).x > parent.getSize().x; - return hasHorizontalBar && exceedHorizontalSpace; - } - - private boolean computeHasVerticalBar() { - final ScrollBar verticalBar = parent.getVerticalBar(); - final boolean hasVerticalBar = verticalBar != null && verticalBar.isEnabled(); - final boolean exceedVerticalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).y > parent.getSize().y; - return hasVerticalBar && exceedVerticalSpace; - } - - private void onMouseUp(Event e) { - if ((computeDist() < CIRCLE_RADIUS) && (computeDist() >= 0)) { - return; - } - deactivate(); - } - - public int computeDist() { - if (originalMouseLocation == null) { - return -1; - } - final Point mouseLocation = getMouseLocation(); - final int deltaX = originalMouseLocation.x - mouseLocation.x; - final int deltaY = originalMouseLocation.y - mouseLocation.y; - final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY); - return dist; - } - - private void deactivate() { - parent.setCursor(previousCursor); - navigationActivated = false; - originalMouseLocation = null; - parent.redraw(); - } - - private void onFocusOut(Event e) { - deactivate(); - } - - private void onMouseMove(Event e) { - if (!navigationActivated) { - return; - } - - final Point mouseLocation = getMouseLocation(); - final int deltaX = originalMouseLocation.x - mouseLocation.x; - final int deltaY = originalMouseLocation.y - mouseLocation.y; - final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY); - if (dist < CIRCLE_RADIUS) { - return; - } - - parent.setRedraw(false); - if (hasHBar) { - final ScrollBar bar = parent.getHorizontalBar(); - bar.setSelection((int) (bar.getSelection() - deltaX * .1)); - fireSelectionEvent(e, bar); - } - - if (hasVBar) { - final ScrollBar bar = parent.getVerticalBar(); - bar.setSelection((int) (bar.getSelection() - deltaY * .1)); - fireSelectionEvent(e, bar); - } - parent.setRedraw(true); - parent.redraw(); - } - - private void fireSelectionEvent(final Event e, final ScrollBar bar) { - final Event event = new Event(); - event.widget = bar; - event.display = parent.getDisplay(); - event.type = SWT.Selection; - event.time = e.time; - - for (final Listener selectionListener : bar.getListeners(SWT.Selection)) { - selectionListener.handleEvent(event); - } - } - - private Point getMouseLocation() { - final Point cursorLocation = Display.getCurrent().getCursorLocation(); - final Point relativeCursorLocation = parent.toControl(cursorLocation); - return relativeCursorLocation; - } - - private void onPaint(final Event e) { - if (!navigationActivated) { - return; - } - - final Rectangle rect = parent.getClientArea(); - if (rect.width == 0 || rect.height == 0) { - return; - } - gc = e.gc; - gc.setAntialias(SWT.ON); - gc.setAdvanced(true); - - final Color oldForegroundColor = gc.getForeground(); - final Color oldBackgroundColor = gc.getBackground(); - gc.setBackground(parent.getForeground()); - - drawCircle(); - drawCentralPoint(); - - drawArrows(); - - gc.setForeground(oldForegroundColor); - gc.setBackground(oldBackgroundColor); - } - - private void drawCircle() { - gc.setBackground(parent.getBackground()); - gc.setForeground(parent.getForeground()); - gc.setAlpha(200); - gc.fillOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2); - gc.setBackground(parent.getForeground()); - gc.setAlpha(255); - gc.drawOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2); - } - - private void drawCentralPoint() { - gc.fillOval(originalMouseLocation.x - CENTRAL_POINT_RADIUS, originalMouseLocation.y - CENTRAL_POINT_RADIUS, CENTRAL_POINT_RADIUS * 2, CENTRAL_POINT_RADIUS * 2); - } - - private void drawArrows() { - gc.setLineWidth(2); - if (hasHBar) { - drawHorizontalArrows(); - } - if (hasVBar) { - drawVerticalArrows(); - } - } - - private void drawHorizontalArrows() { - final int[] points = new int[6]; - // Left - points[0] = originalMouseLocation.x - 6; - points[1] = originalMouseLocation.y + 3; - points[2] = originalMouseLocation.x - 9; - points[3] = originalMouseLocation.y; - points[4] = originalMouseLocation.x - 6; - points[5] = originalMouseLocation.y - 3; - gc.drawPolyline(points); - - // Right - points[0] = originalMouseLocation.x + 7; - points[1] = originalMouseLocation.y + 3; - points[2] = originalMouseLocation.x + 10; - points[3] = originalMouseLocation.y; - points[4] = originalMouseLocation.x + 7; - points[5] = originalMouseLocation.y - 3; - gc.drawPolyline(points); - } - - private void drawVerticalArrows() { - final int[] points = new int[6]; - // Upper - points[0] = originalMouseLocation.x - 3; - points[1] = originalMouseLocation.y - 6; - points[2] = originalMouseLocation.x; - points[3] = originalMouseLocation.y - 10; - points[4] = originalMouseLocation.x + 3; - points[5] = originalMouseLocation.y - 6; - gc.drawPolyline(points); - - // Lower - points[0] = originalMouseLocation.x - 3; - points[1] = originalMouseLocation.y + 7; - points[2] = originalMouseLocation.x; - points[3] = originalMouseLocation.y + 11; - points[4] = originalMouseLocation.x + 3; - points[5] = originalMouseLocation.y + 7; - gc.drawPolyline(points); - - } - - void dispose() { - if (parent.isDisposed()) { - return; - } - parent.removeListener(SWT.MouseDown, mouseDownListener); - parent.removeListener(SWT.MouseUp, mouseUpListener); - parent.removeListener(SWT.Paint, paintListener); - parent.removeListener(SWT.MouseMove, mouseMoveListener); - parent.removeListener(SWT.MouseExit, focusOutListener); - } +// private final StyledText parent; +// boolean navigationActivated = false; +// private GC gc; +// private static final int CIRCLE_RADIUS = 15; +// private static final int CENTRAL_POINT_RADIUS = 2; +// private Point originalMouseLocation; +// private final Listener mouseDownListener, mouseUpListener, paintListener, mouseMoveListener, focusOutListener; +// private boolean hasHBar, hasVBar; +// private Cursor previousCursor; +// +// MouseNavigator(final StyledText styledText) { +// if (styledText == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// if (styledText.isDisposed()) { +// SWT.error(SWT.ERROR_WIDGET_DISPOSED); +// } +// parent = styledText; +// +// mouseDownListener = event -> { +// onMouseDown(event); +// }; +// parent.addListener(SWT.MouseDown, mouseDownListener); +// +// mouseUpListener = event -> { +// onMouseUp(event); +// }; +// parent.addListener(SWT.MouseUp, mouseUpListener); +// +// paintListener = event -> { +// onPaint(event); +// }; +// parent.addListener(SWT.Paint, paintListener); +// +// mouseMoveListener = event -> { +// onMouseMove(event); +// }; +// parent.addListener(SWT.MouseMove, mouseMoveListener); +// +// focusOutListener = event -> { +// onFocusOut(event); +// }; +// parent.addListener(SWT.FocusOut, focusOutListener); +// } +// +// void onMouseDown(Event e) { +// if ((e.button != 2) || navigationActivated) { +// return; +// } +// +// if (!parent.isVisible() || !parent.getEnabled() || parent.middleClickPressed) { +// return; +// } +// +// // Widget has no bar or bars are not enabled +// initBarState(); +// +// if (!hasHBar && !hasVBar) { +// return; +// } +// +// navigationActivated = true; +// previousCursor = parent.getCursor(); +// parent.setCursor(parent.getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); +// originalMouseLocation = getMouseLocation(); +// parent.redraw(); +// } +// +// private void initBarState() { +// hasHBar = computeHasHorizontalBar(); +// hasVBar = computeHasVerticalBar(); +// } +// +// private boolean computeHasHorizontalBar() { +// final ScrollBar horizontalBar = parent.getHorizontalBar(); +// final boolean hasHorizontalBar = horizontalBar != null && horizontalBar.isVisible(); +// final boolean exceedHorizontalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).x > parent.getSize().x; +// return hasHorizontalBar && exceedHorizontalSpace; +// } +// +// private boolean computeHasVerticalBar() { +// final ScrollBar verticalBar = parent.getVerticalBar(); +// final boolean hasVerticalBar = verticalBar != null && verticalBar.isEnabled(); +// final boolean exceedVerticalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).y > parent.getSize().y; +// return hasVerticalBar && exceedVerticalSpace; +// } +// +// private void onMouseUp(Event e) { +// if ((computeDist() < CIRCLE_RADIUS) && (computeDist() >= 0)) { +// return; +// } +// deactivate(); +// } +// +// public int computeDist() { +// if (originalMouseLocation == null) { +// return -1; +// } +// final Point mouseLocation = getMouseLocation(); +// final int deltaX = originalMouseLocation.x - mouseLocation.x; +// final int deltaY = originalMouseLocation.y - mouseLocation.y; +// final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY); +// return dist; +// } +// +// private void deactivate() { +// parent.setCursor(previousCursor); +// navigationActivated = false; +// originalMouseLocation = null; +// parent.redraw(); +// } +// +// private void onFocusOut(Event e) { +// deactivate(); +// } +// +// private void onMouseMove(Event e) { +// if (!navigationActivated) { +// return; +// } +// +// final Point mouseLocation = getMouseLocation(); +// final int deltaX = originalMouseLocation.x - mouseLocation.x; +// final int deltaY = originalMouseLocation.y - mouseLocation.y; +// final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY); +// if (dist < CIRCLE_RADIUS) { +// return; +// } +// +// parent.setRedraw(false); +// if (hasHBar) { +// final ScrollBar bar = parent.getHorizontalBar(); +// bar.setSelection((int) (bar.getSelection() - deltaX * .1)); +// fireSelectionEvent(e, bar); +// } +// +// if (hasVBar) { +// final ScrollBar bar = parent.getVerticalBar(); +// bar.setSelection((int) (bar.getSelection() - deltaY * .1)); +// fireSelectionEvent(e, bar); +// } +// parent.setRedraw(true); +// parent.redraw(); +// } +// +// private void fireSelectionEvent(final Event e, final ScrollBar bar) { +// final Event event = new Event(); +// event.widget = bar; +// event.display = parent.getDisplay(); +// event.type = SWT.Selection; +// event.time = e.time; +// +// for (final Listener selectionListener : bar.getListeners(SWT.Selection)) { +// selectionListener.handleEvent(event); +// } +// } +// +// private Point getMouseLocation() { +// final Point cursorLocation = Display.getCurrent().getCursorLocation(); +// final Point relativeCursorLocation = parent.toControl(cursorLocation); +// return relativeCursorLocation; +// } +// +// private void onPaint(final Event e) { +// if (!navigationActivated) { +// return; +// } +// +// final Rectangle rect = parent.getClientArea(); +// if (rect.width == 0 || rect.height == 0) { +// return; +// } +// gc = e.gc; +// gc.setAntialias(SWT.ON); +// gc.setAdvanced(true); +// +// final Color oldForegroundColor = gc.getForeground(); +// final Color oldBackgroundColor = gc.getBackground(); +// gc.setBackground(parent.getForeground()); +// +// drawCircle(); +// drawCentralPoint(); +// +// drawArrows(); +// +// gc.setForeground(oldForegroundColor); +// gc.setBackground(oldBackgroundColor); +// } +// +// private void drawCircle() { +// gc.setBackground(parent.getBackground()); +// gc.setForeground(parent.getForeground()); +// gc.setAlpha(200); +// gc.fillOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2); +// gc.setBackground(parent.getForeground()); +// gc.setAlpha(255); +// gc.drawOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2); +// } +// +// private void drawCentralPoint() { +// gc.fillOval(originalMouseLocation.x - CENTRAL_POINT_RADIUS, originalMouseLocation.y - CENTRAL_POINT_RADIUS, CENTRAL_POINT_RADIUS * 2, CENTRAL_POINT_RADIUS * 2); +// } +// +// private void drawArrows() { +// gc.setLineWidth(2); +// if (hasHBar) { +// drawHorizontalArrows(); +// } +// if (hasVBar) { +// drawVerticalArrows(); +// } +// } +// +// private void drawHorizontalArrows() { +// final int[] points = new int[6]; +// // Left +// points[0] = originalMouseLocation.x - 6; +// points[1] = originalMouseLocation.y + 3; +// points[2] = originalMouseLocation.x - 9; +// points[3] = originalMouseLocation.y; +// points[4] = originalMouseLocation.x - 6; +// points[5] = originalMouseLocation.y - 3; +// gc.drawPolyline(points); +// +// // Right +// points[0] = originalMouseLocation.x + 7; +// points[1] = originalMouseLocation.y + 3; +// points[2] = originalMouseLocation.x + 10; +// points[3] = originalMouseLocation.y; +// points[4] = originalMouseLocation.x + 7; +// points[5] = originalMouseLocation.y - 3; +// gc.drawPolyline(points); +// } +// +// private void drawVerticalArrows() { +// final int[] points = new int[6]; +// // Upper +// points[0] = originalMouseLocation.x - 3; +// points[1] = originalMouseLocation.y - 6; +// points[2] = originalMouseLocation.x; +// points[3] = originalMouseLocation.y - 10; +// points[4] = originalMouseLocation.x + 3; +// points[5] = originalMouseLocation.y - 6; +// gc.drawPolyline(points); +// +// // Lower +// points[0] = originalMouseLocation.x - 3; +// points[1] = originalMouseLocation.y + 7; +// points[2] = originalMouseLocation.x; +// points[3] = originalMouseLocation.y + 11; +// points[4] = originalMouseLocation.x + 3; +// points[5] = originalMouseLocation.y + 7; +// gc.drawPolyline(points); +// +// } +// +// void dispose() { +// if (parent.isDisposed()) { +// return; +// } +// parent.removeListener(SWT.MouseDown, mouseDownListener); +// parent.removeListener(SWT.MouseUp, mouseUpListener); +// parent.removeListener(SWT.Paint, paintListener); +// parent.removeListener(SWT.MouseMove, mouseMoveListener); +// parent.removeListener(SWT.MouseExit, focusOutListener); +// } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/RTFWriter.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/RTFWriter.java index 957195eae56..d2a3abb1357 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/RTFWriter.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/RTFWriter.java @@ -13,11 +13,6 @@ *******************************************************************************/ package org.eclipse.swt.custom; -import java.util.*; - -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; - /** * The {@code RTFWriter} class is used to write styled content as rich text. * The implementation complies with the RTF specification version 1.5. @@ -31,221 +26,227 @@ * the stream like they are rendered by the widget. In addition, the * widget font name and size is used for the whole text.

    */ +// TODO (visjee) SWING class RTFWriter extends StyledTextWriterBase { - static final int DEFAULT_FOREGROUND = 0; - static final int DEFAULT_BACKGROUND = 1; - List colorTable; - List fontTable; - - public RTFWriter(StyledText styledText, int start, int length) { - super(styledText, start, length); - colorTable = new ArrayList<>(); - fontTable = new ArrayList<>(); - colorTable.add(this.styledText.getForeground()); - colorTable.add(this.styledText.getBackground()); - fontTable.add(this.styledText.getFont()); - } - - @Override - public void close() { - if (!isClosed()) { - writeHeader(); - write("\n}}\0"); - super.close(); - } - } - - /** - * Writes the RTF header including font table and color table. - */ - @Override - void writeHeader() { - StringBuilder header = new StringBuilder(); - FontData fontData = styledText.getFont().getFontData()[0]; - header.append("{\\rtf1\\ansi"); - // specify code page, necessary for copy to work in bidi - // systems that don't support Unicode RTF. - String cpg = System.getProperty("file.encoding").toLowerCase(); - if (cpg.startsWith("cp") || cpg.startsWith("ms")) { - cpg = cpg.substring(2, cpg.length()); - header.append("\\ansicpg"); - header.append(cpg); - } - header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil "); - header.append(fontData.getName()); - header.append(";"); - for (int i = 1; i < fontTable.size(); i++) { - header.append("\\f"); - header.append(i); - header.append(" "); - FontData fd = fontTable.get(i).getFontData()[0]; - header.append(fd.getName()); - header.append(";"); - } - header.append("}}\n{\\colortbl"); - for (Color color : colorTable) { - header.append("\\red"); - header.append(color.getRed()); - header.append("\\green"); - header.append(color.getGreen()); - header.append("\\blue"); - header.append(color.getBlue()); - header.append(";"); - } - // some RTF readers ignore the deff0 font tag. Explicitly - // set the font for the whole document to work around this. - header.append("}\n{\\f0\\fs"); - // font size is specified in half points - header.append(fontData.getHeight() * 2); - header.append(" "); - write(header.toString(), 0); - } - - @Override - public void writeLineDelimiter(String lineDelimiter) { - if (isClosed()) { - SWT.error(SWT.ERROR_IO); - } - write(lineDelimiter); - write("\\par "); - } - - @Override - String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { - write("\\fi"); - write(indent); - switch (alignment) { - case SWT.LEFT: write("\\ql"); break; - case SWT.CENTER: write("\\qc"); break; - case SWT.RIGHT: write("\\qr"); break; - } - if (justify) { - write("\\qj"); - } - write(" "); - - if (lineBackground != null) { - // Background colors are written using the {@code \chshdng0\chcbpat} tag (vs. the {@code \cb} tag). - write("{\\chshdng0\\chcbpat"); - write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); - write(" "); - } - - // This is what will be used to close the line - return lineBackground == null ? "" : "}"; - } - - @Override - void writeEmptyLine() { - // Do nothing. RTF does not need special treatment for empty paragraph. - } - - @Override - String writeSpanStart(StyleRange style) { - write("{\\cf"); - write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); - int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); - if (colorIndex != DEFAULT_BACKGROUND) { - write("\\chshdng0\\chcbpat"); - write(colorIndex); - } - int fontStyle = style.fontStyle; - Font font = style.font; - if (font != null) { - int fontIndex = getFontIndex(font); - write("\\f"); - write(fontIndex); - FontData fontData = font.getFontData()[0]; - write("\\fs"); - write(fontData.getHeight() * 2); - fontStyle = fontData.getStyle(); - } - if ((fontStyle & SWT.BOLD) != 0) { - write("\\b"); - } - if ((fontStyle & SWT.ITALIC) != 0) { - write("\\i"); - } - if (style.underline) { - write("\\ul"); - } - if (style.strikeout) { - write("\\strike"); - } - write(" "); - - // This is what will be used to close the span - StringBuilder toCloseSpan = new StringBuilder(); - if ((fontStyle & SWT.BOLD) != 0) { - toCloseSpan.append("\\b0"); - } - if ((style.fontStyle & SWT.ITALIC) != 0) { - toCloseSpan.append("\\i0"); - } - if (style.underline) { - toCloseSpan.append("\\ul0"); - } - if (style.strikeout) { - toCloseSpan.append("\\strike0"); - } - toCloseSpan.append("}"); - return toCloseSpan.toString(); - } - - // ==== Helper methods ==== - - @Override - String escapeText(String string) { - // The resulting string is at least as long as the original. - StringBuilder result = new StringBuilder(string.length()); - string.chars().forEach(ch -> { - if (ch > 0x7F) { - result.append("\\u"); - result.append(Integer.toString((short) ch)); - result.append('?'); // ANSI representation (1 byte long, \\uc1) - } else if (ch == '}' || ch == '{' || ch == '\\') { - result.append('\\'); - result.append((char) ch); - } else { - // Fixes bug 21698. - result.append((char) ch); - } - }); - return result.toString(); - } - - /** - * Returns the index of the specified color in the RTF color table. - * - * @param color the color - * @param defaultIndex return value if color is null - * @return the index of the specified color in the RTF color table - * or "defaultIndex" if "color" is null. - */ - private int getColorIndex(Color color, int defaultIndex) { - if (color == null) return defaultIndex; - int index = colorTable.indexOf(color); - if (index == -1) { - index = colorTable.size(); - colorTable.add(color); - } - return index; - } - /** - * Returns the index of the specified color in the RTF color table. - * - * @param color the color - * @param defaultIndex return value if color is null - * @return the index of the specified color in the RTF color table - * or "defaultIndex" if "color" is null. - */ - private int getFontIndex(Font font) { - int index = fontTable.indexOf(font); - if (index == -1) { - index = fontTable.size(); - fontTable.add(font); - } - return index; + public RTFWriter(int start, int length) { + super(start, length); + // TODO Auto-generated constructor stub } +// static final int DEFAULT_FOREGROUND = 0; +// static final int DEFAULT_BACKGROUND = 1; +// List colorTable; +// List fontTable; +// +// public RTFWriter(StyledText styledText, int start, int length) { +// super(styledText, start, length); +// colorTable = new ArrayList<>(); +// fontTable = new ArrayList<>(); +// colorTable.add(this.styledText.getForeground()); +// colorTable.add(this.styledText.getBackground()); +// fontTable.add(this.styledText.getFont()); +// } +// +// @Override +// public void close() { +// if (!isClosed()) { +// writeHeader(); +// write("\n}}\0"); +// super.close(); +// } +// } +// +// /** +// * Writes the RTF header including font table and color table. +// */ +// @Override +// void writeHeader() { +// StringBuilder header = new StringBuilder(); +// FontData fontData = styledText.getFont().getFontData()[0]; +// header.append("{\\rtf1\\ansi"); +// // specify code page, necessary for copy to work in bidi +// // systems that don't support Unicode RTF. +// String cpg = System.getProperty("file.encoding").toLowerCase(); +// if (cpg.startsWith("cp") || cpg.startsWith("ms")) { +// cpg = cpg.substring(2, cpg.length()); +// header.append("\\ansicpg"); +// header.append(cpg); +// } +// header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil "); +// header.append(fontData.getName()); +// header.append(";"); +// for (int i = 1; i < fontTable.size(); i++) { +// header.append("\\f"); +// header.append(i); +// header.append(" "); +// FontData fd = fontTable.get(i).getFontData()[0]; +// header.append(fd.getName()); +// header.append(";"); +// } +// header.append("}}\n{\\colortbl"); +// for (Color color : colorTable) { +// header.append("\\red"); +// header.append(color.getRed()); +// header.append("\\green"); +// header.append(color.getGreen()); +// header.append("\\blue"); +// header.append(color.getBlue()); +// header.append(";"); +// } +// // some RTF readers ignore the deff0 font tag. Explicitly +// // set the font for the whole document to work around this. +// header.append("}\n{\\f0\\fs"); +// // font size is specified in half points +// header.append(fontData.getHeight() * 2); +// header.append(" "); +// write(header.toString(), 0); +// } +// +// @Override +// public void writeLineDelimiter(String lineDelimiter) { +// if (isClosed()) { +// SWT.error(SWT.ERROR_IO); +// } +// write(lineDelimiter); +// write("\\par "); +// } +// +// @Override +// String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { +// write("\\fi"); +// write(indent); +// switch (alignment) { +// case SWT.LEFT: write("\\ql"); break; +// case SWT.CENTER: write("\\qc"); break; +// case SWT.RIGHT: write("\\qr"); break; +// } +// if (justify) { +// write("\\qj"); +// } +// write(" "); +// +// if (lineBackground != null) { +// // Background colors are written using the {@code \chshdng0\chcbpat} tag (vs. the {@code \cb} tag). +// write("{\\chshdng0\\chcbpat"); +// write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); +// write(" "); +// } +// +// // This is what will be used to close the line +// return lineBackground == null ? "" : "}"; +// } +// +// @Override +// void writeEmptyLine() { +// // Do nothing. RTF does not need special treatment for empty paragraph. +// } +// +// @Override +// String writeSpanStart(StyleRange style) { +// write("{\\cf"); +// write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); +// int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); +// if (colorIndex != DEFAULT_BACKGROUND) { +// write("\\chshdng0\\chcbpat"); +// write(colorIndex); +// } +// int fontStyle = style.fontStyle; +// Font font = style.font; +// if (font != null) { +// int fontIndex = getFontIndex(font); +// write("\\f"); +// write(fontIndex); +// FontData fontData = font.getFontData()[0]; +// write("\\fs"); +// write(fontData.getHeight() * 2); +// fontStyle = fontData.getStyle(); +// } +// if ((fontStyle & SWT.BOLD) != 0) { +// write("\\b"); +// } +// if ((fontStyle & SWT.ITALIC) != 0) { +// write("\\i"); +// } +// if (style.underline) { +// write("\\ul"); +// } +// if (style.strikeout) { +// write("\\strike"); +// } +// write(" "); +// +// // This is what will be used to close the span +// StringBuilder toCloseSpan = new StringBuilder(); +// if ((fontStyle & SWT.BOLD) != 0) { +// toCloseSpan.append("\\b0"); +// } +// if ((style.fontStyle & SWT.ITALIC) != 0) { +// toCloseSpan.append("\\i0"); +// } +// if (style.underline) { +// toCloseSpan.append("\\ul0"); +// } +// if (style.strikeout) { +// toCloseSpan.append("\\strike0"); +// } +// toCloseSpan.append("}"); +// return toCloseSpan.toString(); +// } +// +// // ==== Helper methods ==== +// +// @Override +// String escapeText(String string) { +// // The resulting string is at least as long as the original. +// StringBuilder result = new StringBuilder(string.length()); +// string.chars().forEach(ch -> { +// if (ch > 0x7F) { +// result.append("\\u"); +// result.append(Integer.toString((short) ch)); +// result.append('?'); // ANSI representation (1 byte long, \\uc1) +// } else if (ch == '}' || ch == '{' || ch == '\\') { +// result.append('\\'); +// result.append((char) ch); +// } else { +// // Fixes bug 21698. +// result.append((char) ch); +// } +// }); +// return result.toString(); +// } +// +// /** +// * Returns the index of the specified color in the RTF color table. +// * +// * @param color the color +// * @param defaultIndex return value if color is null +// * @return the index of the specified color in the RTF color table +// * or "defaultIndex" if "color" is null. +// */ +// private int getColorIndex(Color color, int defaultIndex) { +// if (color == null) return defaultIndex; +// int index = colorTable.indexOf(color); +// if (index == -1) { +// index = colorTable.size(); +// colorTable.add(color); +// } +// return index; +// } +// +// /** +// * Returns the index of the specified color in the RTF color table. +// * +// * @param color the color +// * @param defaultIndex return value if color is null +// * @return the index of the specified color in the RTF color table +// * or "defaultIndex" if "color" is null. +// */ +// private int getFontIndex(Font font) { +// int index = fontTable.indexOf(font); +// if (index == -1) { +// index = fontTable.size(); +// fontTable.add(font); +// } +// return index; +// } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index 335acfb8bfb..0fc1765ed9c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -16,10869 +16,10919 @@ * Karsten Thoms - bug 528746 add getOffsetAtPoint(Point) *******************************************************************************/ package org.eclipse.swt.custom; - - -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -import org.eclipse.swt.*; -import org.eclipse.swt.accessibility.*; -import org.eclipse.swt.dnd.*; -import org.eclipse.swt.events.*; -import org.eclipse.swt.graphics.*; -import org.eclipse.swt.internal.*; -import org.eclipse.swt.printing.*; -import org.eclipse.swt.widgets.*; - -/** - * A StyledText is an editable user interface object that displays lines - * of text. The following style attributes can be defined for the text: - *
      - *
    • foreground color - *
    • background color - *
    • font style (bold, italic, bold-italic, regular) - *
    • underline - *
    • strikeout - *
    - *

    - * In addition to text style attributes, the background color of a line may - * be specified. - *

    - * There are two ways to use this widget when specifying text style information. - * You may use the API that is defined for StyledText or you may define your own - * LineStyleListener. If you define your own listener, you will be responsible - * for maintaining the text style information for the widget. IMPORTANT: You may - * not define your own listener and use the StyledText API. The following - * StyledText API is not supported if you have defined a LineStyleListener:

    - *
      - *
    • getStyleRangeAtOffset(int) - *
    • getStyleRanges() - *
    • replaceStyleRanges(int,int,StyleRange[]) - *
    • setStyleRange(StyleRange) - *
    • setStyleRanges(StyleRange[]) - *
    - *

    - * There are two ways to use this widget when specifying line background colors. - * You may use the API that is defined for StyledText or you may define your own - * LineBackgroundListener. If you define your own listener, you will be responsible - * for maintaining the line background color information for the widget. - * IMPORTANT: You may not define your own listener and use the StyledText API. - * The following StyledText API is not supported if you have defined a - * LineBackgroundListener:

    - *
      - *
    • getLineBackground(int) - *
    • setLineBackground(int,int,Color) - *
    - *

    - * The content implementation for this widget may also be user-defined. To do so, - * you must implement the StyledTextContent interface and use the StyledText API - * setContent(StyledTextContent) to initialize the widget. - *

    - *
    - *
    Styles:
    FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP - *
    Events:
    ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey, OrientationChange - *
    - *

    - * IMPORTANT: This class is not intended to be subclassed. - *

    - * - * @see StyledText snippets - * @see SWT Examples: CustomControlExample, TextEditor - * @see Sample code and further information - * @noextend This class is not intended to be subclassed by clients. - */ -public class StyledText extends Canvas { - static final char TAB = '\t'; - static final String PlatformLineDelimiter = System.lineSeparator(); - static final int BIDI_CARET_WIDTH = 3; - static final int DEFAULT_WIDTH = 64; - static final int DEFAULT_HEIGHT = 64; - static final int V_SCROLL_RATE = 50; - static final int H_SCROLL_RATE = 10; - static final int PREVIOUS_OFFSET_TRAILING = 0; - static final int OFFSET_LEADING = 1; - - static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-1$ - private static int getX(Point p) { return p.x; } // workaround p -> p.x lose typing and cannot be chained in comparing... - static final Comparator SELECTION_COMPARATOR = Comparator.comparingInt(StyledText::getX).thenComparingInt(p -> p.y); - - Color selectionBackground; // selection background color - Color selectionForeground; // selection foreground color - StyledTextContent content; // native content (default or user specified) - StyledTextRenderer renderer; - Listener listener; - TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent - int verticalScrollOffset = 0; // pixel based - int horizontalScrollOffset = 0; // pixel based - boolean alwaysShowScroll = true; - int ignoreResize = 0; - int topIndex = 0; // top visible line - int topIndexY; - int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback - int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated - int tabLength = 4; // number of characters in a tab - int [] tabs; - int leftMargin; - int topMargin; - int rightMargin; - int bottomMargin; - Color marginColor; - int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 - Caret[] carets; - int[] caretOffsets = {0}; - int caretAlignment; - Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y) - int[] selectionAnchors = {0}; // position of selection anchor for the selection ranges. 0 based offset from beginning of text - Point clipboardSelection; // x and y are start and end caret offsets of previous selection - Point doubleClickSelection; // selection after last mouse double click - boolean editable = true; - boolean wordWrap = false; // text is wrapped automatically - boolean visualWrap = false; // process line breaks inside logical lines (inserted by BidiSegmentEvent) - boolean hasStyleWithVariableHeight = false; - boolean hasVerticalIndent = false; - boolean doubleClickEnabled = true; // see getDoubleClickEnabled - boolean overwrite = false; // insert/overwrite edit mode - int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. - Map keyActionMap = new HashMap<>(); - Color background = null; // workaround for bug 4791 - Color foreground = null; // - /** True if a non-default background color is set */ - boolean customBackground; - /** True if a non-default foreground color is set */ - boolean customForeground; - /** False iff the widget is disabled */ - boolean enabled = true; - /** True iff the widget is in the midst of being enabled or disabled */ - boolean insideSetEnableCall; - Clipboard clipboard; - int clickCount; - int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left) - int autoScrollDistance = 0; - int lastTextChangeStart; // cache data of the - int lastTextChangeNewLineCount; // last text changing - int lastTextChangeNewCharCount; // event for use in the - int lastTextChangeReplaceLineCount; // text changed handler - int lastTextChangeReplaceCharCount; - int lastCharCount = 0; - int lastLineBottom; // the bottom pixel of the last line been replaced - boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color - Image leftCaretBitmap = null; - Image rightCaretBitmap = null; - int caretDirection = SWT.NULL; - int caretWidth = 0; - Caret defaultCaret = null; - boolean updateCaretDirection = true; - boolean dragDetect = true; - IME ime; - Cursor cursor; - int alignment; - boolean justify; - int indent, wrapIndent; - int lineSpacing; - int alignmentMargin; - int newOrientation = SWT.NONE; - int accCaretOffset; - Accessible acc; - AccessibleControlAdapter accControlAdapter; - AccessibleAttributeAdapter accAttributeAdapter; - AccessibleEditableTextListener accEditableTextListener; - AccessibleTextExtendedAdapter accTextExtendedAdapter; - AccessibleAdapter accAdapter; - MouseNavigator mouseNavigator; - boolean middleClickPressed; - - //block selection - boolean blockSelection; - int blockXAnchor = -1, blockYAnchor = -1; - int blockXLocation = -1, blockYLocation = -1; - - final static boolean IS_MAC, IS_GTK; - static { - String platform = SWT.getPlatform(); - IS_MAC = "cocoa".equals(platform); - IS_GTK = "gtk".equals(platform); - } - - /** - * The Printing class implements printing of a range of text. - * An instance of Printing is returned in the - * StyledText#print(Printer) API. The run() method may be - * invoked from any thread. - */ - static class Printing implements Runnable { - final static int LEFT = 0; // left aligned header/footer segment - final static int CENTER = 1; // centered header/footer segment - final static int RIGHT = 2; // right aligned header/footer segment - - Printer printer; - StyledTextRenderer printerRenderer; - StyledTextPrintOptions printOptions; - Rectangle clientArea; - FontData fontData; - Font printerFont; - Map resources; - int tabLength; - GC gc; // printer GC - int pageWidth; // width of a printer page in pixels - int startPage; // first page to print - int endPage; // last page to print - int scope; // scope of print job - int startLine; // first (wrapped) line to print - int endLine; // last (wrapped) line to print - boolean singleLine; // widget single line mode - Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y) - boolean mirrored; // indicates the printing gc should be mirrored - int lineSpacing; - int printMargin; - - /** - * Creates an instance of Printing. - * Copies the widget content and rendering data that needs - * to be requested from listeners. - * - * @param parent StyledText widget to print. - * @param printer printer device to print on. - * @param printOptions print options - */ - Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { - this.printer = printer; - this.printOptions = printOptions; - this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0; - singleLine = styledText.isSingleLine(); - startPage = 1; - endPage = Integer.MAX_VALUE; - PrinterData data = printer.getPrinterData(); - scope = data.scope; - if (scope == PrinterData.PAGE_RANGE) { - startPage = data.startPage; - endPage = data.endPage; - if (endPage < startPage) { - int temp = endPage; - endPage = startPage; - startPage = temp; - } - } else if (scope == PrinterData.SELECTION) { - selection = Arrays.copyOf(styledText.selection, styledText.selection.length); - } - printerRenderer = new StyledTextRenderer(printer, null); - printerRenderer.setContent(copyContent(styledText.getContent())); - cacheLineData(styledText); - } - /** - * Caches all line data that needs to be requested from a listener. - * - * @param printerContent StyledTextContent to request - * line data for. - */ - void cacheLineData(StyledText styledText) { - StyledTextRenderer renderer = styledText.renderer; - renderer.copyInto(printerRenderer); - fontData = styledText.getFont().getFontData()[0]; - tabLength = styledText.tabLength; - int lineCount = printerRenderer.lineCount; - if (styledText.isListening(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.LineGetStyle)) { - StyledTextContent content = printerRenderer.content; - for (int i = 0; i < lineCount; i++) { - String line = content.getLine(i); - int lineOffset = content.getOffsetAtLine(i); - StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line); - if (event != null && event.lineBackground != null) { - printerRenderer.setLineBackground(i, 1, event.lineBackground); - } - event = styledText.getBidiSegments(lineOffset, line); - if (event != null) { - printerRenderer.setLineSegments(i, 1, event.segments); - printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars); - } - event = styledText.getLineStyleData(lineOffset, line); - if (event != null) { - printerRenderer.setLineIndent(i, 1, event.indent); - printerRenderer.setLineAlignment(i, 1, event.alignment); - printerRenderer.setLineJustify(i, 1, event.justify); - printerRenderer.setLineBullet(i, 1, event.bullet); - StyleRange[] styles = event.styles; - if (styles != null && styles.length > 0) { - printerRenderer.setStyleRanges(event.ranges, styles); - } - } - } - } - Point screenDPI = styledText.getDisplay().getDPI(); - Point printerDPI = printer.getDPI(); - resources = new HashMap<> (); - for (int i = 0; i < lineCount; i++) { - Color color = printerRenderer.getLineBackground(i, null); - if (color != null) { - if (printOptions.printLineBackground) { - Color printerColor = (Color)resources.get(color); - if (printerColor == null) { - printerColor = new Color (color.getRGB()); - resources.put(color, printerColor); - } - printerRenderer.setLineBackground(i, 1, printerColor); - } else { - printerRenderer.setLineBackground(i, 1, null); - } - } - int indent = printerRenderer.getLineIndent(i, 0); - if (indent != 0) { - printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x); - } - } - StyleRange[] styles = printerRenderer.styles; - for (int i = 0; i < printerRenderer.styleCount; i++) { - StyleRange style = styles[i]; - Font font = style.font; - if (style.font != null) { - Font printerFont = (Font)resources.get(font); - if (printerFont == null) { - printerFont = new Font (printer, font.getFontData()); - resources.put(font, printerFont); - } - style.font = printerFont; - } - Color color = style.foreground; - if (color != null) { - Color printerColor = (Color)resources.get(color); - if (printOptions.printTextForeground) { - if (printerColor == null) { - printerColor = new Color (color.getRGB()); - resources.put(color, printerColor); - } - style.foreground = printerColor; - } else { - style.foreground = null; - } - } - color = style.background; - if (color != null) { - Color printerColor = (Color)resources.get(color); - if (printOptions.printTextBackground) { - if (printerColor == null) { - printerColor = new Color (color.getRGB()); - resources.put(color, printerColor); - } - style.background = printerColor; - } else { - style.background = null; - } - } - if (!printOptions.printTextFontStyle) { - style.fontStyle = SWT.NORMAL; - } - style.rise = style.rise * printerDPI.y / screenDPI.y; - GlyphMetrics metrics = style.metrics; - if (metrics != null) { - metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y; - metrics.descent = metrics.descent * printerDPI.y / screenDPI.y; - metrics.width = metrics.width * printerDPI.x / screenDPI.x; - } - } - lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y; - if (printOptions.printLineNumbers) { - printMargin = 3 * printerDPI.x / screenDPI.x; - } - } - /** - * Copies the text of the specified StyledTextContent. - * - * @param original the StyledTextContent to copy. - */ - StyledTextContent copyContent(StyledTextContent original) { - StyledTextContent printerContent = new DefaultContent(); - int insertOffset = 0; - for (int i = 0; i < original.getLineCount(); i++) { - int insertEndOffset; - if (i < original.getLineCount() - 1) { - insertEndOffset = original.getOffsetAtLine(i + 1); - } else { - insertEndOffset = original.getCharCount(); - } - printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset)); - insertOffset = insertEndOffset; - } - return printerContent; - } - /** - * Disposes of the resources and the PrintRenderer. - */ - void dispose() { - if (gc != null) { - gc.dispose(); - gc = null; - } - if (resources != null) { - for (Resource resource : resources.values()) { - resource.dispose(); - } - resources = null; - } - if (printerFont != null) { - printerFont.dispose(); - printerFont = null; - } - if (printerRenderer != null) { - printerRenderer.dispose(); - printerRenderer = null; - } - } - void init() { - Rectangle trim = printer.computeTrim(0, 0, 0, 0); - Point dpi = printer.getDPI(); - - printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL); - clientArea = printer.getClientArea(); - pageWidth = clientArea.width; - // one inch margin around text - clientArea.x = dpi.x + trim.x; - clientArea.y = dpi.y + trim.y; - clientArea.width -= (clientArea.x + trim.width); - clientArea.height -= (clientArea.y + trim.height); - - int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; - gc = new GC(printer, style); - gc.setFont(printerFont); - printerRenderer.setFont(printerFont, tabLength); - int lineHeight = printerRenderer.getLineHeight(); - if (printOptions.header != null) { - clientArea.y += lineHeight * 2; - clientArea.height -= lineHeight * 2; - } - if (printOptions.footer != null) { - clientArea.height -= lineHeight * 2; - } - - // TODO not wrapped - StyledTextContent content = printerRenderer.content; - startLine = 0; - endLine = singleLine ? 0 : content.getLineCount() - 1; - if (scope == PrinterData.PAGE_RANGE) { - int pageSize = clientArea.height / lineHeight;//WRONG - startLine = (startPage - 1) * pageSize; - } else if (scope == PrinterData.SELECTION) { - startLine = content.getLineAtOffset(selection[0].x); - if (selection[0].y > 0) { - endLine = content.getLineAtOffset(selection[0].y); - } else { - endLine = startLine - 1; - } - } - } - /** - * Prints the lines in the specified page range. - */ - void print() { - Color background = gc.getBackground(); - Color foreground = gc.getForeground(); - int paintY = clientArea.y; - int paintX = clientArea.x; - int width = clientArea.width; - int page = startPage; - int pageBottom = clientArea.y + clientArea.height; - int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT); - TextLayout printLayout = null; - if (printOptions.printLineNumbers || printOptions.header != null || printOptions.footer != null) { - printLayout = new TextLayout(printer); - printLayout.setFont(printerFont); - } - if (printOptions.printLineNumbers) { - int numberingWidth = 0; - int count = endLine - startLine + 1; - String[] lineLabels = printOptions.lineLabels; - if (lineLabels != null) { - for (int i = startLine; i < Math.min(count, lineLabels.length); i++) { - if (lineLabels[i] != null) { - printLayout.setText(lineLabels[i]); - int lineWidth = printLayout.getBounds().width; - numberingWidth = Math.max(numberingWidth, lineWidth); - } - } - } else { - StringBuilder buffer = new StringBuilder("0"); - while ((count /= 10) > 0) buffer.append("0"); - printLayout.setText(buffer.toString()); - numberingWidth = printLayout.getBounds().width; - } - numberingWidth += printMargin; - if (numberingWidth > width) numberingWidth = width; - paintX += numberingWidth; - width -= numberingWidth; - } - for (int i = startLine; i <= endLine && page <= endPage; i++) { - if (paintY == clientArea.y) { - printer.startPage(); - printDecoration(page, true, printLayout); - } - TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); - Color lineBackground = printerRenderer.getLineBackground(i, background); - int paragraphBottom = paintY + layout.getBounds().height; - if (paragraphBottom <= pageBottom) { - //normal case, the whole paragraph fits in the current page - printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); - paintY = paragraphBottom; - } else { - int lineCount = layout.getLineCount(); - while (paragraphBottom > pageBottom && lineCount > 0) { - lineCount--; - paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing(); - } - if (lineCount == 0) { - //the whole paragraph goes to the next page - printDecoration(page, false, printLayout); - printer.endPage(); - page++; - if (page <= endPage) { - printer.startPage(); - printDecoration(page, true, printLayout); - paintY = clientArea.y; - printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); - paintY += layout.getBounds().height; - } - } else { - //draw paragraph top in the current page and paragraph bottom in the next - int height = paragraphBottom - paintY; - gc.setClipping(clientArea.x, paintY, clientArea.width, height); - printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); - gc.setClipping((Rectangle)null); - printDecoration(page, false, printLayout); - printer.endPage(); - page++; - if (page <= endPage) { - printer.startPage(); - printDecoration(page, true, printLayout); - paintY = clientArea.y - height; - int layoutHeight = layout.getBounds().height; - gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height); - printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); - gc.setClipping((Rectangle)null); - paintY += layoutHeight; - } - } - } - printerRenderer.disposeTextLayout(layout); - } - if (page <= endPage && paintY > clientArea.y) { - // close partial page - printDecoration(page, false, printLayout); - printer.endPage(); - } - if (printLayout != null) printLayout.dispose(); - } - /** - * Print header or footer decorations. - * - * @param page page number to print, if specified in the StyledTextPrintOptions header or footer. - * @param header true = print the header, false = print the footer - */ - void printDecoration(int page, boolean header, TextLayout layout) { - String text = header ? printOptions.header : printOptions.footer; - if (text == null) return; - int lastSegmentIndex = 0; - for (int i = 0; i < 3; i++) { - int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); - String segment; - if (segmentIndex == -1) { - segment = text.substring(lastSegmentIndex); - printDecorationSegment(segment, i, page, header, layout); - break; - } else { - segment = text.substring(lastSegmentIndex, segmentIndex); - printDecorationSegment(segment, i, page, header, layout); - lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); - } - } - } - /** - * Print one segment of a header or footer decoration. - * Headers and footers have three different segments. - * One each for left aligned, centered, and right aligned text. - * - * @param segment decoration segment to print - * @param alignment alignment of the segment. 0=left, 1=center, 2=right - * @param page page number to print, if specified in the decoration segment. - * @param header true = print the header, false = print the footer - */ - void printDecorationSegment(String segment, int alignment, int page, boolean header, TextLayout layout) { - int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); - if (pageIndex != -1) { - int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); - StringBuilder buffer = new StringBuilder(segment.substring (0, pageIndex)); - buffer.append (page); - buffer.append (segment.substring(pageIndex + pageTagLength)); - segment = buffer.toString(); - } - if (segment.length() > 0) { - layout.setText(segment); - int segmentWidth = layout.getBounds().width; - int segmentHeight = printerRenderer.getLineHeight(); - int drawX = 0, drawY; - if (alignment == LEFT) { - drawX = clientArea.x; - } else if (alignment == CENTER) { - drawX = (pageWidth - segmentWidth) / 2; - } else if (alignment == RIGHT) { - drawX = clientArea.x + clientArea.width - segmentWidth; - } - if (header) { - drawY = clientArea.y - segmentHeight * 2; - } else { - drawY = clientArea.y + clientArea.height + segmentHeight; - } - layout.draw(gc, drawX, drawY); - } - } - void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) { - if (background != null) { - Rectangle rect = layout.getBounds(); - gc.setBackground(background); - gc.fillRectangle(x, y, rect.width, rect.height); - -// int lineCount = layout.getLineCount(); +// +// +//import java.util.*; +//import java.util.function.*; +//import java.util.stream.*; +// +//import org.eclipse.swt.*; +//import org.eclipse.swt.accessibility.*; +//import org.eclipse.swt.dnd.*; +//import org.eclipse.swt.events.*; +//import org.eclipse.swt.graphics.*; +//import org.eclipse.swt.internal.*; +//import org.eclipse.swt.printing.*; +//import org.eclipse.swt.widgets.*; +// +///** +// * A StyledText is an editable user interface object that displays lines +// * of text. The following style attributes can be defined for the text: +// *
      +// *
    • foreground color +// *
    • background color +// *
    • font style (bold, italic, bold-italic, regular) +// *
    • underline +// *
    • strikeout +// *
    +// *

    +// * In addition to text style attributes, the background color of a line may +// * be specified. +// *

    +// * There are two ways to use this widget when specifying text style information. +// * You may use the API that is defined for StyledText or you may define your own +// * LineStyleListener. If you define your own listener, you will be responsible +// * for maintaining the text style information for the widget. IMPORTANT: You may +// * not define your own listener and use the StyledText API. The following +// * StyledText API is not supported if you have defined a LineStyleListener:

    +// *
      +// *
    • getStyleRangeAtOffset(int) +// *
    • getStyleRanges() +// *
    • replaceStyleRanges(int,int,StyleRange[]) +// *
    • setStyleRange(StyleRange) +// *
    • setStyleRanges(StyleRange[]) +// *
    +// *

    +// * There are two ways to use this widget when specifying line background colors. +// * You may use the API that is defined for StyledText or you may define your own +// * LineBackgroundListener. If you define your own listener, you will be responsible +// * for maintaining the line background color information for the widget. +// * IMPORTANT: You may not define your own listener and use the StyledText API. +// * The following StyledText API is not supported if you have defined a +// * LineBackgroundListener:

    +// *
      +// *
    • getLineBackground(int) +// *
    • setLineBackground(int,int,Color) +// *
    +// *

    +// * The content implementation for this widget may also be user-defined. To do so, +// * you must implement the StyledTextContent interface and use the StyledText API +// * setContent(StyledTextContent) to initialize the widget. +// *

    +// *
    +// *
    Styles:
    FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP +// *
    Events:
    ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey, OrientationChange +// *
    +// *

    +// * IMPORTANT: This class is not intended to be subclassed. +// *

    +// * +// * @see StyledText snippets +// * @see SWT Examples: CustomControlExample, TextEditor +// * @see Sample code and further information +// * @noextend This class is not intended to be subclassed by clients. +// */ +//public class StyledText extends Canvas { +// static final char TAB = '\t'; +// static final String PlatformLineDelimiter = System.lineSeparator(); +// static final int BIDI_CARET_WIDTH = 3; +// static final int DEFAULT_WIDTH = 64; +// static final int DEFAULT_HEIGHT = 64; +// static final int V_SCROLL_RATE = 50; +// static final int H_SCROLL_RATE = 10; +// static final int PREVIOUS_OFFSET_TRAILING = 0; +// static final int OFFSET_LEADING = 1; +// +// static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-1$ +// private static int getX(Point p) { return p.x; } // workaround p -> p.x lose typing and cannot be chained in comparing... +// static final Comparator SELECTION_COMPARATOR = Comparator.comparingInt(StyledText::getX).thenComparingInt(p -> p.y); +// +// Color selectionBackground; // selection background color +// Color selectionForeground; // selection foreground color +// StyledTextContent content; // native content (default or user specified) +// StyledTextRenderer renderer; +// Listener listener; +// TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent +// int verticalScrollOffset = 0; // pixel based +// int horizontalScrollOffset = 0; // pixel based +// boolean alwaysShowScroll = true; +// int ignoreResize = 0; +// int topIndex = 0; // top visible line +// int topIndexY; +// int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback +// int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated +// int tabLength = 4; // number of characters in a tab +// int [] tabs; +// int leftMargin; +// int topMargin; +// int rightMargin; +// int bottomMargin; +// Color marginColor; +// int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 +// Caret[] carets; +// int[] caretOffsets = {0}; +// int caretAlignment; +// Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y) +// int[] selectionAnchors = {0}; // position of selection anchor for the selection ranges. 0 based offset from beginning of text +// Point clipboardSelection; // x and y are start and end caret offsets of previous selection +// Point doubleClickSelection; // selection after last mouse double click +// boolean editable = true; +// boolean wordWrap = false; // text is wrapped automatically +// boolean visualWrap = false; // process line breaks inside logical lines (inserted by BidiSegmentEvent) +// boolean hasStyleWithVariableHeight = false; +// boolean hasVerticalIndent = false; +// boolean doubleClickEnabled = true; // see getDoubleClickEnabled +// boolean overwrite = false; // insert/overwrite edit mode +// int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. +// Map keyActionMap = new HashMap<>(); +// Color background = null; // workaround for bug 4791 +// Color foreground = null; // +// /** True if a non-default background color is set */ +// boolean customBackground; +// /** True if a non-default foreground color is set */ +// boolean customForeground; +// /** False iff the widget is disabled */ +// boolean enabled = true; +// /** True iff the widget is in the midst of being enabled or disabled */ +// boolean insideSetEnableCall; +// Clipboard clipboard; +// int clickCount; +// int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left) +// int autoScrollDistance = 0; +// int lastTextChangeStart; // cache data of the +// int lastTextChangeNewLineCount; // last text changing +// int lastTextChangeNewCharCount; // event for use in the +// int lastTextChangeReplaceLineCount; // text changed handler +// int lastTextChangeReplaceCharCount; +// int lastCharCount = 0; +// int lastLineBottom; // the bottom pixel of the last line been replaced +// boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color +// Image leftCaretBitmap = null; +// Image rightCaretBitmap = null; +// int caretDirection = SWT.NULL; +// int caretWidth = 0; +// Caret defaultCaret = null; +// boolean updateCaretDirection = true; +// boolean dragDetect = true; +// IME ime; +// Cursor cursor; +// int alignment; +// boolean justify; +// int indent, wrapIndent; +// int lineSpacing; +// int alignmentMargin; +// int newOrientation = SWT.NONE; +// int accCaretOffset; +// Accessible acc; +// AccessibleControlAdapter accControlAdapter; +// AccessibleAttributeAdapter accAttributeAdapter; +// AccessibleEditableTextListener accEditableTextListener; +// AccessibleTextExtendedAdapter accTextExtendedAdapter; +// AccessibleAdapter accAdapter; +// MouseNavigator mouseNavigator; +// boolean middleClickPressed; +// +// //block selection +// boolean blockSelection; +// int blockXAnchor = -1, blockYAnchor = -1; +// int blockXLocation = -1, blockYLocation = -1; +// +// final static boolean IS_MAC, IS_GTK; +// static { +// String platform = SWT.getPlatform(); +// IS_MAC = "cocoa".equals(platform); +// IS_GTK = "gtk".equals(platform); +// } +// +// /** +// * The Printing class implements printing of a range of text. +// * An instance of Printing is returned in the +// * StyledText#print(Printer) API. The run() method may be +// * invoked from any thread. +// */ +// static class Printing implements Runnable { +// final static int LEFT = 0; // left aligned header/footer segment +// final static int CENTER = 1; // centered header/footer segment +// final static int RIGHT = 2; // right aligned header/footer segment +// +// Printer printer; +// StyledTextRenderer printerRenderer; +// StyledTextPrintOptions printOptions; +// Rectangle clientArea; +// FontData fontData; +// Font printerFont; +// Map resources; +// int tabLength; +// GC gc; // printer GC +// int pageWidth; // width of a printer page in pixels +// int startPage; // first page to print +// int endPage; // last page to print +// int scope; // scope of print job +// int startLine; // first (wrapped) line to print +// int endLine; // last (wrapped) line to print +// boolean singleLine; // widget single line mode +// Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y) +// boolean mirrored; // indicates the printing gc should be mirrored +// int lineSpacing; +// int printMargin; +// +// /** +// * Creates an instance of Printing. +// * Copies the widget content and rendering data that needs +// * to be requested from listeners. +// * +// * @param parent StyledText widget to print. +// * @param printer printer device to print on. +// * @param printOptions print options +// */ +// Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { +// this.printer = printer; +// this.printOptions = printOptions; +// this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0; +// singleLine = styledText.isSingleLine(); +// startPage = 1; +// endPage = Integer.MAX_VALUE; +// PrinterData data = printer.getPrinterData(); +// scope = data.scope; +// if (scope == PrinterData.PAGE_RANGE) { +// startPage = data.startPage; +// endPage = data.endPage; +// if (endPage < startPage) { +// int temp = endPage; +// endPage = startPage; +// startPage = temp; +// } +// } else if (scope == PrinterData.SELECTION) { +// selection = Arrays.copyOf(styledText.selection, styledText.selection.length); +// } +// printerRenderer = new StyledTextRenderer(printer, null); +// printerRenderer.setContent(copyContent(styledText.getContent())); +// cacheLineData(styledText); +// } +// /** +// * Caches all line data that needs to be requested from a listener. +// * +// * @param printerContent StyledTextContent to request +// * line data for. +// */ +// void cacheLineData(StyledText styledText) { +// StyledTextRenderer renderer = styledText.renderer; +// renderer.copyInto(printerRenderer); +// fontData = styledText.getFont().getFontData()[0]; +// tabLength = styledText.tabLength; +// int lineCount = printerRenderer.lineCount; +// if (styledText.isListening(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.LineGetStyle)) { +// StyledTextContent content = printerRenderer.content; // for (int i = 0; i < lineCount; i++) { -// Rectangle rect = layout.getLineBounds(i); -// rect.x += paintX; -// rect.y += paintY + layout.getSpacing(); -// rect.width = width;//layout bounds -// gc.fillRectangle(rect); -// } - } - if (printOptions.printLineNumbers) { - FontMetrics metrics = layout.getLineMetrics(0); - printLayout.setAscent(metrics.getAscent() + metrics.getLeading()); - printLayout.setDescent(metrics.getDescent()); - String[] lineLabels = printOptions.lineLabels; - if (lineLabels != null) { - if (0 <= index && index < lineLabels.length && lineLabels[index] != null) { - printLayout.setText(lineLabels[index]); - } else { - printLayout.setText(""); - } - } else { - printLayout.setText(String.valueOf(index)); - } - int paintX = x - printMargin - printLayout.getBounds().width; - printLayout.draw(gc, paintX, y); - printLayout.setAscent(-1); - printLayout.setDescent(-1); - } - gc.setForeground(foreground); - layout.draw(gc, x, y); - } - /** - * Starts a print job and prints the pages specified in the constructor. - */ - @Override - public void run() { - String jobName = printOptions.jobName; - if (jobName == null) { - jobName = "Printing"; - } - if (printer.startJob(jobName)) { - init(); - print(); - dispose(); - printer.endJob(); - } - } - } - -/** - * Constructs a new instance of this class given its parent - * and a style value describing its behavior and appearance. - *

    - * The style value is either one of the style constants defined in - * class SWT which is applicable to instances of this - * class, or must be built by bitwise OR'ing together - * (that is, using the int "|" operator) two or more - * of those SWT style constants. The class description - * lists the style constants that are applicable to the class. - * Style bits are also inherited from superclasses. - *

    - * - * @param parent a widget which will be the parent of the new instance (cannot be null) - * @param style the style of widget to construct - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • - *
    - * @exception SWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • - *
    - * - * @see SWT#FULL_SELECTION - * @see SWT#MULTI - * @see SWT#READ_ONLY - * @see SWT#SINGLE - * @see SWT#WRAP - * @see #getStyle - */ -public StyledText(Composite parent, int style) { - super(parent, checkStyle(style)); - // set the fg in the OS to ensure that these are the same as StyledText, necessary - // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses - super.setForeground(getForeground()); - super.setDragDetect(false); - Display display = getDisplay(); - if ((style & SWT.READ_ONLY) != 0) { - setEditable(false); - } - leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0; - if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) { - leftMargin = topMargin = rightMargin = bottomMargin = 2; - } - alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); - if (alignment == 0) alignment = SWT.LEFT; - clipboard = new Clipboard(display); - installDefaultContent(); - renderer = new StyledTextRenderer(getDisplay(), this); - renderer.setContent(content); - renderer.setFont(getFont(), tabLength); - ime = new IME(this, SWT.NONE); - defaultCaret = new Caret(this, SWT.NONE); - if ((style & SWT.WRAP) != 0) { - setWordWrap(true); - } - if (isBidiCaret()) { - createCaretBitmaps(); - Runnable runnable = () -> { - int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT; - if (direction == caretDirection) return; - if (getCaret() != defaultCaret) return; - setCaretLocations(Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new), direction); - }; - BidiUtil.addLanguageListener(this, runnable); - } - setCaret(defaultCaret); - calculateScrollBars(); - createKeyBindings(); - super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM)); - installListeners(); - initializeAccessible(); - setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); - if (IS_MAC) setData(STYLEDTEXT_KEY); -} -/** - * Adds an extended modify listener. An ExtendedModify event is sent by the - * widget when the widget text has changed. - * - * @param extendedModifyListener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { - checkWidget(); - if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - StyledTextListener typedListener = new StyledTextListener(extendedModifyListener); - addListener(ST.ExtendedModify, typedListener); -} -/** - * Adds a bidirectional segment listener. - *

    - * A BidiSegmentEvent is sent - * whenever a line of text is measured or rendered. You can - * specify text ranges in the line that should be treated as if they - * had a different direction than the surrounding text. - * This may be used when adjacent segments of right-to-left text should - * not be reordered relative to each other. - * E.g., multiple Java string literals in a right-to-left language - * should generally remain in logical order to each other, that is, the - * way they are stored. - *

    - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * @see BidiSegmentEvent - * @since 2.0 - */ -public void addBidiSegmentListener(BidiSegmentListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - addListener(ST.LineGetSegments, new StyledTextListener(listener)); - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Adds a caret listener. CaretEvent is sent when the caret offset changes. - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @since 3.5 - */ -public void addCaretListener(CaretListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - addListener(ST.CaretMoved, new StyledTextListener(listener)); -} -/** - * Adds a line background listener. A LineGetBackground event is sent by the - * widget to determine the background color for a line. - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addLineBackgroundListener(LineBackgroundListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - if (!isListening(ST.LineGetBackground)) { - renderer.clearLineBackground(0, content.getLineCount()); - } - addListener(ST.LineGetBackground, new StyledTextListener(listener)); -} -/** - * Adds a line style listener. A LineGetStyle event is sent by the widget to - * determine the styles for a line. - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addLineStyleListener(LineStyleListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - if (!isListening(ST.LineGetStyle)) { - setStyleRanges(0, 0, null, null, true); - renderer.clearLineStyle(0, content.getLineCount()); - } - addListener(ST.LineGetStyle, new StyledTextListener(listener)); - setCaretLocations(); -} -/** - * Adds a modify listener. A Modify event is sent by the widget when the widget text - * has changed. - * - * @param modifyListener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addModifyListener(ModifyListener modifyListener) { - addTypedListener(modifyListener, SWT.Modify); -} -/** - * Adds a paint object listener. A paint object event is sent by the widget when an object - * needs to be drawn. - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @since 3.2 - * - * @see PaintObjectListener - * @see PaintObjectEvent - */ -public void addPaintObjectListener(PaintObjectListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - addListener(ST.PaintObject, new StyledTextListener(listener)); -} -/** - * Adds a selection listener. A Selection event is sent by the widget when the - * user changes the selection. - *

    - * When widgetSelected is called, the event x and y fields contain - * the start and end caret indices of the selection[0]. The selection values returned are visual - * (i.e., x will always always be <= y). - * No event is sent when the caret is moved while the selection length is 0. - *

    - * widgetDefaultSelected is not called for StyledTexts. - *

    - * - * @param listener the listener which should be notified when the user changes the receiver's selection - - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see SelectionListener - * @see #removeSelectionListener - * @see SelectionEvent - */ -public void addSelectionListener(SelectionListener listener) { - addTypedListener(listener, SWT.Selection); -} -/** - * Adds a verify key listener. A VerifyKey event is sent by the widget when a key - * is pressed. The widget ignores the key press if the listener sets the doit field - * of the event to false. - * - * @param listener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addVerifyKeyListener(VerifyKeyListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - addListener(ST.VerifyKey, new StyledTextListener(listener)); -} -/** - * Adds a verify listener. A Verify event is sent by the widget when the widget text - * is about to change. The listener can set the event text and the doit field to - * change the text that is set in the widget or to force the widget to ignore the - * text change. - * - * @param verifyListener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void addVerifyListener(VerifyListener verifyListener) { - addTypedListener(verifyListener, SWT.Verify); -} -/** - * Adds a word movement listener. A movement event is sent when the boundary - * of a word is needed. For example, this occurs during word next and word - * previous actions. - * - * @param movementListener the listener - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @see MovementEvent - * @see MovementListener - * @see #removeWordMovementListener - * - * @since 3.3 - */ -public void addWordMovementListener(MovementListener movementListener) { - checkWidget(); - if (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - addListener(ST.WordNext, new StyledTextListener(movementListener)); - addListener(ST.WordPrevious, new StyledTextListener(movementListener)); -} -/** - * Appends a string to the text at the end of the widget. - * - * @param string the string to be appended - * @see #replaceTextRange(int,int,String) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void append(String string) { - checkWidget(); - if (string == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - int lastChar = Math.max(getCharCount(), 0); - replaceTextRange(lastChar, 0, string); -} -/** - * Calculates the scroll bars - */ -void calculateScrollBars() { - ScrollBar horizontalBar = getHorizontalBar(); - ScrollBar verticalBar = getVerticalBar(); - setScrollBars(true); - if (verticalBar != null) { - verticalBar.setIncrement(getVerticalIncrement()); - } - if (horizontalBar != null) { - horizontalBar.setIncrement(getHorizontalIncrement()); - } -} -/** - * Calculates the top index based on the current vertical scroll offset. - * The top index is the index of the topmost fully visible line or the - * topmost partially visible line if no line is fully visible. - * The top index starts at 0. - */ -void calculateTopIndex(int delta) { - int oldDelta = delta; - int oldTopIndex = topIndex; - int oldTopIndexY = topIndexY; - if (isFixedLineHeight()) { - int verticalIncrement = getVerticalIncrement(); - if (verticalIncrement == 0) { - return; - } - topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); - // Set top index to partially visible top line if no line is fully - // visible but at least some of the widget client area is visible. - // Fixes bug 15088. - if (topIndex >= 0) { - if (clientAreaHeight > 0) { - int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; - topIndexY = getLinePixel(topIndex); - int fullLineTopPixel = topIndex * verticalIncrement; - int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; - // set top index to partially visible line if no line fully fits in - // client area or if space is available but not used (the latter should - // never happen because we use claimBottomFreeSpace) - if (fullLineVisibleHeight < verticalIncrement) { - topIndex = getVerticalScrollOffset() / verticalIncrement; - } - } else if (topIndex >= content.getLineCount()) { - topIndex = content.getLineCount() - 1; - } - } - } else { - if (delta >= 0) { - delta -= topIndexY; - int lineIndex = topIndex; - int lineCount = content.getLineCount(); - while (lineIndex < lineCount) { - if (delta <= 0) break; - delta -= renderer.getCachedLineHeight(lineIndex++); - } - if (lineIndex < lineCount && -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { - topIndex = lineIndex; - topIndexY = -delta; - } else { - topIndex = lineIndex - 1; - topIndexY = -renderer.getCachedLineHeight(topIndex) - delta; - } - } else { - delta -= topIndexY; - int lineIndex = topIndex; - while (lineIndex > 0) { - int lineHeight = renderer.getCachedLineHeight(lineIndex - 1); - if (delta + lineHeight > 0) break; - delta += lineHeight; - lineIndex--; - } - if (lineIndex == 0 || -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { - topIndex = lineIndex; - topIndexY = - delta; - } else { - topIndex = lineIndex - 1; - topIndexY = - renderer.getCachedLineHeight(topIndex) - delta; - } - } - } - if (topIndex < 0) { - // TODO: This logging is in place to determine why topIndex is getting set to negative values. - // It should be deleted once we fix the root cause of this issue. See bug 487254 for details. - System.err.println("StyledText: topIndex was " + topIndex - + ", isFixedLineHeight() = " + isFixedLineHeight() - + ", delta = " + delta - + ", content.getLineCount() = " + content.getLineCount() - + ", clientAreaHeight = " + clientAreaHeight - + ", oldTopIndex = " + oldTopIndex - + ", oldTopIndexY = " + oldTopIndexY - + ", getVerticalScrollOffset = " + getVerticalScrollOffset() - + ", oldDelta = " + oldDelta - + ", getVerticalIncrement() = " + getVerticalIncrement()); - topIndex = 0; - } - if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) { - int width = renderer.getWidth(); - renderer.calculateClientArea(); - if (width != renderer.getWidth()) { - setScrollBars(false); - } - } -} -/** - * Hides the scroll bars if widget is created in single line mode. - */ -static int checkStyle(int style) { - if ((style & SWT.SINGLE) != 0) { - style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI); - } else { - style |= SWT.MULTI; - if ((style & SWT.WRAP) != 0) { - style &= ~SWT.H_SCROLL; - } - } - style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND; - /* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */ - return style & ~SWT.CENTER; -} -/** - * Scrolls down the text to use new space made available by a resize or by - * deleted lines. - */ -void claimBottomFreeSpace() { - if (ime.getCompositionOffset() != -1) return; - if (isFixedLineHeight()) { - int newVerticalOffset = Math.max(0, renderer.getHeight() - clientAreaHeight); - if (newVerticalOffset < getVerticalScrollOffset()) { - scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true); - } - } else { - int bottomIndex = getPartialBottomIndex(); - int height = getLinePixel(bottomIndex + 1); - if (clientAreaHeight > height) { - scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true); - } - } -} -/** - * Scrolls text to the right to use new space made available by a resize. - */ -void claimRightFreeSpace() { - int newHorizontalOffset = Math.max(0, renderer.getWidth() - clientAreaWidth); - if (newHorizontalOffset < horizontalScrollOffset) { - // item is no longer drawn past the right border of the client area - // align the right end of the item with the right border of the - // client area (window is scrolled right). - scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); - } -} -void clearBlockSelection(boolean reset, boolean sendEvent) { - if (reset) resetSelection(); - blockXAnchor = blockYAnchor = -1; - blockXLocation = blockYLocation = -1; - caretDirection = SWT.NULL; - updateCaretVisibility(); - super.redraw(); - if (sendEvent) sendSelectionEvent(); -} -/** - * Removes the widget selection. - * - * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. - */ -void clearSelection(boolean sendEvent) { - int selectionStart = selection[0].x; - int selectionEnd = selection[0].y; - resetSelection(); - // redraw old selection, if any - if (selectionEnd - selectionStart > 0) { - int length = content.getCharCount(); - // called internally to remove selection after text is removed - // therefore make sure redraw range is valid. - int redrawStart = Math.min(selectionStart, length); - int redrawEnd = Math.min(selectionEnd, length); - if (redrawEnd - redrawStart > 0) { - internalRedrawRange(redrawStart, redrawEnd - redrawStart); - } - if (sendEvent) { - sendSelectionEvent(); - } - } -} -@Override -public Point computeSize (int wHint, int hHint, boolean changed) { - checkWidget(); - int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount(); - int width = 0; - int height = 0; - if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { - Display display = getDisplay(); - int maxHeight = display.getClientArea().height; - for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { - TextLayout layout = renderer.getTextLayout(lineIndex); - int wrapWidth = layout.getWidth(); - if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin)); - Rectangle rect = layout.getBounds(); - height += rect.height; - width = Math.max(width, rect.width); - layout.setWidth(wrapWidth); - renderer.disposeTextLayout(layout); - if (isFixedLineHeight() && height > maxHeight) break; - } - if (isFixedLineHeight()) { - height = lineCount * renderer.getLineHeight(); - } - } - // Use default values if no text is defined. - if (width == 0) width = DEFAULT_WIDTH; - if (height == 0) height = DEFAULT_HEIGHT; - if (wHint != SWT.DEFAULT) width = wHint; - if (hHint != SWT.DEFAULT) height = hHint; - int wTrim = getLeftMargin() + rightMargin + getCaretWidth(); - int hTrim = topMargin + bottomMargin; - Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim); - return new Point (rect.width, rect.height); -} -/** - * Copies the selected text to the DND.CLIPBOARD clipboard. - *

    - * The text will be put on the clipboard in plain text, HTML, and RTF formats. - * The DND.CLIPBOARD clipboard is used for data that is - * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or - * by menu action. - *

    - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void copy() { - checkWidget(); - copySelection(DND.CLIPBOARD); -} -/** - * Copies the selected text to the specified clipboard. The text will be put in the - * clipboard in plain text, HTML, and RTF formats. - *

    - * The clipboardType is one of the clipboard constants defined in class - * DND. The DND.CLIPBOARD clipboard is - * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) - * or by menu action. The DND.SELECTION_CLIPBOARD - * clipboard is used for data that is transferred by selecting text and pasting - * with the middle mouse button. - *

    - * - * @param clipboardType indicates the type of clipboard - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.1 - */ -public void copy(int clipboardType) { - checkWidget(); - copySelection(clipboardType); -} -boolean copySelection(int type) { - if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false; - try { - if (blockSelection && blockXLocation != -1) { - String text = getBlockSelectionText(PlatformLineDelimiter); - if (text.length() > 0) { - //TODO RTF support - TextTransfer plainTextTransfer = TextTransfer.getInstance(); - Object[] data = new Object[]{text}; - Transfer[] types = new Transfer[]{plainTextTransfer}; - clipboard.setContents(data, types, type); - return true; - } - } else if (getSelectionRanges().length > 2) { - StringBuilder text = new StringBuilder(); - int[] ranges = getSelectionRanges(); - for (int i = 0; i < ranges.length; i += 2) { - int offset = ranges[i]; - int length = ranges[i + 1]; - text.append(length == 0 ? "" : getText(offset, offset + length - 1)); - text.append(PlatformLineDelimiter); - } - text.delete(text.length() - PlatformLineDelimiter.length(), text.length()); - if (text.length() > 0) { - //TODO RTF support - clipboard.setContents(new Object[]{text.toString()}, new Transfer[]{TextTransfer.getInstance()}, type); - return true; - } - } else { - int length = selection[0].y - selection[0].x; - if (length > 0) { - setClipboardContent(selection[0].x, length, type); - return true; - } - } - } catch (SWTError error) { - // Copy to clipboard failed. This happens when another application - // is accessing the clipboard while we copy. Ignore the error. - // Rethrow all other errors. Fixes bug 17578. - if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { - throw error; - } - } - return false; -} -/** - * Returns the alignment of the widget. - * - * @return the alignment - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - *R - * @see #getLineAlignment(int) - * - * @since 3.2 - */ -public int getAlignment() { - checkWidget(); - return alignment; -} -/** - * Returns the Always Show Scrollbars flag. True if the scrollbars are - * always shown even if they are not required. False if the scrollbars are only - * visible when some part of the content needs to be scrolled to be seen. - * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the - * horizontal and vertical directions. - * - * @return the Always Show Scrollbars flag value - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.8 - */ -public boolean getAlwaysShowScrollBars() { - checkWidget(); - return alwaysShowScroll; -} -int getAvailableHeightAbove(int height) { - int maxHeight = verticalScrollOffset; - if (maxHeight == -1) { - int lineIndex = topIndex - 1; - maxHeight = -topIndexY; - if (topIndexY > 0) { - maxHeight += renderer.getLineHeight(lineIndex--); - } - while (height > maxHeight && lineIndex >= 0) { - maxHeight += renderer.getLineHeight(lineIndex--); - } - } - return Math.min(height, maxHeight); -} -int getAvailableHeightBellow(int height) { - int partialBottomIndex = getPartialBottomIndex(); - int topY = getLinePixel(partialBottomIndex); - int lineHeight = renderer.getLineHeight(partialBottomIndex); - int availableHeight = 0; - int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; - if (topY + lineHeight > clientAreaHeight) { - availableHeight = lineHeight - (clientAreaHeight - topY); - } - int lineIndex = partialBottomIndex + 1; - int lineCount = content.getLineCount(); - while (height > availableHeight && lineIndex < lineCount) { - availableHeight += renderer.getLineHeight(lineIndex++); - } - return Math.min(height, availableHeight); -} -/** - * Returns the color of the margins. - * - * @return the color of the margins. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public Color getMarginColor() { - checkWidget(); - return marginColor != null ? marginColor : getBackground(); -} -/** - * Returns a string that uses only the line delimiter specified by the - * StyledTextContent implementation. - *

    - * Returns only the first line if the widget has the SWT.SINGLE style. - *

    - * - * @param text the text that may have line delimiters that don't - * match the model line delimiter. Possible line delimiters - * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") - * @return the converted text that only uses the line delimiter - * specified by the model. Returns only the first line if the widget - * has the SWT.SINGLE style. - */ -String getModelDelimitedText(String text) { - int length = text.length(); - if (length == 0) { - return text; - } - int crIndex = 0; - int lfIndex = 0; - int i = 0; - StringBuilder convertedText = new StringBuilder(length); - String delimiter = getLineDelimiter(); - while (i < length) { - if (crIndex != -1) { - crIndex = text.indexOf(SWT.CR, i); - } - if (lfIndex != -1) { - lfIndex = text.indexOf(SWT.LF, i); - } - if (lfIndex == -1 && crIndex == -1) { // no more line breaks? - break; - } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { - convertedText.append(text.substring(i, crIndex)); - if (lfIndex == crIndex + 1) { // CR/LF combination? - i = lfIndex + 1; - } else { - i = crIndex + 1; - } - } else { // LF occurs before CR! - convertedText.append(text.substring(i, lfIndex)); - i = lfIndex + 1; - } - if (isSingleLine()) { - break; - } - convertedText.append(delimiter); - } - // copy remaining text if any and if not in single line mode or no - // text copied thus far (because there only is one line) - if (i < length && (!isSingleLine() || convertedText.length() == 0)) { - convertedText.append(text.substring(i)); - } - return convertedText.toString(); -} -boolean checkDragDetect(Event event) { - if (!isListening(SWT.DragDetect)) return false; - if (event.button != 1) return false; - if (blockSelection && blockXLocation != -1) { - Rectangle rect = getBlockSelectionRectangle(); - if (rect.contains(event.x, event.y)) { - return dragDetect(event); - } - } else { - if (selection[0].x == selection[0].y) return false; - int offset = getOffsetAtPoint(event.x, event.y, null, true); - if (selection[0].x <= offset && offset < selection[0].y) { - return dragDetect(event); - } - - } - return false; -} - -/** - * Creates default key bindings. - */ -void createKeyBindings() { - int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT; - int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT; - - // Navigation - setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); - setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); - if (IS_MAC) { - setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START); - setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END); - setKeyBinding(SWT.HOME, ST.TEXT_START); - setKeyBinding(SWT.END, ST.TEXT_END); - setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START); - setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END); - setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT); - setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS); - } else { - setKeyBinding(SWT.HOME, ST.LINE_START); - setKeyBinding(SWT.END, ST.LINE_END); - setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); - setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); - setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT); - setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS); - } - setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); - setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); - setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); - setKeyBinding(nextKey, ST.COLUMN_NEXT); - setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); - - // Selection - setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); - setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); - if (IS_MAC) { - setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START); - setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END); - setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START); - setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END); - setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); - setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); - setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT); - setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS); - } else { - setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); - setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); - setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); - setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); - setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); - setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); - } - setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); - setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); - setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT); - setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); - - // Modification - // Cut, Copy, Paste - setKeyBinding('X' | SWT.MOD1, ST.CUT); - setKeyBinding('C' | SWT.MOD1, ST.COPY); - setKeyBinding('V' | SWT.MOD1, ST.PASTE); - if (IS_MAC) { - setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT); - setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS); - setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT); - } else { - // Cut, Copy, Paste Wordstar style - setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); - setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); - setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); - } - setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); - setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); - setKeyBinding(SWT.DEL, ST.DELETE_NEXT); - setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS); - setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT); - - // Miscellaneous - setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); -} -/** - * Create the bitmaps to use for the caret in bidi mode. This - * method only needs to be called upon widget creation and when the - * font changes (the caret bitmap height needs to match font height). - */ -void createCaretBitmaps() { - int caretWidth = BIDI_CARET_WIDTH; - Display display = getDisplay(); - if (leftCaretBitmap != null) { - if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) { - defaultCaret.setImage(null); - } - leftCaretBitmap.dispose(); - } - int lineHeight = renderer.getLineHeight(); - leftCaretBitmap = new Image(display, caretWidth, lineHeight); - GC gc = new GC (leftCaretBitmap); - gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); - gc.fillRectangle(0, 0, caretWidth, lineHeight); - gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); - gc.drawLine(0,0,0,lineHeight); - gc.drawLine(0,0,caretWidth-1,0); - gc.drawLine(0,1,1,1); - gc.dispose(); - - if (rightCaretBitmap != null) { - if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) { - defaultCaret.setImage(null); - } - rightCaretBitmap.dispose(); - } - rightCaretBitmap = new Image(display, caretWidth, lineHeight); - gc = new GC (rightCaretBitmap); - gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); - gc.fillRectangle(0, 0, caretWidth, lineHeight); - gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); - gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); - gc.drawLine(0,0,caretWidth-1,0); - gc.drawLine(caretWidth-1,1,1,1); - gc.dispose(); -} -/** - * Moves the selected text to the clipboard. The text will be put in the - * clipboard in plain text, HTML, and RTF formats. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void cut() { - checkWidget(); - // Abort cut operation if copy to clipboard fails. - // Fixes bug 21030. - if (copySelection(DND.CLIPBOARD)) { - if (blockSelection && blockXLocation != -1) { - insertBlockSelectionText((char)0, SWT.NULL); - } else { - doDelete(); - } - } -} -/** - * A mouse move event has occurred. See if we should start autoscrolling. If - * the move position is outside of the client area, initiate autoscrolling. - * Otherwise, we've moved back into the widget so end autoscrolling. - */ -void doAutoScroll(Event event) { - int caretLine = getFirstCaretLine(); - if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) { - doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin)); - } else if (event.y < topMargin && caretLine != 0) { - doAutoScroll(SWT.UP, topMargin - event.y); - } else if (event.x < leftMargin && !wordWrap) { - doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x); - } else if (event.x > clientAreaWidth - rightMargin && !wordWrap) { - doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - rightMargin)); - } else { - endAutoScroll(); - } -} -/** - * Initiates autoscrolling. - * - * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS - */ -void doAutoScroll(int direction, int distance) { - autoScrollDistance = distance; - // If we're already autoscrolling in the given direction do nothing - if (autoScrollDirection == direction) { - return; - } - - Runnable timer = null; - final Display display = getDisplay(); - // Set a timer that will simulate the user pressing and holding - // down a cursor key (i.e., arrowUp, arrowDown). - if (direction == SWT.UP) { - timer = new Runnable() { - @Override - public void run() { - /* Bug 437357 - NPE in StyledText.getCaretLine - * StyledText.content is null at times, probably because the - * widget itself has been disposed. - */ - if (isDisposed()) return; - if (autoScrollDirection == SWT.UP) { - if (blockSelection) { - int verticalScrollOffset = getVerticalScrollOffset(); - int y = blockYLocation - verticalScrollOffset; - int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset); - if (pixels != 0) { - setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true); - scrollVertical(pixels, true); - } - } else { - doSelectionPageUp(autoScrollDistance); - } - display.timerExec(V_SCROLL_RATE, this); - } - } - }; - autoScrollDirection = direction; - display.timerExec(V_SCROLL_RATE, timer); - } else if (direction == SWT.DOWN) { - timer = new Runnable() { - @Override - public void run() { - /* Bug 437357 - NPE in StyledText.getCaretLine - * StyledText.content is null at times, probably because the - * widget itself has been disposed. - */ - if (isDisposed()) return; - if (autoScrollDirection == SWT.DOWN) { - if (blockSelection) { - int verticalScrollOffset = getVerticalScrollOffset(); - int y = blockYLocation - verticalScrollOffset; - int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight; - int pixels = Math.min(autoScrollDistance, Math.max(0,max)); - if (pixels != 0) { - setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true); - scrollVertical(pixels, true); - } - } else { - doSelectionPageDown(autoScrollDistance); - } - display.timerExec(V_SCROLL_RATE, this); - } - } - }; - autoScrollDirection = direction; - display.timerExec(V_SCROLL_RATE, timer); - } else if (direction == ST.COLUMN_NEXT) { - timer = new Runnable() { - @Override - public void run() { - /* Bug 437357 - NPE in StyledText.getCaretLine - * StyledText.content is null at times, probably because the - * widget itself has been disposed. - */ - if (isDisposed()) return; - if (autoScrollDirection == ST.COLUMN_NEXT) { - if (blockSelection) { - int x = blockXLocation - horizontalScrollOffset; - int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth; - int pixels = Math.min(autoScrollDistance, Math.max(0,max)); - if (pixels != 0) { - setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true); - scrollHorizontal(pixels, true); - } - } else { - doVisualNext(); - setMouseWordSelectionAnchor(); - doMouseSelection(); - } - display.timerExec(H_SCROLL_RATE, this); - } - } - }; - autoScrollDirection = direction; - display.timerExec(H_SCROLL_RATE, timer); - } else if (direction == ST.COLUMN_PREVIOUS) { - timer = new Runnable() { - @Override - public void run() { - /* Bug 437357 - NPE in StyledText.getCaretLine - * StyledText.content is null at times, probably because the - * widget itself has been disposed. - */ - if (isDisposed()) return; - if (autoScrollDirection == ST.COLUMN_PREVIOUS) { - if (blockSelection) { - int x = blockXLocation - horizontalScrollOffset; - int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset); - if (pixels != 0) { - setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true); - scrollHorizontal(pixels, true); - } - } else { - doVisualPrevious(); - setMouseWordSelectionAnchor(); - doMouseSelection(); - } - display.timerExec(H_SCROLL_RATE, this); - } - } - }; - autoScrollDirection = direction; - display.timerExec(H_SCROLL_RATE, timer); - } -} -/** - * Deletes the previous character. Delete the selected text if any. - * Move the caret in front of the deleted text. - */ -void doBackspace() { - Event event = new Event(); - event.text = ""; - if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { // at least one range to delete - for (int i = selection.length - 1; i >= 0; i--) { // from bottom to top to avoid moving ranges - Point sel = selection[i]; - event.start = sel.x; - event.end = sel.y; - sendKeyEvent(event); - } - } else { - for (int i = caretOffsets.length - 1; i >= 0; i--) { // reverse loop, process from bottom to top - int caretOffset = caretOffsets[i]; - if (caretOffset > 0) { - int lineIndex = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(lineIndex); - if (caretOffset == lineOffset) { - lineOffset = content.getOffsetAtLine(lineIndex - 1); - event.start = lineOffset + content.getLine(lineIndex - 1).length(); - event.end = caretOffset; - } else { - boolean isSurrogate = false; - String lineText = content.getLine(lineIndex); - char ch = lineText.charAt(caretOffset - lineOffset - 1); - if (0xDC00 <= ch && ch <= 0xDFFF) { - if (caretOffset - lineOffset - 2 >= 0) { - ch = lineText.charAt(caretOffset - lineOffset - 2); - isSurrogate = 0xD800 <= ch && ch <= 0xDBFF; - } - } - TextLayout layout = renderer.getTextLayout(lineIndex); - int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR); - renderer.disposeTextLayout(layout); - event.start = start + lineOffset; - event.end = caretOffset; - } - sendKeyEvent(event); - } - } - } -} -void doBlockColumn(boolean next) { - if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); - int x = blockXLocation - horizontalScrollOffset; - int y = blockYLocation - getVerticalScrollOffset(); - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(x, y, trailing, true); - if (offset != -1) { - offset += trailing[0]; - int lineIndex = content.getLineAtOffset(offset); - int newOffset; - if (next) { - newOffset = getClusterNext(offset, lineIndex); - } else { - newOffset = getClusterPrevious(offset, lineIndex); - } - offset = newOffset != offset ? newOffset : -1; - } - if (offset != -1) { - setBlockSelectionOffset(offset, true); - showCaret(); - } else { - int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth; - int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); - x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset; - setBlockSelectionLocation(x, y, true); - Rectangle rect = new Rectangle(x, y, 0, 0); - showLocation(rect, true); - } -} -void doBlockContentStartEnd(boolean end) { - if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); - int offset = end ? content.getCharCount() : 0; - setBlockSelectionOffset(offset, true); - showCaret(); -} -void doBlockWord(boolean next) { - if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); - int x = blockXLocation - horizontalScrollOffset; - int y = blockYLocation - getVerticalScrollOffset(); - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(x, y, trailing, true); - if (offset != -1) { - offset += trailing[0]; - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - String lineText = content.getLine(lineIndex); - int lineLength = lineText.length(); - int newOffset = offset; - if (next) { - if (offset < lineOffset + lineLength) { - newOffset = getWordNext(offset, SWT.MOVEMENT_WORD); - } - } else { - if (offset > lineOffset) { - newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD); - } - } - offset = newOffset != offset ? newOffset : -1; - } - if (offset != -1) { - setBlockSelectionOffset(offset, true); - showCaret(); - } else { - int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6; - int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); - x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset; - setBlockSelectionLocation(x, y, true); - Rectangle rect = new Rectangle(x, y, 0, 0); - showLocation(rect, true); - } -} -void doBlockLineVertical(boolean up) { - if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); - int y = blockYLocation - getVerticalScrollOffset(); - int lineIndex = getLineIndex(y); - if (up) { - if (lineIndex > 0) { - y = getLinePixel(lineIndex - 1); - setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true); - if (y < topMargin) { - scrollVertical(y - topMargin, true); - } - } - } else { - int lineCount = content.getLineCount(); - if (lineIndex + 1 < lineCount) { - y = getLinePixel(lineIndex + 2) - 1; - setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true); - int bottom = clientAreaHeight - bottomMargin; - if (y > bottom) { - scrollVertical(y - bottom, true); - } - } - } -} -void doBlockLineHorizontal(boolean end) { - if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); - int x = blockXLocation - horizontalScrollOffset; - int y = blockYLocation - getVerticalScrollOffset(); - int lineIndex = getLineIndex(y); - int lineOffset = content.getOffsetAtLine(lineIndex); - String lineText = content.getLine(lineIndex); - int lineLength = lineText.length(); - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(x, y, trailing, true); - if (offset != -1) { - offset += trailing[0]; - int newOffset = offset; - if (end) { - if (offset < lineOffset + lineLength) { - newOffset = lineOffset + lineLength; - } - } else { - if (offset > lineOffset) { - newOffset = lineOffset; - } - } - offset = newOffset != offset ? newOffset : -1; - } else { - if (!end) offset = lineOffset + lineLength; - } - if (offset != -1) { - setBlockSelectionOffset(offset, true); - showCaret(); - } else { - int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); - x = (end ? maxWidth : 0) - horizontalScrollOffset; - setBlockSelectionLocation(x, y, true); - Rectangle rect = new Rectangle(x, y, 0, 0); - showLocation(rect, true); - } -} -void doBlockSelection(boolean sendEvent) { - if (caretOffsets[0] > selectionAnchors[0]) { - selection[0].x = selectionAnchors[0]; - selection[0].y = caretOffsets[0]; - } else { - selection[0].x = caretOffsets[0]; - selection[0].y = selectionAnchors[0]; - } - updateCaretVisibility(); - setCaretLocations(); - super.redraw(); - if (sendEvent) { - sendSelectionEvent(); - } - sendAccessibleTextCaretMoved(); -} -/** - * Replaces the selection with the character or insert the character at the - * current caret position if no selection exists. - *

    - * If a carriage return was typed replace it with the line break character - * used by the widget on this platform. - *

    - * - * @param key the character typed by the user - */ -void doContent(final char key) { - if (blockSelection && blockXLocation != -1) { - insertBlockSelectionText(key, SWT.NULL); - return; - } - - for (int i = selection.length - 1; i >= 0; i--) { - Point sel = selection[i]; - Event event = new Event(); - event.start = sel.x; - event.end = sel.y; - // replace a CR line break with the widget line break - // CR does not make sense on Windows since most (all?) applications - // don't recognize CR as a line break. - if (key == SWT.CR || key == SWT.LF) { - if (!isSingleLine()) { - event.text = getLineDelimiter(); - } - } else if (sel.x == sel.y && overwrite && key != TAB) { - // no selection and overwrite mode is on and the typed key is not a - // tab character (tabs are always inserted without overwriting)? - int lineIndex = content.getLineAtOffset(event.end); - int lineOffset = content.getOffsetAtLine(lineIndex); - String line = content.getLine(lineIndex); - // replace character at caret offset if the caret is not at the - // end of the line - if (event.end < lineOffset + line.length()) { - event.end++; - } - event.text = new String(new char[] {key}); - } else { - event.text = new String(new char[] {key}); - } - if (event.text != null) { - if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { - return; - } - sendKeyEvent(event); - } - } -} -/** - * Moves the caret after the last character of the widget content. - */ -void doContentEnd() { - // place caret at end of first line if receiver is in single - // line mode. fixes 4820. - if (isSingleLine()) { - doLineEnd(); - } else { - int length = content.getCharCount(); - setCaretOffsets(new int[] {length}, SWT.DEFAULT); - showCaret(); - } -} -/** - * Moves the caret in front of the first character of the widget content. - */ -void doContentStart() { - setCaretOffsets(new int[] {0}, SWT.DEFAULT); - showCaret(); -} -/** - * Moves the caret to the start of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the - * cursor selection rules. - * - * @see #doSelectionCursorPrevious - */ -void doCursorPrevious() { - if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { - setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), OFFSET_LEADING); - showCaret(); - } else { - doSelectionCursorPrevious(); - } -} -/** - * Moves the caret to the end of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the - * cursor selection rules. - * - * @see #doSelectionCursorNext - */ -void doCursorNext() { - if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { - setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), PREVIOUS_OFFSET_TRAILING); - showCaret(); - } else { - doSelectionCursorNext(); - } -} -/** - * Deletes the next character. Delete the selected text if any. - */ -void doDelete() { - Event event = new Event(); - event.text = ""; - if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { - for (Point sel : selection) { - event.start = sel.x; - event.end = sel.y; - sendKeyEvent(event); - } - } else { - for (int i = caretOffsets.length - 1; i >= 0; i--) { - int caretOffset = caretOffsets[i]; - if (caretOffset < content.getCharCount()) { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - int lineLength = content.getLine(line).length(); - if (caretOffset == lineOffset + lineLength) { - event.start = caretOffset; - event.end = content.getOffsetAtLine(line + 1); - } else { - event.start = caretOffset; - event.end = getClusterNext(caretOffset, line); - } - sendKeyEvent(event); - } - } - } -} -/** - * Deletes the next word. - */ -void doDeleteWordNext() { - if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { - // if a selection exists, treat the as if - // only the delete key was pressed - doDelete(); - } else { - for (int i = caretOffsets.length - 1; i >= 0; i--) { - int caretOffset = caretOffsets[i]; - Event event = new Event(); - event.text = ""; - event.start = caretOffset; - event.end = getWordNext(caretOffset, SWT.MOVEMENT_WORD); - sendKeyEvent(event); - } - } -} -/** - * Deletes the previous word. - */ -void doDeleteWordPrevious() { - if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { - // if a selection exists, treat as if - // only the backspace key was pressed - doBackspace(); - } else { - for (int i = caretOffsets.length - 1; i >= 0; i--) { - int caretOffset = caretOffsets[i]; - Event event = new Event(); - event.text = ""; - event.start = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD); - event.end = caretOffset; - sendKeyEvent(event); - } - } -} -/** - * Moves the caret one line down and to the same character offset relative - * to the beginning of the line. Move the caret to the end of the new line - * if the new line is shorter than the character offset. Moves the caret to - * the end of the text if the caret already is on the last line. - */ -void doLineDown(boolean select) { - int[] newCaretOffsets = new int[caretOffsets.length]; - int lineCount = content.getLineCount(); - int[] alignment = new int[1]; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x; - int y = 0; - boolean lastLine = false; - if (isWordWrap()) { - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - TextLayout layout = renderer.getTextLayout(caretLine); - int lineIndex = getVisualLineIndex(layout, offsetInLine); - int layoutLineCount = layout.getLineCount(); - if (lineIndex == layoutLineCount - 1) { - lastLine = caretLine == lineCount - 1; - caretLine++; - } else { - y = layout.getLineBounds(lineIndex + 1).y; - y++; // bug 485722: workaround for fractional line heights - } - renderer.disposeTextLayout(layout); - } else { - lastLine = caretLine == lineCount - 1; - caretLine++; - } - if (lastLine) { - newCaretOffsets[i] = content.getCharCount(); - } else { - newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment); - } - } - boolean hitLastLine = content.getLineAtOffset(newCaretOffsets[newCaretOffsets.length - 1]) == lineCount - 1; - setCaretOffsets(newCaretOffsets, hitLastLine ? SWT.DEFAULT : alignment[0]); - int oldColumnX = columnX; - int oldHScrollOffset = horizontalScrollOffset; - if (select) { - setMouseWordSelectionAnchor(); - // select first and then scroll to reduce flash when key - // repeat scrolls lots of lines - doSelection(ST.COLUMN_NEXT); - } - showCaret(); - int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; -} -/** - * Moves the caret to the end of the line. - */ -void doLineEnd() { - int[] newOffsets = new int[caretOffsets.length]; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(caretLine); - int lineEndOffset; - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(caretLine); - int offsetInLine = caretOffset - lineOffset; - int lineIndex = getVisualLineIndex(layout, offsetInLine); - int[] offsets = layout.getLineOffsets(); - lineEndOffset = lineOffset + offsets[lineIndex + 1]; - renderer.disposeTextLayout(layout); - } else { - int lineLength = content.getLine(caretLine).length(); - lineEndOffset = lineOffset + lineLength; - } - newOffsets[i] = lineEndOffset; - } - setCaretOffsets(newOffsets, PREVIOUS_OFFSET_TRAILING); - showCaret(); -} -/** - * Moves the caret to the beginning of the line. - */ -void doLineStart() { - int[] newCaretOffsets = new int[caretOffsets.length]; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(caretLine); - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(caretLine); - int offsetInLine = caretOffset - lineOffset; - int lineIndex = getVisualLineIndex(layout, offsetInLine); - int[] offsets = layout.getLineOffsets(); - lineOffset += offsets[lineIndex]; - renderer.disposeTextLayout(layout); - } - newCaretOffsets[i] = lineOffset; - } - setCaretOffsets(newCaretOffsets, OFFSET_LEADING); - showCaret(); -} -/** - * Moves the caret one line up and to the same character offset relative - * to the beginning of the line. Move the caret to the end of the new line - * if the new line is shorter than the character offset. Moves the caret to - * the beginning of the document if it is already on the first line. - */ -void doLineUp(boolean select) { - int[] newCaretOffsets = new int[caretOffsets.length]; - int[] alignment = new int[1]; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x; - int y = 0; - boolean firstLine = false; - if (isWordWrap()) { - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - TextLayout layout = renderer.getTextLayout(caretLine); - int lineIndex = getVisualLineIndex(layout, offsetInLine); - if (lineIndex == 0) { - firstLine = caretLine == 0; - if (!firstLine) { - caretLine--; - y = renderer.getLineHeight(caretLine) - 1; - y--; // bug 485722: workaround for fractional line heights - } - } else { - y = layout.getLineBounds(lineIndex - 1).y; - y++; // bug 485722: workaround for fractional line heights - } - renderer.disposeTextLayout(layout); - } else { - firstLine = caretLine == 0; - caretLine--; - } - if (firstLine) { - newCaretOffsets[i] = 0; - } else { - newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment); - } - } - setCaretOffsets(newCaretOffsets, newCaretOffsets[0] == 0 ? SWT.DEFAULT : alignment[0]); - int oldColumnX = columnX; - int oldHScrollOffset = horizontalScrollOffset; - if (select) setMouseWordSelectionAnchor(); - showCaret(); - if (select) doSelection(ST.COLUMN_PREVIOUS); - int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; -} -void doMouseLinkCursor() { - Display display = getDisplay(); - Point point = display.getCursorLocation(); - point = display.map(null, this, point); - doMouseLinkCursor(point.x, point.y); -} -void doMouseLinkCursor(int x, int y) { - int offset = getOffsetAtPoint(x, y, null, true); - Display display = getDisplay(); - Cursor newCursor = cursor; - if (renderer.hasLink(offset)) { - newCursor = display.getSystemCursor(SWT.CURSOR_HAND); - } else { - if (cursor == null) { - int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; - newCursor = display.getSystemCursor(type); - } - } - if (newCursor != getCursor()) super.setCursor(newCursor); -} -/** - * Moves the caret to the specified location. - * - * @param x x location of the new caret position - * @param y y location of the new caret position - * @param select the location change is a selection operation. - * include the line delimiter in the selection - */ -void doMouseLocationChange(int x, int y, boolean select) { - int line = getLineIndex(y); - - updateCaretDirection = true; - - if (blockSelection) { - x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin)); - y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin)); - if (doubleClickEnabled && clickCount > 1) { - boolean wordSelect = (clickCount & 1) == 0; - if (wordSelect) { - Point left = getPointAtOffset(doubleClickSelection.x); - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(x, y, trailing, true); - if (offset != -1) { - if (x > left.x) { - offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END); - setBlockSelectionOffset(doubleClickSelection.x, offset, true); - } else { - offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START); - setBlockSelectionOffset(doubleClickSelection.y, offset, true); - } - } else { - if (x > left.x) { - setBlockSelectionLocation(left.x, left.y, x, y, true); - } else { - Point right = getPointAtOffset(doubleClickSelection.y); - setBlockSelectionLocation(right.x, right.y, x, y, true); - } - } - } else { - setBlockSelectionLocation(blockXLocation, y, true); - } - return; - } else { - if (select) { - if (blockXLocation == -1) { - setBlockSelectionOffset(caretOffsets[0], false); - } - } else { - clearBlockSelection(true, false); - } - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(x, y, trailing, true); - if (offset != -1) { - if (select) { - setBlockSelectionOffset(offset + trailing[0], true); - return; - } - } else { - if (isFixedLineHeight() && renderer.fixedPitch) { - int avg = renderer.averageCharWidth; - x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; - } - setBlockSelectionLocation(x, y, true); - return; - } - } - } - - // allow caret to be placed below first line only if receiver is - // not in single line mode. fixes 4820. - if (line < 0 || (isSingleLine() && line > 0)) { - return; - } - int[] alignment = new int[1]; - int newCaretOffset = getOffsetAtPoint(x, y, alignment); - int newCaretAlignemnt = alignment[0]; - - if (doubleClickEnabled && clickCount > 1) { - newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); - } - - int newCaretLine = content.getLineAtOffset(newCaretOffset); - - // Is the mouse within the left client area border or on - // a different line? If not the autoscroll selection - // could be incorrectly reset. Fixes 1GKM3XS - boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1; - boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffsets[0]); - if (vchange && hchange && (newCaretOffset != caretOffsets[0] || newCaretAlignemnt != caretAlignment)) { - setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt); - if (select) doMouseSelection(); - showCaret(); - } - if (!select) { - setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt); - clearSelection(true); - } -} -/** - * Updates the selection based on the caret position - */ -void doMouseSelection() { - if (caretOffsets[0] <= selection[0].x || - (caretOffsets[0] > selection[0].x && - caretOffsets[0] < selection[0].y && selectionAnchors[0] == selection[0].x)) { - doSelection(ST.COLUMN_PREVIOUS); - } else { - doSelection(ST.COLUMN_NEXT); - } -} -/** - * Returns the offset of the word at the specified offset. - * If the current selection extends from high index to low index - * (i.e., right to left, or caret is at left border of selection on - * non-bidi platforms) the start offset of the word preceding the - * selection is returned. If the current selection extends from - * low index to high index the end offset of the word following - * the selection is returned. - * - * @param x mouse x location - * @param newCaretOffset caret offset of the mouse cursor location - * @param line line index of the mouse cursor location - */ -int doMouseWordSelect(int x, int newCaretOffset, int line) { - // flip selection anchor based on word selection direction from - // base double click. Always do this here (and don't rely on doAutoScroll) - // because auto scroll only does not cover all possible mouse selections - // (e.g., mouse x < 0 && mouse y > caret line y) - if (newCaretOffset < selectionAnchors[0] && selectionAnchors[0] == selection[0].x) { - selectionAnchors[0] = doubleClickSelection.y; - } else if (newCaretOffset > selectionAnchors[0] && selectionAnchors[0] == selection[0].y) { - selectionAnchors[0] = doubleClickSelection.x; - } - if (0 <= x && x < clientAreaWidth) { - boolean wordSelect = (clickCount & 1) == 0; - if (caretOffsets[0] == selection[0].x) { - if (wordSelect) { - newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START); - } else { - newCaretOffset = content.getOffsetAtLine(line); - } - } else { - if (wordSelect) { - newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END); - } else { - int lineEnd = content.getCharCount(); - if (line + 1 < content.getLineCount()) { - lineEnd = content.getOffsetAtLine(line + 1); - } - newCaretOffset = lineEnd; - } - } - } - return newCaretOffset; -} -/** - * Scrolls one page down so that the last line (truncated or whole) - * of the current page becomes the fully visible top line. - *

    - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the end - * of the text where a full page scroll is not possible. In this case - * the caret is moved after the last character. - *

    - * - * @param select whether or not to select the page - */ -void doPageDown(boolean select, int height) { - if (isSingleLine()) return; - int oldColumnX = columnX; - int oldHScrollOffset = horizontalScrollOffset; - if (isFixedLineHeight()) { - int lineCount = content.getLineCount(); - int caretLine = getFirstCaretLine(); - if (caretLine < lineCount - 1) { - int lineHeight = renderer.getLineHeight(); - int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; - int scrollLines = Math.min(lineCount - caretLine - 1, lines); - // ensure that scrollLines never gets negative and at least one - // line is scrolled. fixes bug 5602. - scrollLines = Math.max(1, scrollLines); - int[] alignment = new int[1]; - int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment); - setCaretOffsets(new int[] {offset}, alignment[0]); - if (select) { - doSelection(ST.COLUMN_NEXT); - } - // scroll one page down or to the bottom - int verticalMaximum = lineCount * getVerticalIncrement(); - int pageSize = clientAreaHeight; - int verticalScrollOffset = getVerticalScrollOffset(); - int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); - if (scrollOffset + pageSize > verticalMaximum) { - scrollOffset = verticalMaximum - pageSize; - } - if (scrollOffset > verticalScrollOffset) { - scrollVertical(scrollOffset - verticalScrollOffset, true); - } - } - } else { - int lineCount = content.getLineCount(); - int lineIndex, lineHeight; - if (height == -1) { - lineIndex = getPartialBottomIndex(); - int topY = getLinePixel(lineIndex); - lineHeight = renderer.getLineHeight(lineIndex); - height = topY; - if (topY + lineHeight <= clientAreaHeight) { - height += lineHeight; - } else { - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(lineIndex); - int y = clientAreaHeight - topY; - for (int i = 0; i < layout.getLineCount(); i++) { - Rectangle bounds = layout.getLineBounds(i); - if (bounds.contains(bounds.x, y)) { - height += bounds.y; - break; - } - } - renderer.disposeTextLayout(layout); - } - } - } else { - lineIndex = getLineIndex(height); - int topLineY = getLinePixel(lineIndex); - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(lineIndex); - int y = height - topLineY; - for (int i = 0; i < layout.getLineCount(); i++) { - Rectangle bounds = layout.getLineBounds(i); - if (bounds.contains(bounds.x, y)) { - height = topLineY + bounds.y + bounds.height; - break; - } - } - renderer.disposeTextLayout(layout); - } else { - height = topLineY + renderer.getLineHeight(lineIndex); - } - } - int caretHeight = height; - if (isWordWrap()) { - for (int caretOffset : caretOffsets) { - int caretLine = content.getLineAtOffset(caretOffset); - TextLayout layout = renderer.getTextLayout(caretLine); - int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); - lineIndex = getVisualLineIndex(layout, offsetInLine); - caretHeight += layout.getLineBounds(lineIndex).y; - renderer.disposeTextLayout(layout); - } - } - lineIndex = getFirstCaretLine(); - lineHeight = renderer.getLineHeight(lineIndex); - while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) { - caretHeight -= lineHeight; - lineHeight = renderer.getLineHeight(++lineIndex); - } - int[] alignment = new int[1]; - int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment); - setCaretOffsets(new int[] {offset}, alignment[0]); - if (select) doSelection(ST.COLUMN_NEXT); - height = getAvailableHeightBellow(height); - scrollVertical(height, true); - if (height == 0) setCaretLocations(); - } - showCaret(); - int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; -} -/** - * Moves the cursor to the end of the last fully visible line. - */ -void doPageEnd() { - // go to end of line if in single line mode. fixes 5673 - if (isSingleLine()) { - doLineEnd(); - } else if (caretOffsets.length == 1) { // pageEnd doesn't make sense with multi-carets - int bottomOffset; - if (isWordWrap()) { - int lineIndex = getPartialBottomIndex(); - TextLayout layout = renderer.getTextLayout(lineIndex); - int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex); - int index = layout.getLineCount() - 1; - while (index >= 0) { - Rectangle bounds = layout.getLineBounds(index); - if (y >= bounds.y + bounds.height) break; - index--; - } - if (index == -1 && lineIndex > 0) { - bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); - } else { - bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); - } - renderer.disposeTextLayout(layout); - } else { - int lineIndex = getBottomIndex(); - bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length(); - } - if (caretOffsets[0] < bottomOffset) { - setCaretOffsets(new int[] {bottomOffset}, OFFSET_LEADING); - showCaret(); - } - } -} -/** - * Moves the cursor to the beginning of the first fully visible line. - */ -void doPageStart() { - int topOffset; - if (isWordWrap()) { - int y, lineIndex; - if (topIndexY > 0) { - lineIndex = topIndex - 1; - y = renderer.getLineHeight(lineIndex) - topIndexY; - } else { - lineIndex = topIndex; - y = -topIndexY; - } - TextLayout layout = renderer.getTextLayout(lineIndex); - int index = 0; - int lineCount = layout.getLineCount(); - while (index < lineCount) { - Rectangle bounds = layout.getLineBounds(index); - if (y <= bounds.y) break; - index++; - } - if (index == lineCount) { - topOffset = content.getOffsetAtLine(lineIndex + 1); - } else { - topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; - } - renderer.disposeTextLayout(layout); - } else { - topOffset = content.getOffsetAtLine(topIndex); - } - if (caretOffsets[0] > topOffset) { - setCaretOffsets(new int[] {topOffset}, OFFSET_LEADING); - showCaret(); - } -} -/** - * Scrolls one page up so that the first line (truncated or whole) - * of the current page becomes the fully visible last line. - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the beginning - * of the text where a full page scroll is not possible. In this case the - * caret is moved in front of the first character. - */ -void doPageUp(boolean select, int height) { - if (isSingleLine()) return; - int oldHScrollOffset = horizontalScrollOffset; - int oldColumnX = columnX; - if (isFixedLineHeight()) { - int caretLine = getFirstCaretLine(); - if (caretLine > 0) { - int lineHeight = renderer.getLineHeight(); - int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; - int scrollLines = Math.max(1, Math.min(caretLine, lines)); - caretLine -= scrollLines; - int[] alignment = new int[1]; - int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment); - setCaretOffsets(new int[] {offset}, alignment[0]); - if (select) { - doSelection(ST.COLUMN_PREVIOUS); - } - int verticalScrollOffset = getVerticalScrollOffset(); - int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); - if (scrollOffset < verticalScrollOffset) { - scrollVertical(scrollOffset - verticalScrollOffset, true); - } - } - } else { - int lineHeight, lineIndex; - if (height == -1) { - if (topIndexY == 0) { - height = clientAreaHeight; - } else { - int y; - if (topIndex > 0) { - lineIndex = topIndex - 1; - lineHeight = renderer.getLineHeight(lineIndex); - height = clientAreaHeight - topIndexY; - y = lineHeight - topIndexY; - } else { - lineIndex = topIndex; - lineHeight = renderer.getLineHeight(lineIndex); - height = clientAreaHeight - (lineHeight + topIndexY); - y = -topIndexY; - } - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(lineIndex); - for (int i = 0; i < layout.getLineCount(); i++) { - Rectangle bounds = layout.getLineBounds(i); - if (bounds.contains(bounds.x, y)) { - height += lineHeight - (bounds.y + bounds.height); - break; - } - } - renderer.disposeTextLayout(layout); - } - } - } else { - lineIndex = getLineIndex(clientAreaHeight - height); - int topLineY = getLinePixel(lineIndex); - if (isWordWrap()) { - TextLayout layout = renderer.getTextLayout(lineIndex); - int y = topLineY; - for (int i = 0; i < layout.getLineCount(); i++) { - Rectangle bounds = layout.getLineBounds(i); - if (bounds.contains(bounds.x, y)) { - height = clientAreaHeight - (topLineY + bounds.y); - break; - } - } - renderer.disposeTextLayout(layout); - } else { - height = clientAreaHeight - topLineY; - } - } - int caretHeight = height; - if (isWordWrap()) { - for (int caretOffset : caretOffsets) { - int caretLine = content.getLineAtOffset(caretOffset); - TextLayout layout = renderer.getTextLayout(caretLine); - int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); - lineIndex = getVisualLineIndex(layout, offsetInLine); - caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y; - renderer.disposeTextLayout(layout); - } - } - lineIndex = getFirstCaretLine(); - lineHeight = renderer.getLineHeight(lineIndex); - while (caretHeight - lineHeight >= 0 && lineIndex > 0) { - caretHeight -= lineHeight; - lineHeight = renderer.getLineHeight(--lineIndex); - } - lineHeight = renderer.getLineHeight(lineIndex); - int[] alignment = new int[1]; - int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment); - setCaretOffsets(new int[] {offset}, alignment[0]); - if (select) doSelection(ST.COLUMN_PREVIOUS); - height = getAvailableHeightAbove(height); - scrollVertical(-height, true); - if (height == 0) setCaretLocations(); - } - showCaret(); - int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; -} -/** - * Updates the selection to extend to the current caret position. - */ -void doSelection(int direction) { - if (caretOffsets.length != selection.length) { - return; - } - if (selectionAnchors.length != selection.length) { - selectionAnchors = new int[selection.length]; - Arrays.fill(selectionAnchors, -1); - } - boolean selectionChanged = false; - Point[] newSelection = Arrays.stream(selection).map(p -> new Point(p.x, p.y)).toArray(Point[]::new); - boolean[] caretAtBeginning = new boolean[newSelection.length]; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - Point currentSelection = newSelection[i]; - int selectionAnchor = selectionAnchors[i]; - if (selectionAnchor == -1) { - selectionAnchor = selectionAnchors[i] = currentSelection.x; - } - int redrawStart = -1; - int redrawEnd = -1; - if (direction == ST.COLUMN_PREVIOUS) { - if (caretOffset < currentSelection.x) { - caretAtBeginning[i] = true; - // grow selection - redrawEnd = currentSelection.x; - redrawStart = currentSelection.x = caretOffset; - // check if selection has reversed direction - if (currentSelection.y != selectionAnchor) { - redrawEnd = currentSelection.y; - currentSelection.y = selectionAnchor; - } - // test whether selection actually changed. Fixes 1G71EO1 - } else if (selectionAnchor == currentSelection.x && caretOffset < currentSelection.y) { - // caret moved towards selection anchor (left side of selection). - // shrink selection - redrawEnd = currentSelection.y; - redrawStart = currentSelection.y = caretOffset; - } - } else { - if (caretOffset > currentSelection.y) { - // grow selection - redrawStart = currentSelection.y; - redrawEnd = currentSelection.y = caretOffset; - // check if selection has reversed direction - if (currentSelection.x != selectionAnchor) { - redrawStart = currentSelection.x; - currentSelection.x = selectionAnchor; - } - // test whether selection actually changed. Fixes 1G71EO1 - } else if (selectionAnchor == currentSelection.y && caretOffset > currentSelection.x) { - // caret moved towards selection anchor (right side of selection). - // shrink selection - caretAtBeginning[i] = true; - redrawStart = currentSelection.x; - redrawEnd = currentSelection.x = caretOffset; - } - } - if (redrawStart != -1 && redrawEnd != -1) { - internalRedrawRange(redrawStart, redrawEnd - redrawStart); - selectionChanged = true; - } - } - if (selectionChanged) { - int[] regions = new int[newSelection.length * 2]; - for (int i = 0; i < newSelection.length; i++) { - Point p = newSelection[i]; - if (caretAtBeginning[i]) { - regions[2 * i] = p.y; - regions[2 * i + 1] = p.x - p.y; - } else { - regions[2 * i] = p.x; - regions[2 * i + 1] = p.y - p.x; - } - } - setSelection(regions, false, blockSelection); - sendSelectionEvent(); - } - sendAccessibleTextCaretMoved(); -} -/** - * Moves the caret to the next character or to the beginning of the - * next line if the cursor is at the end of a line. - */ -void doSelectionCursorNext() { - int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length); - int newAlignment = Integer.MIN_VALUE; - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - int offset; - if (offsetInLine < content.getLine(caretLine).length()) { - TextLayout layout = renderer.getTextLayout(caretLine); - offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); - int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; - renderer.disposeTextLayout(layout); - offset = offsetInLine + lineOffset; - newAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; - newCarets[i] = offset; - } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { - caretLine++; - offset = content.getOffsetAtLine(caretLine); - newAlignment = PREVIOUS_OFFSET_TRAILING; - newCarets[i] = offset; - } - } - if (newAlignment > Integer.MIN_VALUE) { - setCaretOffsets(newCarets, newAlignment); - showCaret(); - } -} -/** - * Moves the caret to the previous character or to the end of the previous - * line if the cursor is at the beginning of a line. - */ -void doSelectionCursorPrevious() { - int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length); - for (int i = 0; i < caretOffsets.length; i++) { - int caretOffset = caretOffsets[i]; - int caretLine = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - if (offsetInLine > 0) { - newCarets[i] = getClusterPrevious(caretOffset, caretLine); - } else if (caretLine > 0) { - caretLine--; - lineOffset = content.getOffsetAtLine(caretLine); - newCarets[i] = lineOffset + content.getLine(caretLine).length(); - } - } - if (!Arrays.equals(caretOffsets, newCarets)) { - setCaretOffsets(newCarets, OFFSET_LEADING); - showCaret(); - } -} -/** - * Moves the caret one line down and to the same character offset relative - * to the beginning of the line. Moves the caret to the end of the new line - * if the new line is shorter than the character offset. - * Moves the caret to the end of the text if the caret already is on the - * last line. - * Adjusts the selection according to the caret change. This can either add - * to or subtract from the old selection, depending on the previous selection - * direction. - */ -void doSelectionLineDown() { - int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; - doLineDown(true); - columnX = oldColumnX; -} -/** - * Moves the caret one line up and to the same character offset relative - * to the beginning of the line. Moves the caret to the end of the new line - * if the new line is shorter than the character offset. - * Moves the caret to the beginning of the document if it is already on the - * first line. - * Adjusts the selection according to the caret change. This can either add - * to or subtract from the old selection, depending on the previous selection - * direction. - */ -void doSelectionLineUp() { - int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; - doLineUp(true); - columnX = oldColumnX; -} -/** - * Scrolls one page down so that the last line (truncated or whole) - * of the current page becomes the fully visible top line. - *

    - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the end - * of the text where a full page scroll is not possible. In this case - * the caret is moved after the last character. - *

    - * Adjusts the selection according to the caret change. This can either add - * to or subtract from the old selection, depending on the previous selection - * direction. - *

    - */ -void doSelectionPageDown(int pixels) { - int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; - doPageDown(true, pixels); - columnX = oldColumnX; -} -/** - * Scrolls one page up so that the first line (truncated or whole) - * of the current page becomes the fully visible last line. - *

    - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the beginning - * of the text where a full page scroll is not possible. In this case the - * caret is moved in front of the first character. - *

    - * Adjusts the selection according to the caret change. This can either add - * to or subtract from the old selection, depending on the previous selection - * direction. - *

    - */ -void doSelectionPageUp(int pixels) { - if (caretOffsets.length > 1) { // operation doesn't make sense for multi-carets - return; - } - int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; - doPageUp(true, pixels); - columnX = oldColumnX; -} -/** - * Moves the caret to the end of the next word . - */ -void doSelectionWordNext() { - int[] offsets = Arrays.stream(caretOffsets).map(offset -> getWordNext(offset, SWT.MOVEMENT_WORD)).toArray(); - // don't change caret position if in single line mode and the cursor - // would be on a different line. fixes 5673 - if (!isSingleLine()) { - // Force symmetrical movement for word next and previous. Fixes 14536 - setCaretOffsets(offsets, OFFSET_LEADING); - showCaret(); - } else { - int[] linesForCurrentCarets = Arrays.stream(caretOffsets).map(offset -> content.getLineAtOffset(offset)).toArray(); - int[] linesForNewCarets = Arrays.stream(offsets).map(offset -> content.getLineAtOffset(offset)).toArray(); - if (Arrays.equals(linesForCurrentCarets, linesForNewCarets)) { - // Force symmetrical movement for word next and previous. Fixes 14536 - setCaretOffsets(offsets, OFFSET_LEADING); - showCaret(); - } - } -} -/** - * Moves the caret to the start of the previous word. - */ -void doSelectionWordPrevious() { - setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getWordPrevious(offset, SWT.MOVEMENT_WORD)).toArray(), OFFSET_LEADING); - showCaret(); -} -/** - * Moves the caret one character to the left. Do not go to the previous line. - * When in a bidi locale and at a R2L character the caret is moved to the - * beginning of the R2L segment (visually right) and then one character to the - * left (visually left because it's now in a L2R segment). - */ -void doVisualPrevious() { - setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterPrevious(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT); - showCaret(); -} -/** - * Moves the caret one character to the right. Do not go to the next line. - * When in a bidi locale and at a R2L character the caret is moved to the - * end of the R2L segment (visually left) and then one character to the - * right (visually right because it's now in a L2R segment). - */ -void doVisualNext() { - setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterNext(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT); - showCaret(); -} -/** - * Moves the caret to the end of the next word. - * If a selection exists, move the caret to the end of the selection - * and remove the selection. - */ -void doWordNext() { - if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { - setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), SWT.DEFAULT); - showCaret(); - } else { - doSelectionWordNext(); - } -} -/** - * Moves the caret to the start of the previous word. - * If a selection exists, move the caret to the start of the selection - * and remove the selection. - */ -void doWordPrevious() { - if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { - setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), SWT.DEFAULT); - showCaret(); - } else { - doSelectionWordPrevious(); - } -} -/** - * Ends the autoscroll process. - */ -void endAutoScroll() { - autoScrollDirection = SWT.NULL; -} -@Override -public Color getBackground() { - checkWidget(); - if (background == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); - } - return background; -} -/** - * Returns the baseline, in points. - * - * Note: this API should not be used if a StyleRange attribute causes lines to - * have different heights (i.e. different fonts, rise, etc). - * - * @return baseline the baseline - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 3.0 - * - * @see #getBaseline(int) - */ -public int getBaseline() { - checkWidget(); - return renderer.getBaseline(); -} -/** - * Returns the baseline at the given offset, in points. - * - * @param offset the offset - * - * @return baseline the baseline - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • - *
    - * - * @since 3.2 - */ -public int getBaseline(int offset) { - checkWidget(); - if (!(0 <= offset && offset <= content.getCharCount())) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (isFixedLineHeight()) { - return renderer.getBaseline(); - } - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); - FontMetrics metrics = layout.getLineMetrics(lineInParagraph); - renderer.disposeTextLayout(layout); - return metrics.getAscent() + metrics.getLeading(); -} -/** - * Gets the BIDI coloring mode. When true the BIDI text display - * algorithm is applied to segments of text that are the same - * color. - * - * @return the current coloring mode - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @deprecated use BidiSegmentListener instead. - */ -@Deprecated -public boolean getBidiColoring() { - checkWidget(); - return bidiColoring; -} -/** - * Returns whether the widget is in block selection mode. - * - * @return true if widget is in block selection mode, false otherwise - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public boolean getBlockSelection() { - checkWidget(); - return blockSelection; -} -Rectangle getBlockSelectionPosition() { - int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset()); - int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset()); - if (firstLine > lastLine) { - int temp = firstLine; - firstLine = lastLine; - lastLine = temp; - } - int left = blockXAnchor; - int right = blockXLocation; - if (left > right) { - left = blockXLocation; - right = blockXAnchor; - } - return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine); -} -/** - * Returns the block selection bounds. The bounds is - * relative to the upper left corner of the document. - * - * @return the block selection bounds - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public Rectangle getBlockSelectionBounds() { - Rectangle rect; - if (blockSelection && blockXLocation != -1) { - rect = getBlockSelectionRectangle(); - } else { - Point startPoint = getPointAtOffset(selection[0].x); - Point endPoint = getPointAtOffset(selection[0].y); - int height = getLineHeight(selection[0].y); - rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y); - if (selection[0].x == selection[0].y) { - rect.width = getCaretWidth(); - } - } - rect.x += horizontalScrollOffset; - rect.y += getVerticalScrollOffset(); - return rect; -} -Rectangle getBlockSelectionRectangle() { - Rectangle rect = getBlockSelectionPosition(); - rect.y = getLinePixel(rect.y); - rect.width = rect.width - rect.x; - rect.height = getLinePixel(rect.height + 1) - rect.y; - return rect; -} -String getBlockSelectionText(String delimiter) { - Rectangle rect = getBlockSelectionPosition(); - int firstLine = rect.y; - int lastLine = rect.height; - int left = rect.x; - int right = rect.width; - StringBuilder buffer = new StringBuilder(); - for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { - int start = getOffsetAtPoint(left, 0, lineIndex, null); - int end = getOffsetAtPoint(right, 0, lineIndex, null); - if (start > end) { - int temp = start; - start = end; - end = temp; - } - String text = content.getTextRange(start, end - start); - buffer.append(text); - if (lineIndex < lastLine) buffer.append(delimiter); - } - return buffer.toString(); -} -/** - * Returns the index of the last fully visible line. - * - * @return index of the last fully visible line. - */ -int getBottomIndex() { - int bottomIndex; - if (isFixedLineHeight()) { - int lineCount = 1; - int lineHeight = renderer.getLineHeight(); - if (lineHeight != 0) { - // calculate the number of lines that are fully visible - int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset(); - lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight; - } - bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); - } else { - int clientAreaHeight = this.clientAreaHeight - bottomMargin; - bottomIndex = getLineIndex(clientAreaHeight); - if (bottomIndex > 0) { - int linePixel = getLinePixel(bottomIndex); - int lineHeight = renderer.getLineHeight(bottomIndex); - if (linePixel + lineHeight > clientAreaHeight) { - if (getLinePixel(bottomIndex - 1) >= topMargin) { - bottomIndex--; - } - } - } - } - return bottomIndex; -} -/** - * Returns the bottom margin. - * - * @return the bottom margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public int getBottomMargin() { - checkWidget(); - return bottomMargin; -} -Rectangle getBoundsAtOffset(int offset) { - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - String line = content.getLine(lineIndex); - Rectangle bounds; - if (line.length() != 0) { - TextLayout layout = renderer.getTextLayout(lineIndex); - int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset)); - bounds = layout.getBounds(offsetInLine, offsetInLine); - if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) { - offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); - Point point = layout.getLocation(offsetInLine, true); - bounds = new Rectangle (point.x, point.y, 0, bounds.height); - } - renderer.disposeTextLayout(layout); - } else { - bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); - } - if (Arrays.binarySearch(caretOffsets, offset) >= 0 && !isWordWrap()) { - int lineEnd = lineOffset + line.length(); - if (offset == lineEnd) { - bounds.width += getCaretWidth(); - } - } - bounds.x += leftMargin - horizontalScrollOffset; - bounds.y += getLinePixel(lineIndex); - return bounds; -} -/** - * Returns the caret position relative to the start of the text. - * - * @return the caret position relative to the start of the text. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getCaretOffset() { - checkWidget(); - return caretOffsets[0]; -} -/** - * Returns the caret width. - * - * @return the caret width, 0 if caret is null. - */ -int getCaretWidth() { - Caret caret = getCaret(); - if (caret == null) return 0; - return caret.getSize().x; -} -Object getClipboardContent(int clipboardType) { - TextTransfer plainTextTransfer = TextTransfer.getInstance(); - return clipboard.getContents(plainTextTransfer, clipboardType); -} -int getClusterNext(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - offset -= lineOffset; - offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER); - offset += lineOffset; - renderer.disposeTextLayout(layout); - return offset; -} -int getClusterPrevious(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - offset -= lineOffset; - offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER); - offset += lineOffset; - renderer.disposeTextLayout(layout); - return offset; -} -/** - * Returns the content implementation that is used for text storage. - * - * @return content the user defined content implementation that is used for - * text storage or the default content implementation if no user defined - * content implementation has been set. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public StyledTextContent getContent() { - checkWidget(); - return content; -} -@Override -public boolean getDragDetect () { - checkWidget (); - return dragDetect; -} -/** - * Returns whether the widget implements double click mouse behavior. - * - * @return true if double clicking a word selects the word, false if double clicks - * have the same effect as regular mouse clicks - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public boolean getDoubleClickEnabled() { - checkWidget(); - return doubleClickEnabled; -} -/** - * Returns whether the widget content can be edited. - * - * @return true if content can be edited, false otherwise - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public boolean getEditable() { - checkWidget(); - return editable; -} -@Override -public Color getForeground() { - checkWidget(); - if (foreground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); - } - return foreground; -} -/** - * Returns the horizontal scroll increment. - * - * @return horizontal scroll increment. - */ -int getHorizontalIncrement() { - return renderer.averageCharWidth; -} -/** - * Returns the horizontal scroll offset relative to the start of the line. - * - * @return horizontal scroll offset relative to the start of the line, - * measured in character increments starting at 0, if > 0 the content is scrolled - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getHorizontalIndex() { - checkWidget(); - return horizontalScrollOffset / getHorizontalIncrement(); -} -/** - * Returns the horizontal scroll offset relative to the start of the line. - * - * @return the horizontal scroll offset relative to the start of the line, - * measured in SWT logical point starting at 0, if > 0 the content is scrolled. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getHorizontalPixel() { - checkWidget(); - return horizontalScrollOffset; -} -/** - * Returns the line indentation of the widget. - * - * @return the line indentation - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getLineIndent(int) - * - * @since 3.2 - */ -public int getIndent() { - checkWidget(); - return indent; -} -/** - * Returns whether the widget justifies lines. - * - * @return whether lines are justified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getLineJustify(int) - * - * @since 3.2 - */ -public boolean getJustify() { - checkWidget(); - return justify; -} -/** - * Returns the action assigned to the key. - * Returns SWT.NULL if there is no action associated with the key. - * - * @param key a key code defined in SWT.java or a character. - * Optionally ORd with a state mask. Preferred state masks are one or more of - * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform - * differences. However, there may be cases where using the specific state masks - * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. - * @return one of the predefined actions defined in ST.java or SWT.NULL - * if there is no action associated with the key. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getKeyBinding(int key) { - checkWidget(); - Integer action = keyActionMap.get(key); - return action == null ? SWT.NULL : action.intValue(); -} -/** - * Gets the number of characters. - * - * @return number of characters in the widget - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getCharCount() { - checkWidget(); - return content.getCharCount(); -} -/** - * Returns the line at the given line index without delimiters. - * Index 0 is the first line of the content. When there are not - * any lines, getLine(0) is a valid call that answers an empty string. - * - * @param lineIndex index of the line to return. - * @return the line text without delimiters - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
    • - *
    - * @since 3.4 - */ -public String getLine(int lineIndex) { - checkWidget(); - if (lineIndex < 0 || - (lineIndex > 0 && lineIndex >= content.getLineCount())) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getLine(lineIndex); -} -/** - * Returns the alignment of the line at the given index. - * - * @param index the index of the line - * - * @return the line alignment - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @see #getAlignment() - * - * @since 3.2 - */ -public int getLineAlignment(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return renderer.getLineAlignment(index, alignment); -} -/** - * Returns the line at the specified offset in the text - * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) - * returns the line of the insert location. - * - * @param offset offset relative to the start of the content. - * 0 <= offset <= getCharCount() - * @return line at the specified offset in the text - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • - *
    - */ -public int getLineAtOffset(int offset) { - checkWidget(); - if (offset < 0 || offset > getCharCount()) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getLineAtOffset(offset); -} -/** - * Returns the background color of the line at the given index. - * Returns null if a LineBackgroundListener has been set or if no background - * color has been specified for the line. Should not be called if a - * LineBackgroundListener has been set since the listener maintains the - * line background colors. - * - * @param index the index of the line - * @return the background color of the line at the given index. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - */ -public Color getLineBackground(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetBackground) ? null : renderer.getLineBackground(index, null); -} -/** - * Returns the bullet of the line at the given index. - * - * @param index the index of the line - * - * @return the line bullet - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @since 3.2 - */ -public Bullet getLineBullet(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetStyle) ? null : renderer.getLineBullet(index, null); -} -/** - * Returns the line background data for the given line or null if - * there is none. - * - * @param lineOffset offset of the line start relative to the start - * of the content. - * @param line line to get line background data for - * @return line background data for the given line. - */ -StyledTextEvent getLineBackgroundData(int lineOffset, String line) { - return sendLineEvent(ST.LineGetBackground, lineOffset, line); -} -/** - * Gets the number of text lines. - * - * @return the number of lines in the widget - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getLineCount() { - checkWidget(); - return content.getLineCount(); -} -/** - * Returns the number of lines that can be completely displayed in the - * widget client area. - * - * @return number of lines that can be completely displayed in the widget - * client area. - */ -int getLineCountWhole() { - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - return lineHeight != 0 ? clientAreaHeight / lineHeight : 1; - } - return getBottomIndex() - topIndex + 1; -} -/** - * Returns the line delimiter used for entering new lines by key down - * or paste operation. - * - * @return line delimiter used for entering new lines by key down - * or paste operation. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public String getLineDelimiter() { - checkWidget(); - return content.getLineDelimiter(); -} -/** - * Returns the line height. - *

    - * Note: this API should not be used if a StyleRange attribute causes lines to - * have different heights (i.e. different fonts, rise, etc). - *

    - * - * @return line height in points. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @see #getLineHeight(int) - */ -public int getLineHeight() { - checkWidget(); - return renderer.getLineHeight(); -} -/** - * Returns the line height at the given offset. - * - * @param offset the offset - * - * @return line height in points - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • - *
    - * - * @since 3.2 - */ -public int getLineHeight(int offset) { - checkWidget(); - if (!(0 <= offset && offset <= content.getCharCount())) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (isFixedLineHeight()) { - return renderer.getLineHeight(); - } - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); - int height = layout.getLineBounds(lineInParagraph).height; - renderer.disposeTextLayout(layout); - return height; -} -/** - * Returns the indentation of the line at the given index. - * - * @param index the index of the line - * - * @return the line indentation - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @see #getIndent() - * - * @since 3.2 - */ -public int getLineIndent(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent); -} -/** - * Returns the vertical indentation of the line at the given index. - * - * @param index the index of the line - * - * @return the line vertical indentation - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @since 3.109 - */ -public int getLineVerticalIndent(int index) { - checkWidget(); - if (index < 0 || index >= content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index); -} -/** - * Returns whether the line at the given index is justified. - * - * @param index the index of the line - * - * @return whether the line is justified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @see #getJustify() - * - * @since 3.2 - */ -public boolean getLineJustify(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetStyle) ? false : renderer.getLineJustify(index, justify); -} -/** - * Returns the line spacing of the widget. - * - * @return the line spacing - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.2 - */ -public int getLineSpacing() { - checkWidget(); - return lineSpacing; -} -/** - * Returns the line style data for the given line or null if there is - * none. - *

    - * If there is a LineStyleListener but it does not set any styles, - * the StyledTextEvent.styles field will be initialized to an empty - * array. - *

    - * - * @param lineOffset offset of the line start relative to the start of - * the content. - * @param line line to get line styles for - * @return line style data for the given line. Styles may start before - * line start and end after line end - */ -StyledTextEvent getLineStyleData(int lineOffset, String line) { - return sendLineEvent(ST.LineGetStyle, lineOffset, line); -} -/** - * Returns the top SWT logical point, relative to the client area, of a given line. - * Clamps out of ranges index. - * - * @param lineIndex the line index, the max value is lineCount. If - * lineIndex == lineCount it returns the bottom SWT logical point of the last line. - * It means this function can be used to retrieve the bottom SWT logical point of any line. - * - * @return the top SWT logical point of a given line index - * - * @since 3.2 - */ -public int getLinePixel(int lineIndex) { - checkWidget(); - int lineCount = content.getLineCount(); - lineIndex = Math.max(0, Math.min(lineCount, lineIndex)); - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin; - } - if (lineIndex == topIndex) - return topIndexY + topMargin; - int height = topIndexY; - if (lineIndex > topIndex) { - for (int i = topIndex; i < lineIndex; i++) { - height += renderer.getLineHeight(i); - } - } else { - for (int i = topIndex - 1; i >= lineIndex; i--) { - height -= renderer.getLineHeight(i); - } - } - return height + topMargin; -} -/** - * Returns the line index for a y, relative to the client area. - * The line index returned is always in the range 0..lineCount - 1. - * - * @param y the y-coordinate point - * - * @return the line index for a given y-coordinate point - * - * @since 3.2 - */ -public int getLineIndex(int y) { - checkWidget(); - y -= topMargin; - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - int lineIndex = (y + getVerticalScrollOffset()) / lineHeight; - int lineCount = content.getLineCount(); - lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex)); - return lineIndex; - } - if (y == topIndexY) return topIndex; - int line = topIndex; - if (y < topIndexY) { - while (y < topIndexY && line > 0) { - y += renderer.getLineHeight(--line); - } - } else { - int lineCount = content.getLineCount(); - int lineHeight = renderer.getLineHeight(line); - while (y - lineHeight >= topIndexY && line < lineCount - 1) { - y -= lineHeight; - lineHeight = renderer.getLineHeight(++line); - } - } - return line; -} -/** - * Returns the tab stops of the line at the given index. - * - * @param index the index of the line - * - * @return the tab stops for the line - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @see #getTabStops() - * - * @since 3.6 - */ -public int[] getLineTabStops(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - if (isListening(ST.LineGetStyle)) return null; - int[] tabs = renderer.getLineTabStops(index, null); - if (tabs == null) tabs = this.tabs; - if (tabs == null) return new int [] {renderer.tabWidth}; - int[] result = new int[tabs.length]; - System.arraycopy(tabs, 0, result, 0, tabs.length); - return result; -} -/** - * Returns the wrap indentation of the line at the given index. - * - * @param index the index of the line - * - * @return the wrap indentation - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • - *
    - * - * @see #getWrapIndent() - * - * @since 3.6 - */ -public int getLineWrapIndent(int index) { - checkWidget(); - if (index < 0 || index > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent); -} -/** - * Returns the left margin. - * - * @return the left margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public int getLeftMargin() { - checkWidget(); - return leftMargin - alignmentMargin; -} -/** - * Returns the x, y location of the upper left corner of the character - * bounding box at the specified offset in the text. The point is - * relative to the upper left corner of the widget client area. - * - * @param offset offset relative to the start of the content. - * 0 <= offset <= getCharCount() - * @return x, y location of the upper left corner of the character - * bounding box at the specified offset in the text. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • - *
    - */ -public Point getLocationAtOffset(int offset) { - checkWidget(); - if (offset < 0 || offset > getCharCount()) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return getPointAtOffset(offset); -} -/** - * Returns true if the mouse navigator is enabled. - * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor - * - * @return the mouse navigator's enabled state - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getEnabled - * @since 3.110 - */ -public boolean getMouseNavigatorEnabled () { - checkWidget (); - return mouseNavigator != null; -} -/** - * Returns the character offset of the first character of the given line. - * - * @param lineIndex index of the line, 0 based relative to the first - * line in the content. 0 <= lineIndex < getLineCount(), except - * lineIndex may always be 0 - * @return offset offset of the first character of the line, relative to - * the beginning of the document. The first character of the document is - * at offset 0. - * When there are not any lines, getOffsetAtLine(0) is a valid call that - * answers 0. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
    • - *
    - * @since 2.0 - */ -public int getOffsetAtLine(int lineIndex) { - checkWidget(); - if (lineIndex < 0 || - (lineIndex > 0 && lineIndex >= content.getLineCount())) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getOffsetAtLine(lineIndex); -} -/** - * Returns the offset of the character at the given location relative - * to the first character in the document. - *

    - * The return value reflects the character offset that the caret will - * be placed at if a mouse click occurred at the specified location. - * If the x coordinate of the location is beyond the center of a character - * the returned offset will be behind the character. - *

    - * - * @param point the origin of character bounding box relative to - * the origin of the widget client area. - * @return offset of the character at the given location relative - * to the first character in the document. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when point is null
    • - *
    • ERROR_INVALID_ARGUMENT when there is no character at the specified location
    • - *
    - * - * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance - */ -@Deprecated -public int getOffsetAtLocation(Point point) { - checkWidget(); - if (point == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(point.x, point.y, trailing, true); - if (offset == -1) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return offset + trailing[0]; -} - -/** - * Returns the offset of the character at the given point relative - * to the first character in the document. - *

    - * The return value reflects the character offset that the caret will - * be placed at if a mouse click occurred at the specified point. - * If the x coordinate of the point is beyond the center of a character - * the returned offset will be behind the character. - *

    - * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that - * it does not throw an exception when no character is found and thus performs faster. - * - * @param point the origin of character bounding box relative to - * the origin of the widget client area. - * @return offset of the character at the given point relative - * to the first character in the document. - * -1 when there is no character at the specified location. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when point is null
    • - *
    - * - * @since 3.107 - */ -public int getOffsetAtPoint(Point point) { - checkWidget(); - if (point == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - int[] trailing = new int[1]; - int offset = getOffsetAtPoint(point.x, point.y, trailing, true); - return offset != -1 ? offset + trailing[0] : -1; -} - -int getOffsetAtPoint(int x, int y, int[] alignment) { - int lineIndex = getLineIndex(y); - y -= getLinePixel(lineIndex); - return getOffsetAtPoint(x, y, lineIndex, alignment); -} -int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) { - TextLayout layout = renderer.getTextLayout(lineIndex); - x += horizontalScrollOffset - leftMargin; - int[] trailing = new int[1]; - int offsetInLine = layout.getOffset(x, y, trailing); - if (alignment != null) alignment[0] = OFFSET_LEADING; - if (trailing[0] != 0) { - int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); - int lineStart = layout.getLineOffsets()[lineInParagraph]; - if (offsetInLine + trailing[0] == lineStart) { - offsetInLine += trailing[0]; - if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING; - } else { - String line = content.getLine(lineIndex); - int level = 0; - if (alignment != null) { - int offset = offsetInLine; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset == 0 && Character.isDigit(line.charAt(offset))) { - level = isMirrored() ? 1 : 0; - } else { - level = layout.getLevel(offset) & 0x1; - } - } - offsetInLine += trailing[0]; - if (alignment != null) { - int trailingLevel = layout.getLevel(offsetInLine) & 0x1; - if (level != trailingLevel) { - alignment[0] = PREVIOUS_OFFSET_TRAILING; - } else { - alignment[0] = OFFSET_LEADING; - } - } - } - } - renderer.disposeTextLayout(layout); - return offsetInLine + content.getOffsetAtLine(lineIndex); -} -int getOffsetAtPoint(int x, int y, int[] trailing, boolean inTextOnly) { - if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) { - return -1; - } - int bottomIndex = getPartialBottomIndex(); - int height = getLinePixel(bottomIndex + 1); - if (inTextOnly && y > height) { - return -1; - } - int lineIndex = getLineIndex(y); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - x += horizontalScrollOffset - leftMargin; - y -= getLinePixel(lineIndex); - int offset = layout.getOffset(x, y, trailing); - Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset)); - renderer.disposeTextLayout(layout); - if (inTextOnly && !(rect.x <= x && x <= rect.x + rect.width)) { - return -1; - } - return offset + lineOffset; -} -/** - * Returns the orientation of the receiver. - * - * @return the orientation style - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 2.1.2 - */ -@Override -public int getOrientation () { - return super.getOrientation (); -} -/** - * Returns the index of the last partially visible line. - * - * @return index of the last partially visible line. - */ -int getPartialBottomIndex() { - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); - return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1); - } - return getLineIndex(clientAreaHeight - bottomMargin); -} -/** - * Returns the index of the first partially visible line. - * - * @return index of the first partially visible line. - */ -int getPartialTopIndex() { - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - return getVerticalScrollOffset() / lineHeight; - } - return topIndexY <= 0 ? topIndex : topIndex - 1; -} -/** - * Returns the content in the specified range using the platform line - * delimiter to separate lines. - * - * @param writer the TextWriter to write line text into - * @return the content in the specified range using the platform line - * delimiter to separate lines as written by the specified TextWriter. - */ -String getPlatformDelimitedText(TextWriter writer) { - int end = writer.getStart() + writer.getCharCount(); - int startLine = content.getLineAtOffset(writer.getStart()); - int endLine = content.getLineAtOffset(end); - String endLineText = content.getLine(endLine); - int endLineOffset = content.getOffsetAtLine(endLine); - - for (int i = startLine; i <= endLine; i++) { - writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); - if (i < endLine) { - writer.writeLineDelimiter(PlatformLineDelimiter); - } - } - if (end > endLineOffset + endLineText.length()) { - writer.writeLineDelimiter(PlatformLineDelimiter); - } - writer.close(); - return writer.toString(); -} -/** - * Returns all the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * The ranges array contains start and length pairs. Each pair refers to - * the corresponding style in the styles array. For example, the pair - * that starts at ranges[n] with length ranges[n+1] uses the style - * at styles[n/2] returned by getStyleRanges(int, int, boolean). - *

    - * - * @return the ranges or an empty array if a LineStyleListener has been set. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.2 - * - * @see #getStyleRanges(boolean) - */ -public int[] getRanges() { - checkWidget(); - if (!isListening(ST.LineGetStyle)) { - int[] ranges = renderer.getRanges(0, content.getCharCount()); - if (ranges != null) return ranges; - } - return new int[0]; -} -/** - * Returns the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * The ranges array contains start and length pairs. Each pair refers to - * the corresponding style in the styles array. For example, the pair - * that starts at ranges[n] with length ranges[n+1] uses the style - * at styles[n/2] returned by getStyleRanges(int, int, boolean). - *

    - * - * @param start the start offset of the style ranges to return - * @param length the number of style ranges to return - * - * @return the ranges or an empty array if a LineStyleListener has been set. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE if start or length are outside the widget content
    • - *
    - * - * @since 3.2 - * - * @see #getStyleRanges(int, int, boolean) - */ -public int[] getRanges(int start, int length) { - checkWidget(); - int contentLength = getCharCount(); - int end = start + length; - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (!isListening(ST.LineGetStyle)) { - int[] ranges = renderer.getRanges(start, length); - if (ranges != null) return ranges; - } - return new int[0]; -} -/** - * Returns the right margin. - * - * @return the right margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public int getRightMargin() { - checkWidget(); - return rightMargin; -} -/** - * Returns the selection. - *

    - * Text selections are specified in terms of caret positions. In a text - * widget that contains N characters, there are N+1 caret positions, - * ranging from 0..N - *

    - *

    - * It is usually better to use {@link #getSelectionRanges()} which better - * support multiple selection and carets and block selection. - *

    - * - * @return start and end of the selection, x is the offset of the first - * selected character, y is the offset after the last selected character. - * The selection values returned are visual (i.e., x will always always be - * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right - * (LtoR), compare the caretOffset to the start and end of the selection - * (e.g., caretOffset == start of selection implies that the selection is RtoL). - * @see #getSelectionRanges - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public Point getSelection() { - checkWidget(); - return new Point(selection[0].x, selection[0].y); -} -/** - * Returns the selection. - *

    - * It is usually better to use {@link #getSelectionRanges()} which better - * support multiple selection and carets and block selection. - *

    - * - * @return start and length of the selection, x is the offset of the - * first selected character, relative to the first character of the - * widget content. y is the length of the selection. - * The selection values returned are visual (i.e., length will always always be - * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right - * (LtoR), compare the caretOffset to the start and end of the selection - * (e.g., caretOffset == start of selection implies that the selection is RtoL). - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @see #getSelectionRanges - */ -public Point getSelectionRange() { - checkWidget(); - return new Point(selection[0].x, selection[0].y - selection[0].x); -} -/** - * Returns the selected ranges of text. - * If block is enabled, return the ranges that are inside the block selection rectangle. - *

    - * The ranges array contains start and length pairs. - *

    - * When the receiver is not - * in block selection mode the return arrays contains the start and length of - * the regular selections. - * - * @return the ranges array - * - * @exception SWTException

      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - * @see #setSelectionRanges(int[]) - */ -public int[] getSelectionRanges() { - checkWidget(); - if (blockSelection && blockXLocation != -1) { - Rectangle rect = getBlockSelectionPosition(); - int firstLine = rect.y; - int lastLine = rect.height; - int left = rect.x; - int right = rect.width; - int[] ranges = new int[(lastLine - firstLine + 1) * 2]; - int index = 0; - for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { - int start = getOffsetAtPoint(left, 0, lineIndex, null); - int end = getOffsetAtPoint(right, 0, lineIndex, null); - if (start > end) { - int temp = start; - start = end; - end = temp; - } - ranges[index++] = start; - ranges[index++] = end - start; - } - return ranges; - } - int[] res = new int[2 * selection.length]; - int index = 0; - for (Point p : selection) { - res[index++] = p.x; - res[index++] = p.y - p.x; - } - return res; -} -/** - * Returns the receiver's selection background color. - * - * @return the selection background color - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.1 - */ -public Color getSelectionBackground() { - checkWidget(); - if (selectionBackground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); - } - return selectionBackground; -} -/** - * Gets the number of selected characters. - * - * @return the number of selected characters. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getSelectionCount() { - checkWidget(); - if (blockSelection && blockXLocation != -1) { - return getBlockSelectionText(content.getLineDelimiter()).length(); - } - return Arrays.stream(selection).collect(Collectors.summingInt(sel -> sel.y - sel.x)); -} -/** - * Returns the receiver's selection foreground color. - * - * @return the selection foreground color - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.1 - */ -public Color getSelectionForeground() { - checkWidget(); - if (selectionForeground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); - } - return selectionForeground; -} -/** - * Returns the selected text. - * - * @return selected text, or an empty String if there is no selection. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public String getSelectionText() { - checkWidget(); - if (blockSelection && blockXLocation != -1) { - return getBlockSelectionText(content.getLineDelimiter()); - } - return Arrays.stream(selection).map(sel -> content.getTextRange(sel.x, sel.y - sel.x)).collect(Collectors.joining()); -} -StyledTextEvent getBidiSegments(int lineOffset, String line) { - if (!isListening(ST.LineGetSegments)) { - if (!bidiColoring) return null; - StyledTextEvent event = new StyledTextEvent(content); - event.segments = getBidiSegmentsCompatibility(line, lineOffset); - return event; - } - StyledTextEvent event = sendLineEvent(ST.LineGetSegments, lineOffset, line); - if (event == null || event.segments == null || event.segments.length == 0) return null; - int lineLength = line.length(); - int[] segments = event.segments; - if (segments[0] > lineLength) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - char[] segmentsChars = event.segmentsChars; - boolean hasSegmentsChars = segmentsChars != null; - for (int i = 1; i < segments.length; i++) { - if ((hasSegmentsChars ? segments[i] < segments[i - 1] : segments[i] <= segments[i - 1]) || segments[i] > lineLength) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - } - if (hasSegmentsChars && !visualWrap) { - for (char segmentsChar : segmentsChars) { - if (segmentsChar == '\n' || segmentsChar == '\r') { - visualWrap = true; - break; - } - } - } - return event; -} -/** - * @see #getBidiSegments - * Supports deprecated setBidiColoring API. Remove when API is removed. - */ -int [] getBidiSegmentsCompatibility(String line, int lineOffset) { - int lineLength = line.length(); - StyleRange [] styles = null; - StyledTextEvent event = getLineStyleData(lineOffset, line); - if (event != null) { - styles = event.styles; - } else { - styles = renderer.getStyleRanges(lineOffset, lineLength, true); - } - if (styles == null || styles.length == 0) { - return new int[] {0, lineLength}; - } - int k=0, count = 1; - while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) { - k++; - } - int[] offsets = new int[(styles.length - k) * 2 + 2]; - for (int i = k; i < styles.length; i++) { - StyleRange style = styles[i]; - int styleLineStart = Math.max(style.start - lineOffset, 0); - int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); - styleLineEnd = Math.min (styleLineEnd, line.length ()); - if (i > 0 && count > 1 && - ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || - (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && - style.similarTo(styles[i-1])) { - offsets[count-2] = Math.min(offsets[count-2], styleLineStart); - offsets[count-1] = Math.max(offsets[count-1], styleLineEnd); - } else { - if (styleLineStart > offsets[count - 1]) { - offsets[count] = styleLineStart; - count++; - } - offsets[count] = styleLineEnd; - count++; - } - } - // add offset for last non-colored segment in line, if any - if (lineLength > offsets[count-1]) { - offsets [count] = lineLength; - count++; - } - if (count == offsets.length) { - return offsets; - } - int [] result = new int [count]; - System.arraycopy (offsets, 0, result, 0, count); - return result; -} -/** - * Returns the style range at the given offset. - *

    - * Returns null if a LineStyleListener has been set or if a style is not set - * for the offset. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param offset the offset to return the style for. - * 0 <= offset < getCharCount() must be true. - * @return a StyleRange with start == offset and length == 1, indicating - * the style at the given offset. null if a LineStyleListener has been set - * or if a style is not set for the given offset. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the offset is invalid
    • - *
    - */ -public StyleRange getStyleRangeAtOffset(int offset) { - checkWidget(); - if (offset < 0 || offset >= getCharCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - if (!isListening(ST.LineGetStyle)) { - StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true); - if (ranges != null) return ranges[0]; - } - return null; -} -/** - * Returns the styles. - *

    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * Note: Because a StyleRange includes the start and length, the - * same instance cannot occur multiple times in the array of styles. - * If the same style attributes, such as font and color, occur in - * multiple StyleRanges, getStyleRanges(boolean) - * can be used to get the styles without the ranges. - *

    - * - * @return the styles or an empty array if a LineStyleListener has been set. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getStyleRanges(boolean) - */ -public StyleRange[] getStyleRanges() { - checkWidget(); - return getStyleRanges(0, content.getCharCount(), true); -} -/** - * Returns the styles. - *

    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * Note: When includeRanges is true, the start and length - * fields of each StyleRange will be valid, however the StyleRange - * objects may need to be cloned. When includeRanges is - * false, getRanges(int, int) can be used to get the - * associated ranges. - *

    - * - * @param includeRanges whether the start and length field of the StyleRanges should be set. - * - * @return the styles or an empty array if a LineStyleListener has been set. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.2 - * - * @see #getRanges(int, int) - * @see #setStyleRanges(int[], StyleRange[]) - */ -public StyleRange[] getStyleRanges(boolean includeRanges) { - checkWidget(); - return getStyleRanges(0, content.getCharCount(), includeRanges); -} -/** - * Returns the styles for the given text range. - *

    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * Note: Because the StyleRange includes the start and length, the - * same instance cannot occur multiple times in the array of styles. - * If the same style attributes, such as font and color, occur in - * multiple StyleRanges, getStyleRanges(int, int, boolean) - * can be used to get the styles without the ranges. - *

    - * @param start the start offset of the style ranges to return - * @param length the number of style ranges to return - * - * @return the styles or an empty array if a LineStyleListener has - * been set. The returned styles will reflect the given range. The first - * returned StyleRange will have a starting offset >= start - * and the last returned StyleRange will have an ending - * offset <= start + length - 1 - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • - *
    - * - * @see #getStyleRanges(int, int, boolean) - * - * @since 3.0 - */ -public StyleRange[] getStyleRanges(int start, int length) { - checkWidget(); - return getStyleRanges(start, length, true); -} -/** - * Returns the styles for the given text range. - *

    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * Note: When includeRanges is true, the start and length - * fields of each StyleRange will be valid, however the StyleRange - * objects may need to be cloned. When includeRanges is - * false, getRanges(int, int) can be used to get the - * associated ranges. - *

    - * - * @param start the start offset of the style ranges to return - * @param length the number of style ranges to return - * @param includeRanges whether the start and length field of the StyleRanges should be set. - * - * @return the styles or an empty array if a LineStyleListener has - * been set. The returned styles will reflect the given range. The first - * returned StyleRange will have a starting offset >= start - * and the last returned StyleRange will have an ending - * offset >= start + length - 1 - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • - *
    - * - * @since 3.2 - * - * @see #getRanges(int, int) - * @see #setStyleRanges(int[], StyleRange[]) - */ -public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { - checkWidget(); - int contentLength = getCharCount(); - int end = start + length; - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (!isListening(ST.LineGetStyle)) { - StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges); - if (ranges != null) return ranges; - } - return new StyleRange[0]; -} -/** - * Returns the tab width measured in characters. - * - * @return tab width measured in characters - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getTabStops() - */ -public int getTabs() { - checkWidget(); - return tabLength; -} - -/** - * Returns the tab list of the receiver. - * - * @return the tab list - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.6 - */ -public int[] getTabStops() { - checkWidget(); - if (tabs == null) return new int [] {renderer.tabWidth}; - int[] result = new int[tabs.length]; - System.arraycopy(tabs, 0, result, 0, tabs.length); - return result; -} - -/** - * Returns a copy of the widget content. - * - * @return copy of the widget content - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public String getText() { - checkWidget(); - return content.getTextRange(0, getCharCount()); -} -/** - * Returns the widget content between the two offsets. - * - * @param start offset of the first character in the returned String - * @param end offset of the last character in the returned String - * @return widget content starting at start and ending at end - * @see #getTextRange(int,int) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • - *
    - */ -public String getText(int start, int end) { - checkWidget(); - int contentLength = getCharCount(); - if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getTextRange(start, end - start + 1); -} -/** - * Returns the smallest bounding rectangle that includes the characters between two offsets. - * - * @param start offset of the first character included in the bounding box - * @param end offset of the last character included in the bounding box - * @return bounding box of the text between start and end - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • - *
    - * @since 3.1 - */ -public Rectangle getTextBounds(int start, int end) { - checkWidget(); - int contentLength = getCharCount(); - if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - int lineStart = content.getLineAtOffset(start); - int lineEnd = content.getLineAtOffset(end); - Rectangle rect; - int y = getLinePixel(lineStart); - int height = 0; - int left = 0x7fffffff, right = 0; - for (int i = lineStart; i <= lineEnd; i++) { - int lineOffset = content.getOffsetAtLine(i); - TextLayout layout = renderer.getTextLayout(i); - int length = layout.getText().length(); - if (length > 0) { - if (i == lineStart) { - if (i == lineEnd) { - rect = layout.getBounds(start - lineOffset, end - lineOffset); - } else { - rect = layout.getBounds(start - lineOffset, length); - } - y += rect.y; - } else if (i == lineEnd) { - rect = layout.getBounds(0, end - lineOffset); - } else { - rect = layout.getBounds(); - } - left = Math.min(left, rect.x); - right = Math.max(right, rect.x + rect.width); - height += rect.height; - } else { - height += renderer.getLineHeight(); - } - renderer.disposeTextLayout(layout); - } - rect = new Rectangle (left, y, right-left, height); - rect.x += leftMargin - horizontalScrollOffset; - return rect; -} -/** - * Returns the widget content starting at start for length characters. - * - * @param start offset of the first character in the returned String - * @param length number of characters to return - * @return widget content starting at start and extending length characters. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or length are outside the widget content
    • - *
    - */ -public String getTextRange(int start, int length) { - checkWidget(); - int contentLength = getCharCount(); - int end = start + length; - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getTextRange(start, length); -} -/** - * Returns the maximum number of characters that the receiver is capable of holding. - * - * @return the text limit - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getTextLimit() { - checkWidget(); - return textLimit; -} -/** - * Gets the top index. - *

    - * The top index is the index of the fully visible line that is currently - * at the top of the widget or the topmost partially visible line if no line is fully visible. - * The top index changes when the widget is scrolled. Indexing is zero based. - *

    - * - * @return the index of the top line - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getTopIndex() { - checkWidget(); - return topIndex; -} -/** - * Returns the top margin. - * - * @return the top margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public int getTopMargin() { - checkWidget(); - return topMargin; -} -/** - * Gets the top SWT logical point. - *

    - * The top point is the SWT logical point position of the line that is - * currently at the top of the widget. The text widget can be scrolled by points - * by dragging the scroll thumb so that a partial line may be displayed at the top - * the widget. The top point changes when the widget is scrolled. The top point - * does not include the widget trimming. - *

    - * - * @return SWT logical point position of the top line - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public int getTopPixel() { - checkWidget(); - return getVerticalScrollOffset(); -} -/** - * Returns the vertical scroll increment. - * - * @return vertical scroll increment. - */ -int getVerticalIncrement() { - return renderer.getLineHeight(); -} -int getVerticalScrollOffset() { - if (verticalScrollOffset == -1) { - renderer.calculate(0, topIndex); - int height = 0; - for (int i = 0; i < topIndex; i++) { - height += renderer.getCachedLineHeight(i); - } - height -= topIndexY; - verticalScrollOffset = height; - } - return verticalScrollOffset; -} -int getVisualLineIndex(TextLayout layout, int offsetInLine) { - int lineIndex = layout.getLineIndex(offsetInLine); - int[] offsets = layout.getLineOffsets(); - Caret caret = getCaret(); - if (caret != null && lineIndex != 0 && offsetInLine == offsets[lineIndex]) { - int lineY = layout.getLineBounds(lineIndex).y; - int caretY = caret.getLocation().y - getLinePixel(getFirstCaretLine()); - if (lineY > caretY) lineIndex--; - caretAlignment = OFFSET_LEADING; - } - return lineIndex; -} -int getCaretDirection() { - if (!isBidiCaret()) return SWT.DEFAULT; - if (ime.getCompositionOffset() != -1) return SWT.DEFAULT; - if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection; - updateCaretDirection = false; - int caretLine = getFirstCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); - String line = content.getLine(caretLine); - int offset = caretOffsets[0] - lineOffset; - int lineLength = line.length(); - if (lineLength == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT; - if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; - if (offset == lineLength && offset > 0) offset--; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset == 0 && Character.isDigit(line.charAt(offset))) { - return isMirrored() ? SWT.RIGHT : SWT.LEFT; - } - TextLayout layout = renderer.getTextLayout(caretLine); - int level = layout.getLevel(offset); - renderer.disposeTextLayout(layout); - return ((level & 1) != 0) ? SWT.RIGHT : SWT.LEFT; -} -/* - * Returns the index of the line the first/top caret is on. - */ -int getFirstCaretLine() { - return content.getLineAtOffset(caretOffsets[0]); -} -int getWrapWidth () { - if (wordWrap && !isSingleLine()) { - int width = clientAreaWidth - leftMargin - rightMargin; - return width > 0 ? width : 1; - } - return -1; -} -int getWordNext (int offset, int movement) { - return getWordNext(offset, movement, false); -} -int getWordNext (int offset, int movement, boolean ignoreListener) { - int newOffset, lineOffset; - String lineText; - if (offset >= getCharCount()) { - newOffset = offset; - int lineIndex = content.getLineCount() - 1; - lineOffset = content.getOffsetAtLine(lineIndex); - lineText = content.getLine(lineIndex); - } else { - int lineIndex = content.getLineAtOffset(offset); - lineOffset = content.getOffsetAtLine(lineIndex); - lineText = content.getLine(lineIndex); - int lineLength = lineText.length(); - if (offset >= lineOffset + lineLength) { - newOffset = content.getOffsetAtLine(lineIndex + 1); - } else { - TextLayout layout = renderer.getTextLayout(lineIndex); - newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement); - renderer.disposeTextLayout(layout); - } - } - if (ignoreListener) return newOffset; - return sendWordBoundaryEvent(ST.WordNext, movement, offset, newOffset, lineText, lineOffset); -} -int getWordPrevious(int offset, int movement) { - return getWordPrevious(offset, movement, false); -} -int getWordPrevious(int offset, int movement, boolean ignoreListener) { - int newOffset, lineOffset; - String lineText; - if (offset <= 0) { - newOffset = 0; - int lineIndex = content.getLineAtOffset(newOffset); - lineOffset = content.getOffsetAtLine(lineIndex); - lineText = content.getLine(lineIndex); - } else { - int lineIndex = content.getLineAtOffset(offset); - lineOffset = content.getOffsetAtLine(lineIndex); - lineText = content.getLine(lineIndex); - if (offset == lineOffset) { - String nextLineText = content.getLine(lineIndex - 1); - int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); - newOffset = nextLineOffset + nextLineText.length(); - } else { - int layoutOffset = Math.min(offset - lineOffset, lineText.length()); - TextLayout layout = renderer.getTextLayout(lineIndex); - newOffset = lineOffset + layout.getPreviousOffset(layoutOffset, movement); - renderer.disposeTextLayout(layout); - } - } - if (ignoreListener) return newOffset; - return sendWordBoundaryEvent(ST.WordPrevious, movement, offset, newOffset, lineText, lineOffset); -} -/** - * Returns whether the widget wraps lines. - * - * @return true if widget wraps lines, false otherwise - * @since 2.0 - */ -public boolean getWordWrap() { - checkWidget(); - return wordWrap; -} -/** - * Returns the wrap indentation of the widget. - * - * @return the wrap indentation - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #getLineWrapIndent(int) - * - * @since 3.6 - */ -public int getWrapIndent() { - checkWidget(); - return wrapIndent; -} -/** - * Returns the location of the given offset. - *

    - * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts). - *

    - * - * @return location of the character at the given offset in the line. - */ -Point getPointAtOffset(int offset) { - int lineIndex = content.getLineAtOffset(offset); - String line = content.getLine(lineIndex); - int lineOffset = content.getOffsetAtLine(lineIndex); - int offsetInLine = Math.max (0, offset - lineOffset); - int lineLength = line.length(); - if (lineIndex < content.getLineCount() - 1) { - int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; - if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { - offsetInLine = lineLength; - } - } - Point point; - TextLayout layout = renderer.getTextLayout(lineIndex); - if (lineLength != 0 && offsetInLine <= lineLength) { - if (offsetInLine == lineLength) { - offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); - point = layout.getLocation(offsetInLine, true); - } else { - switch (caretAlignment) { - case OFFSET_LEADING: - point = layout.getLocation(offsetInLine, false); - break; - case PREVIOUS_OFFSET_TRAILING: - default: - boolean lineBegin = offsetInLine == 0; - // If word wrap is enabled, we should also consider offsets - // of wrapped line parts as line begin and do NOT go back. - // This prevents clients to jump one line higher than - // expected, see bug 488172. - // Respect caretAlignment at the caretOffset, unless there's - // a non-empty selection, see bug 488172 comment 6. - if (wordWrap && !lineBegin && (Arrays.binarySearch(caretOffsets, offset) < 0 || Arrays.stream(selection).allMatch(p -> p.x == p.y))) { - int[] offsets = layout.getLineOffsets(); - for (int i : offsets) { - if (i == offsetInLine) { - lineBegin = true; - break; - } - } - } - if (lineBegin) { - point = layout.getLocation(offsetInLine, false); - } else { - offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); - point = layout.getLocation(offsetInLine, true); - } - break; - } - } - } else { - point = new Point(layout.getIndent(), layout.getVerticalIndent()); - } - renderer.disposeTextLayout(layout); - point.x += leftMargin - horizontalScrollOffset; - point.y += getLinePixel(lineIndex); - return point; -} -/** - * Inserts a string. The old selection is replaced with the new text. - * - * @param string the string - * @see #replaceTextRange(int,int,String) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when string is null
    • - *
    - */ -public void insert(String string) { - checkWidget(); - if (string == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (blockSelection) { - insertBlockSelectionText(string, false); - } else { - Point sel = getSelectionRange(); - replaceTextRange(sel.x, sel.y, string); - } -} -int insertBlockSelectionText(String text, boolean fillWithSpaces) { - int lineCount = 1; - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (ch == '\n' || ch == '\r') { - lineCount++; - if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') { - i++; - } - } - } - String[] lines = new String[lineCount]; - int start = 0; - lineCount = 0; - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (ch == '\n' || ch == '\r') { - lines[lineCount++] = text.substring(start, i); - if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') { - i++; - } - start = i + 1; - } - } - lines[lineCount++] = text.substring(start); - if (fillWithSpaces) { - int maxLength = 0; - for (String line : lines) { - int length = line.length(); - maxLength = Math.max(maxLength, length); - } - for (int i = 0; i < lines.length; i++) { - String line = lines[i]; - int length = line.length(); - if (length < maxLength) { - int numSpaces = maxLength - length; - StringBuilder buffer = new StringBuilder(length + numSpaces); - buffer.append(line); - for (int j = 0; j < numSpaces; j++) buffer.append(' '); - lines[i] = buffer.toString(); - } - } - } - int firstLine, lastLine, left, right; - if (blockXLocation != -1) { - Rectangle rect = getBlockSelectionPosition(); - firstLine = rect.y; - lastLine = rect.height; - left = rect.x; - right = rect.width; - } else { - firstLine = lastLine = getFirstCaretLine(); - left = right = getPointAtOffset(caretOffsets[0]).x; - } - start = caretOffsets[0]; - int caretLine = getFirstCaretLine(); - int index = 0, lineIndex = firstLine; - while (lineIndex <= lastLine) { - String string = index < lineCount ? lines[index++] : ""; - int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces); - if (lineIndex == caretLine) start = lineStart; - lineIndex++; - } - while (index < lineCount) { - int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces); - if (lineIndex == caretLine) start = lineStart; - lineIndex++; - } - return start; -} -void insertBlockSelectionText(char key, int action) { - if (key == SWT.CR || key == SWT.LF) return; - Rectangle rect = getBlockSelectionPosition(); - int firstLine = rect.y; - int lastLine = rect.height; - int left = rect.x; - int right = rect.width; - int[] trailing = new int[1]; - int offset = 0, delta = 0; - String text = key != 0 ? new String(new char[] {key}) : ""; - int length = text.length(); - for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { - String line = content.getLine(lineIndex); - int lineOffset = content.getOffsetAtLine(lineIndex); - int lineEndOffset = lineOffset + line.length(); - int linePixel = getLinePixel(lineIndex); - int start = getOffsetAtPoint(left, linePixel, trailing, true); - boolean outOfLine = start == -1; - if (outOfLine) { - start = left < leftMargin ? lineOffset : lineEndOffset; - } else { - start += trailing[0]; - } - int end = getOffsetAtPoint(right, linePixel, trailing, true); - if (end == -1) { - end = right < leftMargin ? lineOffset : lineEndOffset; - } else { - end += trailing[0]; - } - if (start > end) { - int temp = start; - start = end; - end = temp; - } - if (start == end && !outOfLine) { - switch (action) { - case ST.DELETE_PREVIOUS: - if (start > lineOffset) start = getClusterPrevious(start, lineIndex); - break; - case ST.DELETE_NEXT: - if (end < lineEndOffset) end = getClusterNext(end, lineIndex); - break; - } - } - if (outOfLine) { - if (line.length() >= delta) { - delta = line.length(); - offset = lineEndOffset + length; - } - } else { - offset = start + length; - delta = content.getCharCount(); - } - Event event = new Event(); - event.text = text; - event.start = start; - event.end = end; - sendKeyEvent(event); - } - int x = getPointAtOffset(offset).x; - int verticalScrollOffset = getVerticalScrollOffset(); - setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false); -} -/** - * Creates content change listeners and set the default content model. - */ -void installDefaultContent() { - textChangeListener = new TextChangeListener() { - @Override - public void textChanging(TextChangingEvent event) { - handleTextChanging(event); - } - @Override - public void textChanged(TextChangedEvent event) { - handleTextChanged(event); - } - @Override - public void textSet(TextChangedEvent event) { - handleTextSet(event); - } - }; - content = new DefaultContent(); - content.addTextChangeListener(textChangeListener); -} -/** - * Adds event listeners - */ -void installListeners() { - ScrollBar verticalBar = getVerticalBar(); - ScrollBar horizontalBar = getHorizontalBar(); - - listener = event -> { - switch (event.type) { - case SWT.Dispose: handleDispose(event); break; - case SWT.KeyDown: handleKeyDown(event); break; - case SWT.KeyUp: handleKeyUp(event); break; - case SWT.MenuDetect: handleMenuDetect(event); break; - case SWT.MouseDown: handleMouseDown(event); break; - case SWT.MouseUp: handleMouseUp(event); break; - case SWT.MouseMove: handleMouseMove(event); break; - case SWT.Paint: handlePaint(event); break; - case SWT.Resize: handleResize(event); break; - case SWT.Traverse: handleTraverse(event); break; - } - }; - addListener(SWT.Dispose, listener); - addListener(SWT.KeyDown, listener); - addListener(SWT.KeyUp, listener); - addListener(SWT.MenuDetect, listener); - addListener(SWT.MouseDown, listener); - addListener(SWT.MouseUp, listener); - addListener(SWT.MouseMove, listener); - addListener(SWT.Paint, listener); - addListener(SWT.Resize, listener); - addListener(SWT.Traverse, listener); - ime.addListener(SWT.ImeComposition, event -> { - if (!editable) { - event.doit = false; - event.start = 0; - event.end = 0; - event.text = ""; - return; - } - - switch (event.detail) { - case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; - case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; - case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; - } - }); - if (verticalBar != null) { - verticalBar.addListener(SWT.Selection, this::handleVerticalScroll); - } - if (horizontalBar != null) { - horizontalBar.addListener(SWT.Selection, this::handleHorizontalScroll); - } -} -void internalRedrawRange(int start, int length) { - if (length <= 0) return; - int end = start + length; - int startLine = content.getLineAtOffset(start); - int endLine = content.getLineAtOffset(end); - int partialBottomIndex = getPartialBottomIndex(); - int partialTopIndex = getPartialTopIndex(); - if (startLine > partialBottomIndex || endLine < partialTopIndex) { - return; - } - if (partialTopIndex > startLine) { - startLine = partialTopIndex; - start = 0; - } else { - start -= content.getOffsetAtLine(startLine); - } - if (partialBottomIndex < endLine) { - endLine = partialBottomIndex + 1; - end = 0; - } else { - end -= content.getOffsetAtLine(endLine); - } - - TextLayout layout = renderer.getTextLayout(startLine); - int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); - int[] offsets = layout.getLineOffsets(); - int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); - - /* Redraw end of line before start line if wrapped and start offset is first char */ - if (isWordWrap() && startIndex > 0 && offsets[startIndex] == start) { - Rectangle rect = layout.getLineBounds(startIndex - 1); - rect.x = rect.width; - rect.width = clientAreaWidth - rightMargin - rect.x; - rect.x += lineX; - rect.y += startLineY; - super.redraw(rect.x, rect.y, rect.width, rect.height, false); - } - - if (startLine == endLine) { - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); - if (startIndex == endIndex) { - /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ - Rectangle rect = layout.getBounds(start, end - 1); - rect.x += lineX; - rect.y += startLineY; - super.redraw(rect.x, rect.y, rect.width, rect.height, false); - renderer.disposeTextLayout(layout); - return; - } - } - - /* Redraw start line from the start offset to the end of client area */ - Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1); - if (startRect.height == 0) { - Rectangle bounds = layout.getLineBounds(startIndex); - startRect.x = bounds.width; - startRect.y = bounds.y; - startRect.height = bounds.height; - } - startRect.x += lineX; - startRect.y += startLineY; - startRect.width = clientAreaWidth - rightMargin - startRect.x; - super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false); - - /* Redraw end line from the beginning of the line to the end offset */ - if (startLine != endLine) { - renderer.disposeTextLayout(layout); - layout = renderer.getTextLayout(endLine); - offsets = layout.getLineOffsets(); - } - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); - Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); - if (endRect.height == 0) { - Rectangle bounds = layout.getLineBounds(endIndex); - endRect.y = bounds.y; - endRect.height = bounds.height; - } - endRect.x += lineX; - endRect.y += getLinePixel(endLine); - super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false); - renderer.disposeTextLayout(layout); - - /* Redraw all lines in between start and end line */ - int y = startRect.y + startRect.height; - if (endRect.y > y) { - super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false); - } -} -void handleCompositionOffset (Event event) { - int[] trailing = new int [1]; - event.index = getOffsetAtPoint(event.x, event.y, trailing, true); - event.count = trailing[0]; -} -void handleCompositionSelection (Event event) { - if (event.start != event.end) { - int charCount = getCharCount(); - event.start = Math.max(0, Math.min(event.start, charCount)); - event.end = Math.max(0, Math.min(event.end, charCount)); - if (event.text != null) { - setSelection(event.start, event.end); - } else { - event.text = getTextRange(event.start, event.end - event.start); - } - } else { - event.start = selection[0].x; - event.end = selection[0].y; - event.text = getSelectionText(); - } -} -void handleCompositionChanged(Event event) { - String text = event.text; - int start = event.start; - int end = event.end; - int charCount = content.getCharCount(); - start = Math.min(start, charCount); - end = Math.min(end, charCount); - int length = text.length(); - if (length == ime.getCommitCount()) { - content.replaceTextRange(start, end - start, ""); - setCaretOffsets(new int[] {ime.getCompositionOffset()}, SWT.DEFAULT); - caretWidth = 0; - caretDirection = SWT.NULL; - } else { - content.replaceTextRange(start, end - start, text); - int alignment = SWT.DEFAULT; - if (ime.getWideCaret()) { - start = ime.getCompositionOffset(); - for (int caretOffset : caretOffsets) { - int lineIndex = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; - renderer.disposeTextLayout(layout); - } - alignment = OFFSET_LEADING; - } - setCaretOffsets(new int[] {ime.getCaretOffset()}, alignment); - } - resetSelection(); - showCaret(); -} -/** - * Frees resources. - */ -void handleDispose(Event event) { - removeListener(SWT.Dispose, listener); - notifyListeners(SWT.Dispose, event); - event.type = SWT.None; - - clipboard.dispose(); - if (renderer != null) { - renderer.dispose(); - renderer = null; - } - if (content != null) { - content.removeTextChangeListener(textChangeListener); - content = null; - } - if (defaultCaret != null) { - defaultCaret.dispose(); - defaultCaret = null; - } - if (leftCaretBitmap != null) { - leftCaretBitmap.dispose(); - leftCaretBitmap = null; - } - if (rightCaretBitmap != null) { - rightCaretBitmap.dispose(); - rightCaretBitmap = null; - } - if (carets != null) { - for (Caret caret : carets) { - if (caret != null) { - caret.dispose(); - } - } - carets = null; - } - if (isBidiCaret()) { - BidiUtil.removeLanguageListener(this); - } - selectionBackground = null; - selectionForeground = null; - marginColor = null; - textChangeListener = null; - selection = null; - doubleClickSelection = null; - keyActionMap = null; - background = null; - foreground = null; - clipboard = null; - tabs = null; -} -/** - * Scrolls the widget horizontally. - */ -void handleHorizontalScroll(Event event) { - int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; - scrollHorizontal(scrollPixel, false); -} -/** - * If an action has been registered for the key stroke execute the action. - * Otherwise, if a character has been entered treat it as new content. - * - * @param event keyboard event - */ -void handleKey(Event event) { - int action; - caretAlignment = PREVIOUS_OFFSET_TRAILING; - if (event.keyCode != 0) { - // special key pressed (e.g., F1) - action = getKeyBinding(event.keyCode | event.stateMask); - } else { - // character key pressed - action = getKeyBinding(event.character | event.stateMask); - if (action == SWT.NULL) { - // see if we have a control character - if ((event.stateMask & SWT.CTRL) != 0 && event.character <= 31) { - // get the character from the CTRL+char sequence, the control - // key subtracts 64 from the value of the key that it modifies - int c = event.character + 64; - action = getKeyBinding(c | event.stateMask); - } - } - } - if (action == SWT.NULL) { - boolean ignore = false; - - if (IS_MAC) { - // Ignore accelerator key combinations (we do not want to - // insert a character in the text in this instance). - ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 0; - } else { - // Ignore accelerator key combinations (we do not want to - // insert a character in the text in this instance). Don't - // ignore CTRL+ALT combinations since that is the Alt Gr - // key on some keyboards. See bug 20953. - ignore = event.stateMask == SWT.ALT || - event.stateMask == SWT.CTRL || - event.stateMask == (SWT.ALT | SWT.SHIFT) || - event.stateMask == (SWT.CTRL | SWT.SHIFT); - } - // -ignore anything below SPACE except for line delimiter keys and tab. - // -ignore DEL - if (!ignore && event.character > 31 && event.character != SWT.DEL || - event.character == SWT.CR || event.character == SWT.LF || - event.character == TAB) { - doContent(event.character); - update(); - } - } else { - invokeAction(action); - } -} -/** - * If a VerifyKey listener exists, verify that the key that was entered - * should be processed. - * - * @param event keyboard event - */ -void handleKeyDown(Event event) { - if (clipboardSelection == null) { - clipboardSelection = new Point(selection[0].x, selection[0].y); - } - newOrientation = SWT.NONE; - event.stateMask &= SWT.MODIFIER_MASK; - - Event verifyEvent = new Event(); - verifyEvent.character = event.character; - verifyEvent.keyCode = event.keyCode; - verifyEvent.keyLocation = event.keyLocation; - verifyEvent.stateMask = event.stateMask; - verifyEvent.doit = event.doit; - notifyListeners(ST.VerifyKey, verifyEvent); - if (verifyEvent.doit) { - if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) { - newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT; - } - handleKey(event); - } -} -/** - * Update the Selection Clipboard. - * - * @param event keyboard event - */ -void handleKeyUp(Event event) { - if (clipboardSelection != null) { - if (clipboardSelection.x != selection[0].x || clipboardSelection.y != selection[0].y) { - copySelection(DND.SELECTION_CLIPBOARD); - } - } - clipboardSelection = null; - - if (newOrientation != SWT.NONE) { - if (newOrientation != getOrientation()) { - Event e = new Event(); - e.doit = true; - notifyListeners(SWT.OrientationChange, e); - if (e.doit) { - setOrientation(newOrientation); - } - } - newOrientation = SWT.NONE; - } -} -/** - * Update the event location for focus-based context menu triggers. - * - * @param event menu detect event - */ -void handleMenuDetect(Event event) { - if (event.detail == SWT.MENU_KEYBOARD) { - Point point = getDisplay().map(this, null, getPointAtOffset(caretOffsets[0])); - event.x = point.x; - event.y = point.y + getLineHeight(caretOffsets[0]); - } -} -/** - * Updates the caret location and selection if mouse button 1 has been - * pressed. - */ -void handleMouseDown(Event event) { - //force focus (object support) - forceFocus(); - - //drag detect - if (dragDetect && checkDragDetect(event)) return; - - //paste clipboard selection - if (event.button == 2) { - // On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from - // a long middle-click (mouse navigation started) - if (IS_GTK && mouseNavigator != null) { - middleClickPressed = true; - getDisplay().timerExec(200, ()->{ - boolean click = middleClickPressed; - middleClickPressed = false; - if (click && mouseNavigator !=null) { - mouseNavigator.onMouseDown(event); - } else { - pasteOnMiddleClick(event); - } - }); - return; - } else { - pasteOnMiddleClick(event); - } - } - - //set selection - if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) { - return; - } - clickCount = event.count; - boolean addSelection = (event.stateMask & SWT.MOD3) != 0; - if (clickCount == 1) { - if (addSelection && !blockSelection) { - int offset = getOffsetAtPoint(event.x, event.y, null); - addSelection(offset, 0); - sendSelectionEvent(); - } else { - boolean expandSelection = (event.stateMask & SWT.MOD2) != 0; - doMouseLocationChange(event.x, event.y, expandSelection); - } - } else { - if (doubleClickEnabled) { - boolean wordSelect = (clickCount & 1) == 0; - int offset = getOffsetAtPoint(event.x, event.y, null); - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - if (wordSelect) { - String line = content.getLine(lineIndex); - int lineLength = line.length(); - int min = blockSelection ? lineOffset : 0; - int max = blockSelection ? lineOffset + lineLength : content.getCharCount(); - final Point offsetPoint = getPointAtOffset(offset); - if (event.x > offsetPoint.x - && offset < Math.min(max, lineOffset + lineLength) // Not beyond EOL - && !Character.isWhitespace(line.charAt(offset - lineOffset))) { // Not on whitespace - offset++; - } - int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START)); - int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END)); - int[] regions = new int[2]; - if (addSelection) { - int[] current = getSelectionRanges(); - regions = Arrays.copyOf(current, current.length + 2); - } - regions[regions.length - 2] = start; - regions[regions.length - 1] = end - start; - setSelection(regions, false, true); - sendSelectionEvent(); - } else { - if (blockSelection) { - setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true); - } else { - int lineEnd = content.getCharCount(); - if (lineIndex + 1 < content.getLineCount()) { - lineEnd = content.getOffsetAtLine(lineIndex + 1); - } - int[] regions = new int[2]; - if (addSelection) { - int[] current = getSelectionRanges(); - regions = Arrays.copyOf(current, current.length + 2); - } - regions[regions.length - 2] = lineOffset; - regions[regions.length - 1] = lineEnd - lineOffset; - setSelection(regions, false, false); - sendSelectionEvent(); - } - } - doubleClickSelection = new Point(selection[0].x, selection[0].y); - showCaret(); - } - } -} - -void addSelection(int offset, int length) { - int[] ranges = getSelectionRanges(); - ranges = Arrays.copyOf(ranges, ranges.length + 2); - ranges[ranges.length - 2] = offset; - ranges[ranges.length - 1] = length; - setSelection(ranges, true, true); -} - -/** - * Updates the caret location and selection if mouse button 1 is pressed - * during the mouse move. - */ -void handleMouseMove(Event event) { - if (clickCount > 0) { - update(); - doAutoScroll(event); - doMouseLocationChange(event.x, event.y, true); - } - if (renderer.hasLinks) { - doMouseLinkCursor(event.x, event.y); - } -} -/** - * Autoscrolling ends when the mouse button is released. - */ -void handleMouseUp(Event event) { - middleClickPressed = false; - clickCount = 0; - endAutoScroll(); - if (event.button == 1) { - copySelection(DND.SELECTION_CLIPBOARD); - } -} -/** - * Renders the invalidated area specified in the paint event. - * - * @param event paint event - */ -void handlePaint(Event event) { - if (event.width == 0 || event.height == 0) return; - if (clientAreaWidth == 0 || clientAreaHeight == 0) return; - - final int endY = event.y + event.height; - GC gc = event.gc; - Color background = getBackground(); - Color foreground = getForeground(); - if (endY > 0) { - final int startLine = getLineIndex(event.y); - final int endLine = isSingleLine() ? 1 : content.getLineCount(); - final int x = leftMargin - horizontalScrollOffset; - int y = getLinePixel(startLine); - y += renderer.drawLines(startLine, endLine, x, y, endY, gc, background, foreground); - if (y < endY) { - gc.setBackground(background); - drawBackground(gc, 0, y, clientAreaWidth, endY - y); - } - } - if (blockSelection && blockXLocation != -1) { - gc.setBackground(getSelectionBackground()); - Rectangle rect = getBlockSelectionRectangle(); - gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1)); - gc.setAdvanced(true); - if (gc.getAdvanced()) { - gc.setAlpha(100); - gc.fillRectangle(rect); - gc.setAdvanced(false); - } - } - if(carets != null) { - for (int i = 1; i < carets.length; i++) { //skip 1st caret that's already drawn - Caret caret = carets[i]; - if (caret.isVisible()) { - if (caret.getImage() != null) { - gc.drawImage(caret.getImage(), caret.getBounds().x, caret.getBounds().y); - } else { - gc.drawRectangle(caret.getBounds().x, caret.getBounds().y, caret.getBounds().width, getLineHeight(caretOffsets[i])); - } - } - } - } - - // fill the margin background - gc.setBackground(marginColor != null ? marginColor : background); - if (topMargin > 0) { - drawBackground(gc, 0, 0, clientAreaWidth, topMargin); - } - if (bottomMargin > 0) { - drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin); - } - if (leftMargin - alignmentMargin > 0) { - drawBackground(gc, 0, 0, leftMargin - alignmentMargin, clientAreaHeight); - } - if (rightMargin > 0) { - drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight); - } -} -/** - * Recalculates the scroll bars. Rewraps all lines when in word - * wrap mode. - * - * @param event resize event - */ -void handleResize(Event event) { - int oldHeight = clientAreaHeight; - int oldWidth = clientAreaWidth; - Rectangle clientArea = getClientArea(); - clientAreaHeight = clientArea.height; - clientAreaWidth = clientArea.width; - if (!alwaysShowScroll && ignoreResize != 0) return; - - redrawMargins(oldHeight, oldWidth); - if (wordWrap) { - if (oldWidth != clientAreaWidth) { - renderer.reset(0, content.getLineCount()); - verticalScrollOffset = -1; - renderer.calculateIdle(); - super.redraw(); - } - if (oldHeight != clientAreaHeight) { - if (oldHeight == 0) topIndexY = 0; - setScrollBars(true); - } - setCaretLocations(); - } else { - renderer.calculateClientArea(); - setScrollBars(true); - claimRightFreeSpace(); - // StyledText allows any value for horizontalScrollOffset when clientArea is zero - // in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429. - if (clientAreaWidth != 0) { - ScrollBar horizontalBar = getHorizontalBar(); - if (horizontalBar != null && horizontalBar.getVisible()) { - if (horizontalScrollOffset != horizontalBar.getSelection()) { - horizontalBar.setSelection(horizontalScrollOffset); - horizontalScrollOffset = horizontalBar.getSelection(); - } - } - } - } - updateCaretVisibility(); - claimBottomFreeSpace(); - setAlignment(); - //TODO FIX TOP INDEX DURING RESIZE -// if (oldHeight != clientAreaHeight || wordWrap) { -// calculateTopIndex(0); -// } -} -/** - * Updates the caret position and selection and the scroll bars to reflect - * the content change. - */ -void handleTextChanged(TextChangedEvent event) { - int offset = ime.getCompositionOffset(); - if (offset != -1 && lastTextChangeStart < offset) { - // updating the compositionOffset of the ongoing IME if last IMEs text is deleted meanwhile - // for example 1.insert IME text 2.open IME menu 3. ctrl+backspace => 4. commit IME would result in IllegalArgumentException - int compositionOffset = ime.getCaretOffset() + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount; - // workaround: while ongoing IME non-ime text is deleted it may result in too big compositionOffset - // for example 1.insert IME text 2.insert space 3.open IME menu 4. ctrl+backspace twice => 5. commit IME would result in IllegalArgumentException - compositionOffset= Math.min(compositionOffset, getCharCount()); - ime.setCompositionOffset(compositionOffset); - } - int firstLine = content.getLineAtOffset(lastTextChangeStart); - resetCache(firstLine, 0); - if (!isFixedLineHeight() && topIndex > firstLine) { - topIndex = firstLine; - if (topIndex < 0) { - // TODO: This logging is in place to determine why topIndex is getting set to negative values. - // It should be deleted once we fix the root cause of this issue. See bug 487254 for details. - System.err.println("StyledText: topIndex was " + topIndex - + ", lastTextChangeStart = " + lastTextChangeStart - + ", content.getClass() = " + content.getClass() - ); - topIndex = 0; - } - topIndexY = 0; - super.redraw(); - } else { - int lastLine = firstLine + lastTextChangeNewLineCount; - int firstLineTop = getLinePixel(firstLine); - int newLastLineBottom = getLinePixel(lastLine + 1); - if (lastLineBottom != newLastLineBottom) { - super.redraw(); - } else { - super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); - redrawLinesBullet(renderer.redrawLines); - } - } - renderer.redrawLines = null; - // update selection/caret location after styles have been changed. - // otherwise any text measuring could be incorrect - // - // also, this needs to be done after all scrolling. Otherwise, - // selection redraw would be flushed during scroll which is wrong. - // in some cases new text would be drawn in scroll source area even - // though the intent is to scroll it. - if (!(blockSelection && blockXLocation != -1)) { - updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); - } - if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) { - claimBottomFreeSpace(); - } - if (lastTextChangeReplaceCharCount > 0) { - claimRightFreeSpace(); - } - - sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0); - lastCharCount += lastTextChangeNewCharCount; - lastCharCount -= lastTextChangeReplaceCharCount; - setAlignment(); -} -/** - * Updates the screen to reflect a pending content change. - * - * @param event .start the start offset of the change - * @param event .newText text that is going to be inserted or empty String - * if no text will be inserted - * @param event .replaceCharCount length of text that is going to be replaced - * @param event .newCharCount length of text that is going to be inserted - * @param event .replaceLineCount number of lines that are going to be replaced - * @param event .newLineCount number of new lines that are going to be inserted - */ -void handleTextChanging(TextChangingEvent event) { - if (event.replaceCharCount < 0) { - event.start += event.replaceCharCount; - event.replaceCharCount *= -1; - } - lastTextChangeStart = event.start; - lastTextChangeNewLineCount = event.newLineCount; - lastTextChangeNewCharCount = event.newCharCount; - lastTextChangeReplaceLineCount = event.replaceLineCount; - lastTextChangeReplaceCharCount = event.replaceCharCount; - int lineIndex = content.getLineAtOffset(event.start); - int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); - int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); - lastLineBottom = destY; - if (srcY < 0 && destY < 0) { - lastLineBottom += srcY - destY; - verticalScrollOffset += destY - srcY; - calculateTopIndex(destY - srcY); - setScrollBars(true); - } else { - scrollText(srcY, destY); - } - sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount); - renderer.textChanging(event); - - // Update the caret offset if it is greater than the length of the content. - // This is necessary since style range API may be called between the - // handleTextChanging and handleTextChanged events and this API sets the - // caretOffset. - int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; - int tooBigOffsets = 0; - while (tooBigOffsets < caretOffsets.length && caretOffsets[caretOffsets.length - 1 - tooBigOffsets] > newEndOfText) { - tooBigOffsets++; - } - if (tooBigOffsets != 0) { - int[] newCaretOffsets = Arrays.copyOf(caretOffsets, caretOffsets.length - tooBigOffsets + 1); - newCaretOffsets[newCaretOffsets.length - 1] = newEndOfText; - setCaretOffsets(newCaretOffsets, SWT.DEFAULT); - } -} -/** - * Called when the widget content is set programmatically, overwriting - * the old content. Resets the caret position, selection and scroll offsets. - * Recalculates the content width and scroll bars. Redraws the widget. - * - * @param event text change event. - */ -void handleTextSet(TextChangedEvent event) { - reset(); - int newCharCount = getCharCount(); - sendAccessibleTextChanged(0, newCharCount, lastCharCount); - lastCharCount = newCharCount; - setAlignment(); -} -/** - * Called when a traversal key is pressed. - * Allow tab next traversal to occur when the widget is in single - * line mode or in multi line and non-editable mode . - * When in editable multi line mode we want to prevent the tab - * traversal and receive the tab key event instead. - * - * @param event the event - */ -void handleTraverse(Event event) { - switch (event.detail) { - case SWT.TRAVERSE_ESCAPE: - case SWT.TRAVERSE_PAGE_NEXT: - case SWT.TRAVERSE_PAGE_PREVIOUS: - event.doit = true; - break; - case SWT.TRAVERSE_RETURN: - case SWT.TRAVERSE_TAB_NEXT: - case SWT.TRAVERSE_TAB_PREVIOUS: - if ((getStyle() & SWT.SINGLE) != 0) { - event.doit = true; - } else { - if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) { - event.doit = true; - } - } - break; - } -} -/** - * Scrolls the widget vertically. - */ -void handleVerticalScroll(Event event) { - int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset(); - scrollVertical(scrollPixel, false); -} -/** - * Add accessibility support for the widget. - */ -void initializeAccessible() { - acc = getAccessible(); - - accAdapter = new AccessibleAdapter() { - @Override - public void getName (AccessibleEvent e) { - String name = null; - String text = getAssociatedLabel (); - if (text != null) { - name = stripMnemonic (text); - } - e.result = name; - } - @Override - public void getHelp(AccessibleEvent e) { - e.result = getToolTipText(); - } - @Override - public void getKeyboardShortcut(AccessibleEvent e) { - String shortcut = null; - String text = getAssociatedLabel (); - if (text != null) { - char mnemonic = _findMnemonic (text); - if (mnemonic != '\0') { - shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ - } - } - e.result = shortcut; - } - }; - acc.addAccessibleListener(accAdapter); - - accTextExtendedAdapter = new AccessibleTextExtendedAdapter() { - @Override - public void getCaretOffset(AccessibleTextEvent e) { - e.offset = StyledText.this.getCaretOffset(); - } - @Override - public void setCaretOffset(AccessibleTextEvent e) { - StyledText.this.setCaretOffset(e.offset); - e.result = ACC.OK; - } - @Override - public void getSelectionRange(AccessibleTextEvent e) { - Point selection = StyledText.this.getSelectionRange(); - e.offset = selection.x; - e.length = selection.y; - } - @Override - public void addSelection(AccessibleTextEvent e) { - StyledText st = StyledText.this; - Point point = st.getSelection(); - if (point.x == point.y) { - int end = e.end; - if (end == -1) end = st.getCharCount(); - st.setSelection(e.start, end); - e.result = ACC.OK; - } - } - @Override - public void getSelection(AccessibleTextEvent e) { - StyledText st = StyledText.this; - if (st.blockSelection && st.blockXLocation != -1) { - Rectangle rect = st.getBlockSelectionPosition(); - int lineIndex = rect.y + e.index; - int linePixel = st.getLinePixel(lineIndex); - e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel); - if (e.ranges.length > 0) { - e.start = e.ranges[0]; - e.end = e.ranges[e.ranges.length - 1]; - } - } else { - if (e.index == 0) { - Point point = st.getSelection(); - e.start = point.x; - e.end = point.y; - if (e.start > e.end) { - int temp = e.start; - e.start = e.end; - e.end = temp; - } - } - } - } - @Override - public void getSelectionCount(AccessibleTextEvent e) { - StyledText st = StyledText.this; - if (st.blockSelection && st.blockXLocation != -1) { - Rectangle rect = st.getBlockSelectionPosition(); - e.count = rect.height - rect.y + 1; - } else { - Point point = st.getSelection(); - e.count = point.x == point.y ? 0 : 1; - } - } - @Override - public void removeSelection(AccessibleTextEvent e) { - StyledText st = StyledText.this; - if (e.index == 0) { - if (st.blockSelection) { - st.clearBlockSelection(true, false); - } else { - st.clearSelection(false); - } - e.result = ACC.OK; - } - } - @Override - public void setSelection(AccessibleTextEvent e) { - if (e.index != 0) return; - StyledText st = StyledText.this; - Point point = st.getSelection(); - if (point.x == point.y) return; - int end = e.end; - if (end == -1) end = st.getCharCount(); - st.setSelection(e.start, end); - e.result = ACC.OK; - } - @Override - public void getCharacterCount(AccessibleTextEvent e) { - e.count = StyledText.this.getCharCount(); - } - @Override - public void getOffsetAtPoint(AccessibleTextEvent e) { - StyledText st = StyledText.this; - Point point = new Point (e.x, e.y); - Display display = st.getDisplay(); - point = display.map(null, st, point); - e.offset = st.getOffsetAtPoint(point.x, point.y, null, true); - } - @Override - public void getTextBounds(AccessibleTextEvent e) { - StyledText st = StyledText.this; - int start = e.start; - int end = e.end; - int contentLength = st.getCharCount(); - start = Math.max(0, Math.min(start, contentLength)); - end = Math.max(0, Math.min(end, contentLength)); - if (start > end) { - int temp = start; - start = end; - end = temp; - } - int startLine = st.getLineAtOffset(start); - int endLine = st.getLineAtOffset(end); - Rectangle[] rects = new Rectangle[endLine - startLine + 1]; - Rectangle bounds = null; - int index = 0; - Display display = st.getDisplay(); - for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) { - Rectangle rect = new Rectangle(0, 0, 0, 0); - rect.y = st.getLinePixel(lineIndex); - rect.height = st.renderer.getLineHeight(lineIndex); - if (lineIndex == startLine) { - rect.x = st.getPointAtOffset(start).x; - } else { - rect.x = st.leftMargin - st.horizontalScrollOffset; - } - if (lineIndex == endLine) { - rect.width = st.getPointAtOffset(end).x - rect.x; - } else { - TextLayout layout = st.renderer.getTextLayout(lineIndex); - rect.width = layout.getBounds().width - rect.x; - st.renderer.disposeTextLayout(layout); - } - rects [index++] = rect = display.map(st, null, rect); - if (bounds == null) { - bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height); - } else { - bounds.add(rect); - } - } - e.rectangles = rects; - if (bounds != null) { - e.x = bounds.x; - e.y = bounds.y; - e.width = bounds.width; - e.height = bounds.height; - } - } - int[] getRanges(int left, int top, int right, int bottom) { - StyledText st = StyledText.this; - int lineStart = st.getLineIndex(top); - int lineEnd = st.getLineIndex(bottom); - int count = lineEnd - lineStart + 1; - int[] ranges = new int [count * 2]; - int index = 0; - for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) { - String line = st.content.getLine(lineIndex); - int lineOffset = st.content.getOffsetAtLine(lineIndex); - int lineEndOffset = lineOffset + line.length(); - int linePixel = st.getLinePixel(lineIndex); - int start = st.getOffsetAtPoint(left, linePixel, null, true); - if (start == -1) { - start = left < st.leftMargin ? lineOffset : lineEndOffset; - } - int[] trailing = new int[1]; - int end = st.getOffsetAtPoint(right, linePixel, trailing, true); - if (end == -1) { - end = right < st.leftMargin ? lineOffset : lineEndOffset; - } else { - end += trailing[0]; - } - if (start > end) { - int temp = start; - start = end; - end = temp; - } - ranges[index++] = start; - ranges[index++] = end; - } - return ranges; - } - @Override - public void getRanges(AccessibleTextEvent e) { - StyledText st = StyledText.this; - Point point = new Point (e.x, e.y); - Display display = st.getDisplay(); - point = display.map(null, st, point); - e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height); - if (e.ranges.length > 0) { - e.start = e.ranges[0]; - e.end = e.ranges[e.ranges.length - 1]; - } - } - @Override - public void getText(AccessibleTextEvent e) { - StyledText st = StyledText.this; - int start = e.start; - int end = e.end; - int contentLength = st.getCharCount(); - if (end == -1) end = contentLength; - start = Math.max(0, Math.min(start, contentLength)); - end = Math.max(0, Math.min(end, contentLength)); - if (start > end) { - int temp = start; - start = end; - end = temp; - } - int count = e.count; - switch (e.type) { - case ACC.TEXT_BOUNDARY_ALL: - //nothing to do - break; - case ACC.TEXT_BOUNDARY_CHAR: { - int newCount = 0; - if (count > 0) { - while (count-- > 0) { - int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER); - if (newEnd == contentLength) break; - if (newEnd == end) break; - end = newEnd; - newCount++; - } - start = end; - end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER); - } else { - while (count++ < 0) { - int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER); - if (newStart == start) break; - start = newStart; - newCount--; - } - end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER); - } - count = newCount; - break; - } - case ACC.TEXT_BOUNDARY_WORD: { - int newCount = 0; - if (count > 0) { - while (count-- > 0) { - int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true); - if (newEnd == end) break; - newCount++; - end = newEnd; - } - start = end; - end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true); - } else { - if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) { - //start is a word start already - count++; - } - while (count <= 0) { - int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true); - if (newStart == start) break; - count++; - start = newStart; - if (count != 0) newCount--; - } - if (count <= 0 && start == 0) { - end = start; - } else { - end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true); - } - } - count = newCount; - break; - } - case ACC.TEXT_BOUNDARY_LINE: - //TODO implement line - case ACC.TEXT_BOUNDARY_PARAGRAPH: - case ACC.TEXT_BOUNDARY_SENTENCE: { - int offset = count > 0 ? end : start; - int lineIndex = st.getLineAtOffset(offset) + count; - lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1)); - start = st.getOffsetAtLine(lineIndex); - String line = st.getLine(lineIndex); - end = start + line.length(); - count = lineIndex - st.getLineAtOffset(offset); - break; - } - } - e.start = start; - e.end = end; - e.count = count; - e.result = st.content.getTextRange(start, end - start); - } - @Override - public void getVisibleRanges(AccessibleTextEvent e) { - e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin); - if (e.ranges.length > 0) { - e.start = e.ranges[0]; - e.end = e.ranges[e.ranges.length - 1]; - } - } - @Override - public void scrollText(AccessibleTextEvent e) { - StyledText st = StyledText.this; - int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel(); - switch (e.type) { - case ACC.SCROLL_TYPE_ANYWHERE: - case ACC.SCROLL_TYPE_TOP_LEFT: - case ACC.SCROLL_TYPE_LEFT_EDGE: - case ACC.SCROLL_TYPE_TOP_EDGE: { - Rectangle rect = st.getBoundsAtOffset(e.start); - if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) { - horizontalPixel = horizontalPixel + rect.x - st.leftMargin; - } - if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) { - topPixel = topPixel + rect.y - st.topMargin; - } - break; - } - case ACC.SCROLL_TYPE_BOTTOM_RIGHT: - case ACC.SCROLL_TYPE_BOTTOM_EDGE: - case ACC.SCROLL_TYPE_RIGHT_EDGE: { - Rectangle rect = st.getBoundsAtOffset(e.end - 1); - if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) { - horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin; - } - if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) { - topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin; - } - break; - } - case ACC.SCROLL_TYPE_POINT: { - Point point = new Point(e.x, e.y); - Display display = st.getDisplay(); - point = display.map(null, st, point); - Rectangle rect = st.getBoundsAtOffset(e.start); - topPixel = topPixel - point.y + rect.y; - horizontalPixel = horizontalPixel - point.x + rect.x; - break; - } - } - st.setTopPixel(topPixel); - st.setHorizontalPixel(horizontalPixel); - e.result = ACC.OK; - } - }; - acc.addAccessibleTextListener(accTextExtendedAdapter); - - accEditableTextListener = new AccessibleEditableTextListener() { - @Override - public void setTextAttributes(AccessibleTextAttributeEvent e) { - // This method must be implemented by the application - e.result = ACC.OK; - } - @Override - public void replaceText(AccessibleEditableTextEvent e) { - StyledText st = StyledText.this; - st.replaceTextRange(e.start, e.end - e.start, e.string); - e.result = ACC.OK; - } - @Override - public void pasteText(AccessibleEditableTextEvent e) { - StyledText st = StyledText.this; - st.setSelection(e.start); - st.paste(); - e.result = ACC.OK; - } - @Override - public void cutText(AccessibleEditableTextEvent e) { - StyledText st = StyledText.this; - st.setSelection(e.start, e.end); - st.cut(); - e.result = ACC.OK; - } - @Override - public void copyText(AccessibleEditableTextEvent e) { - StyledText st = StyledText.this; - st.setSelection(e.start, e.end); - st.copy(); - e.result = ACC.OK; - } - }; - acc.addAccessibleEditableTextListener(accEditableTextListener); - - accAttributeAdapter = new AccessibleAttributeAdapter() { - @Override - public void getAttributes(AccessibleAttributeEvent e) { - StyledText st = StyledText.this; - e.leftMargin = st.getLeftMargin(); - e.topMargin = st.getTopMargin(); - e.rightMargin = st.getRightMargin(); - e.bottomMargin = st.getBottomMargin(); - e.tabStops = st.getTabStops(); - e.justify = st.getJustify(); - e.alignment = st.getAlignment(); - e.indent = st.getIndent(); - } - @Override - public void getTextAttributes(AccessibleTextAttributeEvent e) { - StyledText st = StyledText.this; - int contentLength = st.getCharCount(); - if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) { - e.start = 0; - e.end = contentLength; - e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background); - return; - } - int offset = Math.max(0, Math.min(e.offset, contentLength - 1)); - int lineIndex = st.getLineAtOffset(offset); - int lineOffset = st.getOffsetAtLine(lineIndex); - int lineCount = st.getLineCount(); - offset = offset - lineOffset; - - TextLayout layout = st.renderer.getTextLayout(lineIndex); - int lineLength = layout.getText().length(); - if (lineLength > 0) { - e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1))); - } - - // If no override info available, use defaults. Don't supply default colors, though. - if (e.textStyle == null) { - e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background); - } else { - if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) { - TextStyle textStyle = new TextStyle(e.textStyle); - if (textStyle.foreground == null) textStyle.foreground = st.foreground; - if (textStyle.background == null) textStyle.background = st.background; - if (textStyle.font == null) textStyle.font = st.getFont(); - e.textStyle = textStyle; - } - } - - //offset at line delimiter case - if (offset >= lineLength) { - e.start = lineOffset + lineLength; - if (lineIndex + 1 < lineCount) { - e.end = st.getOffsetAtLine(lineIndex + 1); - } else { - e.end = contentLength; - } - return; - } - - int[] ranges = layout.getRanges(); - st.renderer.disposeTextLayout(layout); - int index = 0; - int end = 0; - while (index < ranges.length) { - int styleStart = ranges[index++]; - int styleEnd = ranges[index++]; - if (styleStart <= offset && offset <= styleEnd) { - e.start = lineOffset + styleStart; - e.end = lineOffset + styleEnd + 1; - return; - } - if (styleStart > offset) { - e.start = lineOffset + end; - e.end = lineOffset + styleStart; - return; - } - end = styleEnd + 1; - } - if (index == ranges.length) { - e.start = lineOffset + end; - if (lineIndex + 1 < lineCount) { - e.end = st.getOffsetAtLine(lineIndex + 1); - } else { - e.end = contentLength; - } - } - } - }; - acc.addAccessibleAttributeListener(accAttributeAdapter); - - accControlAdapter = new AccessibleControlAdapter() { - @Override - public void getRole(AccessibleControlEvent e) { - e.detail = ACC.ROLE_TEXT; - } - @Override - public void getState(AccessibleControlEvent e) { - int state = 0; - if (isEnabled()) state |= ACC.STATE_FOCUSABLE; - if (isFocusControl()) state |= ACC.STATE_FOCUSED; - if (!isVisible()) state |= ACC.STATE_INVISIBLE; - if (!getEditable()) state |= ACC.STATE_READONLY; - if (isSingleLine()) state |= ACC.STATE_SINGLELINE; - else state |= ACC.STATE_MULTILINE; - e.detail = state; - } - @Override - public void getValue(AccessibleControlEvent e) { - e.result = StyledText.this.getText(); - } - }; - acc.addAccessibleControlListener(accControlAdapter); - - addListener(SWT.FocusIn, event -> acc.setFocus(ACC.CHILDID_SELF)); - - addListener(SWT.Dispose, event -> { - // Issue 448: A 3rd party program that uses Accessible may - // cache obtained connection and query it even after StyledText - // is disposed. Disconnect all listeners to avoid querying a - // disposed control. - acc.removeAccessibleControlListener(accControlAdapter); - acc.removeAccessibleAttributeListener(accAttributeAdapter); - acc.removeAccessibleEditableTextListener(accEditableTextListener); - acc.removeAccessibleTextListener(accTextExtendedAdapter); - acc.removeAccessibleListener(accAdapter); - }); -} - -/* - * Return the Label immediately preceding the receiver in the z-order, - * or null if none. - */ -String getAssociatedLabel () { - Control[] siblings = getParent ().getChildren (); - for (int i = 0; i < siblings.length; i++) { - if (siblings [i] == StyledText.this) { - if (i > 0) { - Control sibling = siblings [i-1]; - if (sibling instanceof Label) return ((Label) sibling).getText(); - if (sibling instanceof CLabel) return ((CLabel) sibling).getText(); - } - break; - } - } - return null; -} -String stripMnemonic (String string) { - int index = 0; - int length = string.length (); - do { - while ((index < length) && (string.charAt (index) != '&')) index++; - if (++index >= length) return string; - if (string.charAt (index) != '&') { - return string.substring(0, index-1) + string.substring(index, length); - } - index++; - } while (index < length); - return string; -} -/* - * Return the lowercase of the first non-'&' character following - * an '&' character in the given string. If there are no '&' - * characters in the given string, return '\0'. - */ -char _findMnemonic (String string) { - if (string == null) return '\0'; - int index = 0; - int length = string.length (); - do { - while (index < length && string.charAt (index) != '&') index++; - if (++index >= length) return '\0'; - if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index)); - index++; - } while (index < length); - return '\0'; -} -/** - * Executes the action. - * - * @param action one of the actions defined in ST.java - */ -public void invokeAction(int action) { - checkWidget(); - if (blockSelection && invokeBlockAction(action)) return; - updateCaretDirection = true; - switch (action) { - // Navigation - case ST.LINE_UP: - doLineUp(false); - clearSelection(true); - break; - case ST.LINE_DOWN: - doLineDown(false); - clearSelection(true); - break; - case ST.LINE_START: - doLineStart(); - clearSelection(true); - break; - case ST.LINE_END: - doLineEnd(); - clearSelection(true); - break; - case ST.COLUMN_PREVIOUS: - doCursorPrevious(); - clearSelection(true); - break; - case ST.COLUMN_NEXT: - doCursorNext(); - clearSelection(true); - break; - case ST.PAGE_UP: - doPageUp(false, -1); - clearSelection(true); - break; - case ST.PAGE_DOWN: - doPageDown(false, -1); - clearSelection(true); - break; - case ST.WORD_PREVIOUS: - doWordPrevious(); - clearSelection(true); - break; - case ST.WORD_NEXT: - doWordNext(); - clearSelection(true); - break; - case ST.TEXT_START: - doContentStart(); - clearSelection(true); - break; - case ST.TEXT_END: - doContentEnd(); - clearSelection(true); - break; - case ST.WINDOW_START: - doPageStart(); - clearSelection(true); - break; - case ST.WINDOW_END: - doPageEnd(); - clearSelection(true); - break; - // Selection - case ST.SELECT_LINE_UP: - doSelectionLineUp(); - break; - case ST.SELECT_ALL: - selectAll(); - break; - case ST.SELECT_LINE_DOWN: - doSelectionLineDown(); - break; - case ST.SELECT_LINE_START: - doLineStart(); - doSelection(ST.COLUMN_PREVIOUS); - break; - case ST.SELECT_LINE_END: - doLineEnd(); - doSelection(ST.COLUMN_NEXT); - break; - case ST.SELECT_COLUMN_PREVIOUS: - doSelectionCursorPrevious(); - doSelection(ST.COLUMN_PREVIOUS); - break; - case ST.SELECT_COLUMN_NEXT: - doSelectionCursorNext(); - doSelection(ST.COLUMN_NEXT); - break; - case ST.SELECT_PAGE_UP: - doSelectionPageUp(-1); - break; - case ST.SELECT_PAGE_DOWN: - doSelectionPageDown(-1); - break; - case ST.SELECT_WORD_PREVIOUS: - doSelectionWordPrevious(); - doSelection(ST.COLUMN_PREVIOUS); - break; - case ST.SELECT_WORD_NEXT: - doSelectionWordNext(); - doSelection(ST.COLUMN_NEXT); - break; - case ST.SELECT_TEXT_START: - doContentStart(); - doSelection(ST.COLUMN_PREVIOUS); - break; - case ST.SELECT_TEXT_END: - doContentEnd(); - doSelection(ST.COLUMN_NEXT); - break; - case ST.SELECT_WINDOW_START: - doPageStart(); - doSelection(ST.COLUMN_PREVIOUS); - break; - case ST.SELECT_WINDOW_END: - doPageEnd(); - doSelection(ST.COLUMN_NEXT); - break; - // Modification - case ST.CUT: - cut(); - break; - case ST.COPY: - copy(); - break; - case ST.PASTE: - paste(); - break; - case ST.DELETE_PREVIOUS: - doBackspace(); - break; - case ST.DELETE_NEXT: - doDelete(); - break; - case ST.DELETE_WORD_PREVIOUS: - doDeleteWordPrevious(); - break; - case ST.DELETE_WORD_NEXT: - doDeleteWordNext(); - break; - // Miscellaneous - case ST.TOGGLE_OVERWRITE: - overwrite = !overwrite; // toggle insert/overwrite mode - break; - case ST.TOGGLE_BLOCKSELECTION: - setBlockSelection(!blockSelection); - break; - } -} -/** -* Returns true if an action should not be performed when block -* selection in active -*/ -boolean invokeBlockAction(int action) { - switch (action) { - // Navigation - case ST.LINE_UP: - case ST.LINE_DOWN: - case ST.LINE_START: - case ST.LINE_END: - case ST.COLUMN_PREVIOUS: - case ST.COLUMN_NEXT: - case ST.PAGE_UP: - case ST.PAGE_DOWN: - case ST.WORD_PREVIOUS: - case ST.WORD_NEXT: - case ST.TEXT_START: - case ST.TEXT_END: - case ST.WINDOW_START: - case ST.WINDOW_END: - clearBlockSelection(false, false); - return false; - // Selection - case ST.SELECT_LINE_UP: - doBlockLineVertical(true); - return true; - case ST.SELECT_LINE_DOWN: - doBlockLineVertical(false); - return true; - case ST.SELECT_LINE_START: - doBlockLineHorizontal(false); - return true; - case ST.SELECT_LINE_END: - doBlockLineHorizontal(true); - return false; - case ST.SELECT_COLUMN_PREVIOUS: - doBlockColumn(false); - return true; - case ST.SELECT_COLUMN_NEXT: - doBlockColumn(true); - return true; - case ST.SELECT_WORD_PREVIOUS: - doBlockWord(false); - return true; - case ST.SELECT_WORD_NEXT: - doBlockWord(true); - return true; - case ST.SELECT_ALL: - return false; - case ST.SELECT_TEXT_START: - doBlockContentStartEnd(false); - break; - case ST.SELECT_TEXT_END: - doBlockContentStartEnd(true); - break; - case ST.SELECT_PAGE_UP: - case ST.SELECT_PAGE_DOWN: - case ST.SELECT_WINDOW_START: - case ST.SELECT_WINDOW_END: - //blocked actions - return true; - // Modification - case ST.CUT: - case ST.COPY: - case ST.PASTE: - return false; - case ST.DELETE_PREVIOUS: - case ST.DELETE_NEXT: - if (blockXLocation != -1) { - insertBlockSelectionText((char)0, action); - return true; - } - return false; - case ST.DELETE_WORD_PREVIOUS: - case ST.DELETE_WORD_NEXT: - //blocked actions - return blockXLocation != -1; - } - return false; -} -boolean isBidiCaret() { - return BidiUtil.isBidiPlatform(); -} -boolean isFixedLineHeight() { - return !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent; -} -/** - * Returns whether the given offset is inside a multi byte line delimiter. - * Example: - * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true - * - * @return true if the given offset is inside a multi byte line delimiter. - * false if the given offset is before or after a line delimiter. - */ -boolean isLineDelimiter(int offset) { - int line = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = offset - lineOffset; - // offsetInLine will be greater than line length if the line - // delimiter is longer than one character and the offset is set - // in between parts of the line delimiter. - return offsetInLine > content.getLine(line).length(); -} -/** - * Returns whether the widget is mirrored (right oriented/right to left - * writing order). - * - * @return isMirrored true=the widget is right oriented, false=the widget - * is left oriented - */ -boolean isMirrored() { - return (getStyle() & SWT.MIRRORED) != 0; -} -/** - * Returns true if any text in the widget is selected, - * and false otherwise. - * - * @return the text selection state - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.103 - */ -public boolean isTextSelected() { - checkWidget(); - if (blockSelection && blockXLocation != -1) { - Rectangle rect = getBlockSelectionPosition(); - return !rect.isEmpty(); - } - return Arrays.stream(selection).anyMatch(range -> range.x != range.y); -} -/** - * Returns whether the widget can have only one line. - * - * @return true if widget can have only one line, false if widget can have - * multiple lines - */ -boolean isSingleLine() { - return (getStyle() & SWT.SINGLE) != 0; -} - -/** - * Sends the specified verify event, replace/insert text as defined by - * the event and send a modify event. - * - * @param event the text change event. - *
      - *
    • event.start - the replace start offset
    • - *
    • event.end - the replace end offset
    • - *
    • event.text - the new text
    • - *
    - * @param updateCaret whether or not he caret should be set behind - * the new text - */ -void modifyContent(Event event, boolean updateCaret) { - event.doit = true; - notifyListeners(SWT.Verify, event); - if (event.doit) { - StyledTextEvent styledTextEvent = null; - int replacedLength = event.end - event.start; - if (isListening(ST.ExtendedModify)) { - styledTextEvent = new StyledTextEvent(content); - styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); - styledTextEvent.text = content.getTextRange(event.start, replacedLength); - } - if (updateCaret) { - //Fix advancing flag for delete/backspace key on direction boundary - if (event.text.length() == 0) { - int lineIndex = content.getLineAtOffset(event.start); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - int levelStart = layout.getLevel(event.start - lineOffset); - int lineIndexEnd = content.getLineAtOffset(event.end); - if (lineIndex != lineIndexEnd) { - renderer.disposeTextLayout(layout); - lineOffset = content.getOffsetAtLine(lineIndexEnd); - layout = renderer.getTextLayout(lineIndexEnd); - } - int levelEnd = layout.getLevel(event.end - lineOffset); - renderer.disposeTextLayout(layout); - if (levelStart != levelEnd) { - caretAlignment = PREVIOUS_OFFSET_TRAILING; - } else { - caretAlignment = OFFSET_LEADING; - } - } - } - content.replaceTextRange(event.start, replacedLength, event.text); - // set the caret position prior to sending the modify event. - // fixes 1GBB8NJ - if (updateCaret && !(blockSelection && blockXLocation != -1)) { - // always update the caret location. fixes 1G8FODP - setSelection(Arrays.stream(selection).map(sel -> { - if (sel.y < event.start || sel.x > event.end) { - return sel; - } else { // current range edited - return new Point(event.start + event.text.length(), event.start + event.text.length()); - } - }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)).toArray(), true, false); - showCaret(); - } - notifyListeners(SWT.Modify, event); - if (isListening(ST.ExtendedModify)) { - notifyListeners(ST.ExtendedModify, styledTextEvent); - } - } -} -void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) { - if (isListening(ST.PaintObject)) { - StyledTextEvent event = new StyledTextEvent (content) ; - event.gc = gc; - event.x = x; - event.y = y; - event.ascent = ascent; - event.descent = descent; - event.style = style; - event.bullet = bullet; - event.bulletIndex = bulletIndex; - notifyListeners(ST.PaintObject, event); - } -} -/** - * Replaces the selection with the text on the DND.CLIPBOARD - * clipboard or, if there is no selection, inserts the text at the current - * caret offset. If the widget has the SWT.SINGLE style and the - * clipboard text contains more than one line, only the first line without - * line delimiters is inserted in the widget. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void paste(){ - checkWidget(); - String text = (String) getClipboardContent(DND.CLIPBOARD); - if (text != null && text.length() > 0) { - if (blockSelection) { - boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch; - int offset = insertBlockSelectionText(text, fillWithSpaces); - setCaretOffsets(new int[] {offset}, SWT.DEFAULT); - clearBlockSelection(true, true); - setCaretLocations(); - return; - } else if (getSelectionRanges().length / 2 > 1) { // multi selection - insertMultiSelectionText(text); - setCaretLocations(); - return; - } - Event event = new Event(); - event.start = selection[0].x; - event.end = selection[0].y; - String delimitedText = getModelDelimitedText(text); - if (textLimit > 0) { - int uneditedTextLength = getCharCount() - (selection[0].y - selection[0].x); - if ((uneditedTextLength + delimitedText.length()) > textLimit) { - int endIndex = textLimit - uneditedTextLength; - delimitedText = delimitedText.substring(0, Math.max(endIndex, 0)); - } - } - event.text = delimitedText; - sendKeyEvent(event); - } -} - -private void insertMultiSelectionText(String text) { - String[] blocks = text.split(PlatformLineDelimiter); - int[] ranges = getSelectionRanges(); - for (int i = ranges.length / 2 - 1; i >= 0; i --) { - int offset = ranges[2 * i]; - int length = ranges[2 * i + 1]; - String toPaste = blocks.length > i ? blocks[i] : blocks[blocks.length - 1]; - Event event = new Event(); - event.start = offset; - event.end = offset + length; - event.text = toPaste; - sendKeyEvent(event); - } -} - -private void pasteOnMiddleClick(Event event) { - String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD); - if (text != null && text.length() > 0) { - // position cursor - doMouseLocationChange(event.x, event.y, false); - // insert text - Event e = new Event(); - e.start = selection[0].x; - e.end = selection[0].y; - e.text = getModelDelimitedText(text); - sendKeyEvent(e); - } -} -/** - * Prints the widget's text to the default printer. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void print() { - checkWidget(); - Printer printer = new Printer(); - StyledTextPrintOptions options = new StyledTextPrintOptions(); - options.printTextForeground = true; - options.printTextBackground = true; - options.printTextFontStyle = true; - options.printLineBackground = true; - new Printing(this, printer, options).run(); - printer.dispose(); -} -/** - * Returns a runnable that will print the widget's text - * to the specified printer. - *

    - * The runnable may be run in a non-UI thread. - *

    - * - * @param printer the printer to print to - * - * @return a Runnable for printing the receiver's text - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when printer is null
    • - *
    - */ -public Runnable print(Printer printer) { - checkWidget(); - if (printer == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - StyledTextPrintOptions options = new StyledTextPrintOptions(); - options.printTextForeground = true; - options.printTextBackground = true; - options.printTextFontStyle = true; - options.printLineBackground = true; - return print(printer, options); -} -/** - * Returns a runnable that will print the widget's text - * to the specified printer. - *

    - * The runnable may be run in a non-UI thread. - *

    - * - * @param printer the printer to print to - * @param options print options to use during printing - * - * @return a Runnable for printing the receiver's text - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when printer or options is null
    • - *
    - * @since 2.1 - */ -public Runnable print(Printer printer, StyledTextPrintOptions options) { - checkWidget(); - if (printer == null || options == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - return new Printing(this, printer, options); -} -/** - * Causes the entire bounds of the receiver to be marked - * as needing to be redrawn. The next time a paint request - * is processed, the control will be completely painted. - *

    - * Recalculates the content width for all lines in the bounds. - * When a LineStyleListener is used a redraw call - * is the only notification to the widget that styles have changed - * and that the content width may have changed. - *

    - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see Control#update() - */ -@Override -public void redraw() { - super.redraw(); - int itemCount = getPartialBottomIndex() - topIndex + 1; - renderer.reset(topIndex, itemCount); - renderer.calculate(topIndex, itemCount); - setScrollBars(false); - doMouseLinkCursor(); -} -/** - * Causes the rectangular area of the receiver specified by - * the arguments to be marked as needing to be redrawn. - * The next time a paint request is processed, that area of - * the receiver will be painted. If the all flag - * is true, any children of the receiver which - * intersect with the specified area will also paint their - * intersecting areas. If the all flag is - * false, the children will not be painted. - *

    - * Marks the content width of all lines in the specified rectangle - * as unknown. Recalculates the content width of all visible lines. - * When a LineStyleListener is used a redraw call - * is the only notification to the widget that styles have changed - * and that the content width may have changed. - *

    - * - * @param x the x coordinate of the area to draw - * @param y the y coordinate of the area to draw - * @param width the width of the area to draw - * @param height the height of the area to draw - * @param all true if children should redraw, and false otherwise - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see Control#update() - */ -@Override -public void redraw(int x, int y, int width, int height, boolean all) { - super.redraw(x, y, width, height, all); - if (height > 0) { - int firstLine = getLineIndex(y); - int lastLine = getLineIndex(y + height); - resetCache(firstLine, lastLine - firstLine + 1); - doMouseLinkCursor(); - } -} -void redrawLines(int startLine, int lineCount, boolean bottomChanged) { - // do nothing if redraw range is completely invisible - int endLine = startLine + lineCount - 1; - int partialBottomIndex = getPartialBottomIndex(); - int partialTopIndex = getPartialTopIndex(); - if (startLine > partialBottomIndex || endLine < partialTopIndex) { - return; - } - // only redraw visible lines - if (startLine < partialTopIndex) { - startLine = partialTopIndex; - } - if (endLine > partialBottomIndex) { - endLine = partialBottomIndex; - } - int redrawTop = getLinePixel(startLine); - int redrawBottom = getLinePixel(endLine + 1); - if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin; - int redrawWidth = clientAreaWidth - leftMargin - rightMargin; - super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); -} -void redrawLinesBullet (int[] redrawLines) { - if (redrawLines == null) return; - int topIndex = getPartialTopIndex(); - int bottomIndex = getPartialBottomIndex(); - for (int redrawLine : redrawLines) { - int lineIndex = redrawLine; - if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue; - int width = -1; - Bullet bullet = renderer.getLineBullet(lineIndex, null); - if (bullet != null) { - StyleRange style = bullet.style; - GlyphMetrics metrics = style.metrics; - width = metrics.width; - } - if (width == -1) width = getClientArea().width; - int height = renderer.getLineHeight(lineIndex); - int y = getLinePixel(lineIndex); - super.redraw(0, y, width, height, false); - } -} -void redrawMargins(int oldHeight, int oldWidth) { - /* Redraw the old or new right/bottom margin if needed */ - if (oldWidth != clientAreaWidth) { - if (rightMargin > 0) { - int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; - super.redraw(x, 0, rightMargin, oldHeight, false); - } - } - if (oldHeight != clientAreaHeight) { - if (bottomMargin > 0) { - int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; - super.redraw(0, y, oldWidth, bottomMargin, false); - } - } -} -/** - * Redraws the specified text range. - * - * @param start offset of the first character to redraw - * @param length number of characters to redraw - * @param clearBackground true if the background should be cleared as - * part of the redraw operation. If true, the entire redraw range will - * be cleared before anything is redrawn. If the redraw range includes - * the last character of a line (i.e., the entire line is redrawn) the - * line is cleared all the way to the right border of the widget. - * The redraw operation will be faster and smoother if clearBackground - * is set to false. Whether or not the flag can be set to false depends - * on the type of change that has taken place. If font styles or - * background colors for the redraw range have changed, clearBackground - * should be set to true. If only foreground colors have changed for - * the redraw range, clearBackground can be set to false. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • - *
    - */ -public void redrawRange(int start, int length, boolean clearBackground) { - checkWidget(); - int end = start + length; - int contentLength = content.getCharCount(); - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - int firstLine = content.getLineAtOffset(start); - int lastLine = content.getLineAtOffset(end); - resetCache(firstLine, lastLine - firstLine + 1); - internalRedrawRange(start, length); - doMouseLinkCursor(); -} -/** - * Removes the specified bidirectional segment listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @since 2.0 - */ -public void removeBidiSegmentListener(BidiSegmentListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.LineGetSegments, listener); - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Removes the specified caret listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @since 3.5 - */ -public void removeCaretListener(CaretListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.CaretMoved, listener); -} -/** - * Removes the specified extended modify listener. - * - * @param extendedModifyListener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { - checkWidget(); - if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.ExtendedModify, extendedModifyListener); -} -/** - * Removes the specified line background listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeLineBackgroundListener(LineBackgroundListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.LineGetBackground, listener); -} -/** - * Removes the specified line style listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeLineStyleListener(LineStyleListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.LineGetStyle, listener); - setCaretLocations(); -} -/** - * Removes the specified modify listener. - * - * @param modifyListener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeModifyListener(ModifyListener modifyListener) { - checkWidget(); - if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(SWT.Modify, modifyListener); -} -/** - * Removes the specified listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * @since 3.2 - */ -public void removePaintObjectListener(PaintObjectListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.PaintObject, listener); -} -/** - * Removes the listener from the collection of listeners who will - * be notified when the user changes the receiver's selection. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see SelectionListener - * @see #addSelectionListener - */ -public void removeSelectionListener(SelectionListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(SWT.Selection, listener); -} -/** - * Removes the specified verify listener. - * - * @param verifyListener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeVerifyListener(VerifyListener verifyListener) { - checkWidget(); - if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(SWT.Verify, verifyListener); -} -/** - * Removes the specified key verify listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void removeVerifyKeyListener(VerifyKeyListener listener) { - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.VerifyKey, listener); -} -/** - * Removes the specified word movement listener. - * - * @param listener the listener which should no longer be notified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - * - * @see MovementEvent - * @see MovementListener - * @see #addWordMovementListener - * - * @since 3.3 - */ - -public void removeWordMovementListener(MovementListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeTypedListener(ST.WordNext, listener); - removeTypedListener(ST.WordPrevious, listener); -} -/** - * Replaces the styles in the given range with new styles. This method - * effectively deletes the styles in the given range and then adds the - * the new styles. - *

    - * Note: Because a StyleRange includes the start and length, the - * same instance cannot occur multiple times in the array of styles. - * If the same style attributes, such as font and color, occur in - * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[]) - * can be used to share styles and reduce memory usage. - *

    - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param start offset of first character where styles will be deleted - * @param length length of the range to delete styles in - * @param ranges StyleRange objects containing the new style information. - * The ranges should not overlap and should be within the specified start - * and length. The style rendering is undefined if the ranges do overlap - * or are ill-defined. Must not be null. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • - *
    • ERROR_NULL_ARGUMENT when ranges is null
    • - *
    - * - * @since 2.0 - * - * @see #setStyleRanges(int, int, int[], StyleRange[]) - */ -public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - setStyleRanges(start, length, null, ranges, false); -} -/** - * Replaces the given text range with new text. - * If the widget has the SWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text - * that was set. Note that only a single line of text should be set when - * the SWT.SINGLE style is used. - *

    - * NOTE: During the replace operation the current selection is - * changed as follows: - *

    - *
      - *
    • selection before replaced text: selection unchanged - *
    • selection after replaced text: adjust the selection so that same text - * remains selected - *
    • selection intersects replaced text: selection is cleared and caret - * is placed after inserted text - *
    - * - * @param start offset of first character to replace - * @param length number of characters to replace. Use 0 to insert text - * @param text new text. May be empty to delete text. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • - *
    • ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. - * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
    • - *
    • ERROR_NULL_ARGUMENT when string is null
    • - *
    - */ -public void replaceTextRange(int start, int length, String text) { - checkWidget(); - if (text == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - int contentLength = getCharCount(); - int end = start + length; - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - Event event = new Event(); - event.start = start; - event.end = end; - event.text = text; - modifyContent(event, false); -} -/** - * Resets the caret position, selection and scroll offsets. Recalculate - * the content width and scroll bars. Redraw the widget. - */ -void reset() { - ScrollBar verticalBar = getVerticalBar(); - ScrollBar horizontalBar = getHorizontalBar(); - setCaretOffsets(new int[] {0}, SWT.DEFAULT); - topIndex = 0; - topIndexY = 0; - verticalScrollOffset = 0; - horizontalScrollOffset = 0; - resetSelection(); - renderer.setContent(content); - if (verticalBar != null) { - verticalBar.setSelection(0); - } - if (horizontalBar != null) { - horizontalBar.setSelection(0); - } - resetCache(0, 0); - setCaretLocations(); - super.redraw(); -} -void resetBidiData() { - caretDirection = SWT.NULL; - resetCache(0, content.getLineCount()); - setCaretLocations(); - keyActionMap.clear(); - createKeyBindings(); - super.redraw(); -} -void resetCache(SortedSet lines) { - if (lines == null || lines.isEmpty()) return; - int maxLineIndex = renderer.maxWidthLineIndex; - renderer.reset(lines); - renderer.calculateClientArea(); - if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) { - renderer.calculate(maxLineIndex, 1); - } - setScrollBars(true); - if (!isFixedLineHeight()) { - if (topIndex > lines.iterator().next()) { - verticalScrollOffset = -1; - } - renderer.calculateIdle(); - } -} -void resetCache(int firstLine, int count) { - int maxLineIndex = renderer.maxWidthLineIndex; - renderer.reset(firstLine, count); - renderer.calculateClientArea(); - if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) { - renderer.calculate(maxLineIndex, 1); - } - setScrollBars(true); - if (!isFixedLineHeight()) { - if (topIndex > firstLine) { - verticalScrollOffset = -1; - } - renderer.calculateIdle(); - } -} -/** - * Resets the selection. - */ -void resetSelection() { - selection = Arrays.stream(caretOffsets).mapToObj(offset -> new Point(offset, offset)).toArray(Point[]::new); - selectionAnchors = Arrays.copyOf(caretOffsets, caretOffsets.length); - sendAccessibleTextCaretMoved(); -} - -@Override -public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) { - super.scroll(destX, destY, x, y, width, height, false); - if (all) { - int deltaX = destX - x, deltaY = destY - y; - for (Control child : getChildren()) { - Rectangle rect = child.getBounds(); - child.setLocation(rect.x + deltaX, rect.y + deltaY); - } - } -} - -/** - * Scrolls the widget horizontally. - * - * @param pixels number of SWT logical points to scroll, > 0 = scroll left, - * < 0 scroll right - * @param adjustScrollBar - * true= the scroll thumb will be moved to reflect the new scroll offset. - * false = the scroll thumb will not be moved - * @return - * true=the widget was scrolled - * false=the widget was not scrolled, the given offset is not valid. - */ -boolean scrollHorizontal(int pixels, boolean adjustScrollBar) { - if (pixels == 0) return false; - if (wordWrap) return false; - ScrollBar horizontalBar = getHorizontalBar(); - if (horizontalBar != null && adjustScrollBar) { - horizontalBar.setSelection(horizontalScrollOffset + pixels); - } - int scrollHeight = clientAreaHeight - topMargin - bottomMargin; - if (pixels > 0) { - int sourceX = leftMargin + pixels; - int scrollWidth = clientAreaWidth - sourceX - rightMargin; - if (scrollWidth > 0) { - scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true); - } - if (sourceX > scrollWidth) { - super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true); - } - } else { - int destinationX = leftMargin - pixels; - int scrollWidth = clientAreaWidth - destinationX - rightMargin; - if (scrollWidth > 0) { - scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true); - } - if (destinationX > scrollWidth) { - super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true); - } - } - horizontalScrollOffset += pixels; - setCaretLocations(); - return true; -} -/** - * Scrolls the widget vertically. - * - * @param pixel the new vertical scroll offset - * @param adjustScrollBar - * true= the scroll thumb will be moved to reflect the new scroll offset. - * false = the scroll thumb will not be moved - * @return - * true=the widget was scrolled - * false=the widget was not scrolled - */ -boolean scrollVertical(int pixels, boolean adjustScrollBar) { - if (pixels == 0) { - return false; - } - if (verticalScrollOffset != -1) { - ScrollBar verticalBar = getVerticalBar(); - if (verticalBar != null && adjustScrollBar) { - verticalBar.setSelection(verticalScrollOffset + pixels); - } - int deltaY = 0; - if (pixels > 0) { - int sourceY = topMargin + pixels; - int scrollHeight = clientAreaHeight - sourceY - bottomMargin; - if (scrollHeight > 0) { - deltaY = -pixels; - } - } else { - int destinationY = topMargin - pixels; - int scrollHeight = clientAreaHeight - destinationY - bottomMargin; - if (scrollHeight > 0) { - deltaY = -pixels; - } - } - Control[] children = getChildren(); - for (Control child : children) { - Rectangle rect = child.getBounds(); - child.setLocation(rect.x, rect.y + deltaY); - } - verticalScrollOffset += pixels; - calculateTopIndex(pixels); - super.redraw(); - } else { - calculateTopIndex(pixels); - super.redraw(); - } - setCaretLocations(); - return true; -} -void scrollText(int srcY, int destY) { - if (srcY == destY) return; - int deltaY = destY - srcY; - int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight; - if (deltaY > 0) { - scrollHeight = clientAreaHeight - srcY - bottomMargin; - } else { - scrollHeight = clientAreaHeight - destY - bottomMargin; - } - scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true); - if ((0 < srcY + scrollHeight) && (topMargin > srcY)) { - super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false); - } - if ((0 < destY + scrollHeight) && (topMargin > destY)) { - super.redraw(leftMargin, 0, scrollWidth, topMargin, false); - } - if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) { - super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false); - } - if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) { - super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); - } -} -void sendAccessibleTextCaretMoved() { - if (Arrays.stream(caretOffsets).noneMatch(caretOffset -> caretOffset == accCaretOffset)) { - accCaretOffset = caretOffsets[0]; - getAccessible().textCaretMoved(caretOffsets[0]); - } -} -void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) { - Accessible accessible = getAccessible(); - if (replaceCharCount != 0) { - accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount); - } - if (newCharCount != 0) { - accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount); - } -} -/** - * Selects all the text. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void selectAll() { - checkWidget(); - if (blockSelection) { - renderer.calculate(0, content.getLineCount()); - setScrollBars(false); - int verticalScrollOffset = getVerticalScrollOffset(); - int left = leftMargin - horizontalScrollOffset; - int top = topMargin - verticalScrollOffset; - int right = renderer.getWidth() - rightMargin - horizontalScrollOffset; - int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset; - setBlockSelectionLocation(left, top, right, bottom, false); - return; - } - setSelection(0, Math.max(getCharCount(),0)); -} -/** - * Replaces/inserts text as defined by the event. - * - * @param event the text change event. - *
      - *
    • event.start - the replace start offset
    • - *
    • event.end - the replace end offset
    • - *
    • event.text - the new text
    • - *
    - */ -void sendKeyEvent(Event event) { - if (editable) { - modifyContent(event, true); - } -} -/** - * Returns a StyledTextEvent that can be used to request data such - * as styles and background color for a line. - *

    - * The specified line may be a visual (wrapped) line if in word - * wrap mode. The returned object will always be for a logical - * (unwrapped) line. - *

    - * - * @param lineOffset offset of the line. This may be the offset of - * a visual line if the widget is in word wrap mode. - * @param line line text. This may be the text of a visual line if - * the widget is in word wrap mode. - * @return StyledTextEvent that can be used to request line data - * for the given line. - */ -StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { - StyledTextEvent event = null; - if (isListening(eventType)) { - event = new StyledTextEvent(content); - event.detail = lineOffset; - event.text = line; - event.alignment = alignment; - event.indent = indent; - event.wrapIndent = wrapIndent; - event.justify = justify; - notifyListeners(eventType, event); - } - return event; -} -/** - * Sends the specified selection event. - */ -void sendSelectionEvent() { - getAccessible().textSelectionChanged(); - Event event = new Event(); - event.x = selection[0].x; - event.y = selection[selection.length - 1].y; - notifyListeners(SWT.Selection, event); -} -int sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) { - int lineWidth = 0, start, end; - StringBuilder buffer = new StringBuilder(); - if (lineIndex < content.getLineCount()) { - int[] trailing = new int[1]; - start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true); - if (start == -1) { - int lineOffset = content.getOffsetAtLine(lineIndex); - int lineLegth = content.getLine(lineIndex).length(); - start = end = lineOffset + lineLegth; - if (fillWithSpaces) { - TextLayout layout = renderer.getTextLayout(lineIndex); - lineWidth = layout.getBounds().width; - renderer.disposeTextLayout(layout); - } - } else { - start += trailing[0]; - end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null); - fillWithSpaces = false; - } - } else { - start = end = content.getCharCount(); - buffer.append(content.getLineDelimiter()); - } - if (start > end) { - int temp = start; - start = end; - end = temp; - } - if (fillWithSpaces) { - int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin; - int spacesCount = spacesWidth / renderer.averageCharWidth; - for (int i = 0; i < spacesCount; i++) { - buffer.append(' '); - } - } - buffer.append(text); - Event event = new Event(); - event.start = start; - event.end = end; - event.text = buffer.toString(); - sendKeyEvent(event); - return event.start + event.text.length(); -} -int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) { - if (isListening(eventType)) { - StyledTextEvent event = new StyledTextEvent(content); - event.detail = lineOffset; - event.text = lineText; - event.count = movement; - event.start = offset; - event.end = newOffset; - notifyListeners(eventType, event); - offset = event.end; - if (offset != newOffset) { - int length = getCharCount(); - if (offset < 0) { - offset = 0; - } else if (offset > length) { - offset = length; - } else { - if (isLineDelimiter(offset)) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - } - } - return offset; - } - return newOffset; -} -void setAlignment() { - if ((getStyle() & SWT.SINGLE) == 0) return; - int alignment = renderer.getLineAlignment(0, this.alignment); - int newAlignmentMargin = 0; - if (alignment != SWT.LEFT) { - renderer.calculate(0, 1); - int width = renderer.getWidth() - alignmentMargin; - newAlignmentMargin = clientAreaWidth - width; - if (newAlignmentMargin < 0) newAlignmentMargin = 0; - if (alignment == SWT.CENTER) newAlignmentMargin /= 2; - } - if (alignmentMargin != newAlignmentMargin) { - leftMargin -= alignmentMargin; - leftMargin += newAlignmentMargin; - alignmentMargin = newAlignmentMargin; - resetCache(0, 1); - setCaretLocations(); - super.redraw(); - } -} -/** - * Sets the alignment of the widget. The argument should be one of SWT.LEFT, - * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines. - *

    - * Note that if SWT.MULTI is set, then SWT.WRAP must also be set - * in order to stabilize the right edge before setting alignment. - *

    - * - * @param alignment the new alignment - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #setLineAlignment(int, int, int) - * - * @since 3.2 - */ -public void setAlignment(int alignment) { - checkWidget(); - alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER); - if (alignment == 0 || this.alignment == alignment) return; - this.alignment = alignment; - resetCache(0, content.getLineCount()); - setCaretLocations(); - setAlignment(); - super.redraw(); -} -/** - * Set the Always Show Scrollbars flag. True if the scrollbars are - * always shown even if they are not required (default value). False if the scrollbars are only - * visible when some part of the content needs to be scrolled to be seen. - * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the - * horizontal and vertical directions. - * - * @param show true to show the scrollbars even when not required, false to show scrollbars only when required - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.8 - */ -public void setAlwaysShowScrollBars(boolean show) { - checkWidget(); - if (show == alwaysShowScroll) return; - alwaysShowScroll = show; - setScrollBars(true); -} -/** - * @see Control#setBackground(Color) - */ -@Override -public void setBackground(Color color) { - checkWidget(); - boolean backgroundDisabled = false; - if (!this.enabled && color == null) { - if (background != null) { - Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND); - if (background.equals(disabledBg)) { - return; - } else { - color = new Color (disabledBg.getRGBA()); - backgroundDisabled = true; - } - } - } - customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled; - background = color; - super.setBackground(color); - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the block selection mode. - * - * @param blockSelection true=enable block selection, false=disable block selection - * - * @since 3.5 - */ -public void setBlockSelection(boolean blockSelection) { - checkWidget(); - if ((getStyle() & SWT.SINGLE) != 0) return; - if (blockSelection == this.blockSelection) return; - if (wordWrap) return; - this.blockSelection = blockSelection; - if (cursor == null) { - Display display = getDisplay(); - int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; - super.setCursor(display.getSystemCursor(type)); - } - if (blockSelection) { - int start = selection[0].x; - int end = selection[0].y; - if (start != end) { - setBlockSelectionOffset(start, end, false); - } - } else { - clearBlockSelection(false, false); - } -} -/** - * Sets the block selection bounds. The bounds is - * relative to the upper left corner of the document. - * - * @param rect the new bounds for the block selection - * - * @see #setBlockSelectionBounds(int, int, int, int) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when point is null
    • - *
    - * - * @since 3.5 - */ -public void setBlockSelectionBounds(Rectangle rect) { - checkWidget(); - if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height); -} -/** - * Sets the block selection bounds. The bounds is - * relative to the upper left corner of the document. - * - * @param x the new x coordinate for the block selection - * @param y the new y coordinate for the block selection - * @param width the new width for the block selection - * @param height the new height for the block selection - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setBlockSelectionBounds(int x, int y, int width, int height) { - checkWidget(); - int verticalScrollOffset = getVerticalScrollOffset(); - if (!blockSelection) { - x -= horizontalScrollOffset; - y -= verticalScrollOffset; - int start = getOffsetAtPoint(x, y, null); - int end = getOffsetAtPoint(x+width-1, y+height-1, null); - setSelection(new int[] {start, end - start}, false, false); - setCaretLocations(); - return; - } - int minY = topMargin; - int minX = leftMargin; - int maxY = renderer.getHeight() - bottomMargin; - int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin; - int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset; - int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset; - int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset; - int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset; - if (isFixedLineHeight() && renderer.fixedPitch) { - int avg = renderer.averageCharWidth; - anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; - locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; - } - setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false); -} -void setBlockSelectionLocation (int x, int y, boolean sendEvent) { - int verticalScrollOffset = getVerticalScrollOffset(); - blockXLocation = x + horizontalScrollOffset; - blockYLocation = y + verticalScrollOffset; - int[] alignment = new int[1]; - int offset = getOffsetAtPoint(x, y, alignment); - setCaretOffsets(new int[] {offset}, alignment[0]); - if (blockXAnchor == -1) { - blockXAnchor = blockXLocation; - blockYAnchor = blockYLocation; - selectionAnchors[0] = caretOffsets[0]; - } - doBlockSelection(sendEvent); -} -void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) { - int verticalScrollOffset = getVerticalScrollOffset(); - blockXAnchor = anchorX + horizontalScrollOffset; - blockYAnchor = anchorY + verticalScrollOffset; - selectionAnchors[0] = getOffsetAtPoint(anchorX, anchorY, null); - setBlockSelectionLocation(x, y, sendEvent); -} -void setBlockSelectionOffset (int offset, boolean sendEvent) { - Point point = getPointAtOffset(offset); - int verticalScrollOffset = getVerticalScrollOffset(); - blockXLocation = point.x + horizontalScrollOffset; - blockYLocation = point.y + verticalScrollOffset; - setCaretOffsets(new int[] {offset}, SWT.DEFAULT); - if (blockXAnchor == -1) { - blockXAnchor = blockXLocation; - blockYAnchor = blockYLocation; - selectionAnchors[0] = caretOffsets[0]; - } - doBlockSelection(sendEvent); -} -void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) { - int verticalScrollOffset = getVerticalScrollOffset(); - Point anchorPoint = getPointAtOffset(anchorOffset); - blockXAnchor = anchorPoint.x + horizontalScrollOffset; - blockYAnchor = anchorPoint.y + verticalScrollOffset; - selectionAnchors[0] = anchorOffset; - setBlockSelectionOffset(offset, sendEvent); -} - -/** - * Sets the receiver's caret. Set the caret's height and location. - * - * @param caret the new caret for the receiver - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -@Override -public void setCaret(Caret caret) { - checkWidget (); - super.setCaret(caret); - caretDirection = SWT.NULL; - if (caret != null) { - setCaretLocations(); - if(carets != null) { - for (int i = 1; i < carets.length; i++) { - carets[i].dispose(); - } - } - carets = new Caret[] {caret}; - } else { - carets = null; - } -} -/** - * Sets the BIDI coloring mode. When true the BIDI text display - * algorithm is applied to segments of text that are the same - * color. - * - * @param mode the new coloring mode - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @deprecated use BidiSegmentListener instead. - */ -@Deprecated -public void setBidiColoring(boolean mode) { - checkWidget(); - bidiColoring = mode; -} -/** - * Sets the bottom margin. - * - * @param bottomMargin the bottom margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setBottomMargin (int bottomMargin) { - checkWidget(); - setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); -} -/** - * Moves the Caret to the current caret offset. - */ -void setCaretLocations() { - Point[] newCaretPos = Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new); - setCaretLocations(newCaretPos, getCaretDirection()); -} -void setCaretLocations(final Point[] locations, int direction) { - Caret firstCaret = getCaret(); - if (firstCaret != null) { - if (carets == null || carets.length == 0) { - carets = new Caret[] { firstCaret }; - } - final boolean isDefaultCaret = firstCaret == defaultCaret; - if (locations.length > carets.length) { - int formerCaretCount = carets.length; - carets = Arrays.copyOf(carets, locations.length); - for (int i = formerCaretCount; i < carets.length; i++) { - carets[i] = new Caret(this, firstCaret.getStyle()); - carets[i].setImage(firstCaret.getImage()); - carets[i].setFont(firstCaret.getFont()); - carets[i].setSize(firstCaret.getSize()); - } - } else if (locations.length < carets.length) { - for (int i = locations.length; i < carets.length; i++) { - carets[i].dispose(); - } - carets = Arrays.copyOf(carets, locations.length); - } - for (int i = Math.min(caretOffsets.length, locations.length)-1; i>=0; i--) { // reverse order, seee bug 579028#c7 - final Caret caret = carets[i]; - final int caretOffset = caretOffsets[i]; - final Point location = locations[i]; - final StyleRange styleAtOffset = content.getCharCount() > 0 ? - (caretOffset < content.getCharCount() ? - getStyleRangeAtOffset(caretOffset) : - getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style - null; - final int caretLine = content.getLineAtOffset(caretOffset); - - int graphicalLineHeight = getLineHeight(); - final int lineStartOffset = getOffsetAtLine(caretLine); - int graphicalLineFirstOffset = lineStartOffset; - final int lineEndOffset = lineStartOffset + getLine(caretLine).length(); - int graphicalLineLastOffset = lineEndOffset; - if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles... - graphicalLineHeight = getLineHeight(caretOffset); - final Rectangle characterBounds = getBoundsAtOffset(caretOffset); - graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y)); - graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1; - if (graphicalLineLastOffset < graphicalLineFirstOffset) { - graphicalLineLastOffset = getCharCount(); - } - } - - int caretHeight = getLineHeight(); - boolean isTextAlignedAtBottom = true; - if (graphicalLineFirstOffset >= 0) { - for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) { - isTextAlignedAtBottom &= ( - (style.font == null || Objects.equals(style.font, getFont())) && - style.rise >= 0 && - (style.metrics == null || style.metrics.descent <= 0) - ); - } - } - if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) { - if (isDefaultCaret) { - direction = SWT.DEFAULT; - caretHeight = graphicalLineHeight; - } else { - caretHeight = caret.getSize().y; - } - } - if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) { - location.y += (graphicalLineHeight - caretHeight); - } - - int imageDirection = direction; - if (isMirrored()) { - if (imageDirection == SWT.LEFT) { - imageDirection = SWT.RIGHT; - } else if (imageDirection == SWT.RIGHT) { - imageDirection = SWT.LEFT; - } - } - if (isDefaultCaret && imageDirection == SWT.RIGHT) { - location.x -= (caret.getSize().x - 1); - } - if (isDefaultCaret) { - caret.setBounds(location.x, location.y, caretWidth, caretHeight); - } else { - caret.setLocation(location); - } - if (direction != caretDirection) { - caretDirection = direction; - if (isDefaultCaret) { - if (imageDirection == SWT.DEFAULT) { - defaultCaret.setImage(null); - } else if (imageDirection == SWT.LEFT) { - defaultCaret.setImage(leftCaretBitmap); - } else if (imageDirection == SWT.RIGHT) { - defaultCaret.setImage(rightCaretBitmap); - } - } - if (caretDirection == SWT.LEFT) { - BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI); - } else if (caretDirection == SWT.RIGHT) { - BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI); - } - } - } - updateCaretVisibility(); - super.redraw(); - } - columnX = locations[0].x; -} -/** - * Sets the caret offset. - * - * @param offset caret offset, relative to the first character in the text. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the offset is inside a multi byte line - * delimiter (and thus neither clearly in front of or after the line delimiter) - *
    - */ -public void setCaretOffset(int offset) { - checkWidget(); - int length = getCharCount(); - if (length > 0 && !Arrays.equals(caretOffsets, new int[] {offset})) { - if (offset < 0) { - offset = 0; - } else if (offset > length) { - offset = length; - } else { - if (isLineDelimiter(offset)) { - // offset is inside a multi byte line delimiter. This is an - // illegal operation and an exception is thrown. Fixes 1GDKK3R - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - } - setCaretOffsets(new int[] {offset}, PREVIOUS_OFFSET_TRAILING); - // clear the selection if the caret is moved. - // don't notify listeners about the selection change. - if (blockSelection) { - clearBlockSelection(true, false); - } else { - clearSelection(false); - } - } - setCaretLocations(); -} -void setCaretOffsets(int[] newOffsets, int alignment) { - if (newOffsets.length > 1) { - newOffsets = Arrays.stream(newOffsets).distinct().sorted().toArray(); - } - if (!Arrays.equals(caretOffsets, newOffsets)) { - caretOffsets = newOffsets; - if (isListening(ST.CaretMoved)) { - StyledTextEvent event = new StyledTextEvent(content); - event.end = caretOffsets[caretOffsets.length - 1]; - notifyListeners(ST.CaretMoved, event); - } - } - if (alignment != SWT.DEFAULT) { - caretAlignment = alignment; - } -} -/** - * Copies the specified text range to the clipboard. The text will be placed - * in the clipboard in plain text, HTML, and RTF formats. - * - * @param start start index of the text - * @param length length of text to place in clipboard - * - * @exception SWTError - * @see org.eclipse.swt.dnd.Clipboard#setContents - */ -void setClipboardContent(int start, int length, int clipboardType) throws SWTError { - if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return; - TextTransfer plainTextTransfer = TextTransfer.getInstance(); - TextWriter plainTextWriter = new TextWriter(start, length); - String plainText = getPlatformDelimitedText(plainTextWriter); - Object[] data; - Transfer[] types; - if (clipboardType == DND.SELECTION_CLIPBOARD) { - data = new Object[]{plainText}; - types = new Transfer[]{plainTextTransfer}; - } else { - try { - RTFTransfer rtfTransfer = RTFTransfer.getInstance(); - RTFWriter rtfWriter = new RTFWriter(this, start, length); - String rtfText = getPlatformDelimitedText(rtfWriter); - - HTMLTransfer htmlTransfer = HTMLTransfer.getInstance(); - HTMLWriter htmlWriter = new HTMLWriter(this, start, length, content); - String htmlText = getPlatformDelimitedText(htmlWriter); - htmlText = "" +htmlText; //cause extra memory pressure to fail fast instead of failing in HTMLTransfer.javaToNative() - data = new Object[]{rtfText, htmlText, plainText}; - types = new Transfer[]{rtfTransfer, htmlTransfer, plainTextTransfer}; - } catch (OutOfMemoryError oome) { - // Adding RTF and HTML text may increase size by factor > 15 - // fall back: copy plain text - data = new Object[] { plainText }; - types = new Transfer[] { plainTextTransfer }; - clipboard.setContents(data, types, clipboardType); - OutOfMemoryError customOome = new OutOfMemoryError( - "Out of Memory: Copied only plain text (" + plainText.lines().count() + " lines)."); - customOome.initCause(oome); - // Still throw as it is likely that other threads silently failed too, but at least copied text is not lost - throw customOome; - } - } - clipboard.setContents(data, types, clipboardType); -} -/** - * Sets the content implementation to use for text storage. - * - * @param newContent StyledTextContent implementation to use for text storage. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when listener is null
    • - *
    - */ -public void setContent(StyledTextContent newContent) { - checkWidget(); - if (newContent == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (content != null) { - content.removeTextChangeListener(textChangeListener); - } - content = newContent; - content.addTextChangeListener(textChangeListener); - reset(); -} -/** - * Sets the receiver's cursor to the cursor specified by the - * argument. Overridden to handle the null case since the - * StyledText widget uses an ibeam as its default cursor. - * - * @see Control#setCursor(Cursor) - */ -@Override -public void setCursor (Cursor cursor) { - checkWidget(); - if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - this.cursor = cursor; - if (cursor == null) { - Display display = getDisplay(); - int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; - super.setCursor(display.getSystemCursor(type)); - } else { - super.setCursor(cursor); - } -} -/** - * Sets whether the widget implements double click mouse behavior. - * - * @param enable if true double clicking a word selects the word, if false - * double clicks have the same effect as regular mouse clicks. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void setDoubleClickEnabled(boolean enable) { - checkWidget(); - doubleClickEnabled = enable; -} -@Override -public void setDragDetect (boolean dragDetect) { - checkWidget (); - this.dragDetect = dragDetect; -} -/** - * Sets whether the widget content can be edited. - * - * @param editable if true content can be edited, if false content can not be - * edited - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void setEditable(boolean editable) { - checkWidget(); - this.editable = editable; -} -@Override -public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - Display display = getDisplay(); - this.enabled = enabled; - this.insideSetEnableCall = true; - try { - if (enabled && editable) { - if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); - if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - } else if(!enabled) { - if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND)); - if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND)); - } else if(!editable) { - if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND)); - if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - } - } - finally { - this.insideSetEnableCall = false; - } -} - -@Override -public boolean setFocus() { - boolean focusGained = super.setFocus(); - if (focusGained && hasMultipleCarets()) { - // Multiple carets need to update their drawing. See bug 579179 - setCaretLocations(); - } - return focusGained; -} - -private boolean hasMultipleCarets() { - return carets != null && carets.length > 1; -} - -/** - * See {@link TextLayout#setFixedLineMetrics} - * - * @since 3.125 - */ -public void setFixedLineMetrics(FontMetrics metrics) { - renderer.setFixedLineMetrics (metrics); -} - -/** - * Sets a new font to render text with. - *

    - * NOTE: Italic fonts are not supported unless they have no overhang - * and the same baseline as regular fonts. - *

    - * - * @param font new font - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -@Override -public void setFont(Font font) { - checkWidget(); - int oldLineHeight = renderer.getLineHeight(); - super.setFont(font); - renderer.setFont(getFont(), tabLength); - // keep the same top line visible. fixes 5815 - if (isFixedLineHeight()) { - int lineHeight = renderer.getLineHeight(); - if (lineHeight != oldLineHeight) { - int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset(); - scrollVertical(vscroll, true); - } - } - resetCache(0, content.getLineCount()); - claimBottomFreeSpace(); - calculateScrollBars(); - if (isBidiCaret()) createCaretBitmaps(); - caretDirection = SWT.NULL; - setCaretLocations(); - super.redraw(); -} -@Override -public void setForeground(Color color) { - checkWidget(); - boolean foregroundDisabled = false; - if (!this.enabled && color == null) { - if (foreground != null) { - Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND); - if (foreground.equals(disabledFg)) { - return; - } else { - color = new Color (disabledFg.getRGBA()); - foregroundDisabled = true; - } - } - } - customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled; - foreground = color; - super.setForeground(color); - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the horizontal scroll offset relative to the start of the line. - * Do nothing if there is no text set. - *

    - * NOTE: The horizontal index is reset to 0 when new text is set in the - * widget. - *

    - * - * @param offset horizontal scroll offset relative to the start - * of the line, measured in character increments starting at 0, if - * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void setHorizontalIndex(int offset) { - checkWidget(); - if (getCharCount() == 0) { - return; - } - if (offset < 0) { - offset = 0; - } - offset *= getHorizontalIncrement(); - // allow any value if client area width is unknown or 0. - // offset will be checked in resize handler. - // don't use isVisible since width is known even if widget - // is temporarily invisible - if (clientAreaWidth > 0) { - int width = renderer.getWidth(); - // prevent scrolling if the content fits in the client area. - // align end of longest line with right border of client area - // if offset is out of range. - if (offset > width - clientAreaWidth) { - offset = Math.max(0, width - clientAreaWidth); - } - } - scrollHorizontal(offset - horizontalScrollOffset, true); -} -/** - * Sets the horizontal SWT logical point offset relative to the start of the line. - * Do nothing if there is no text set. - *

    - * NOTE: The horizontal SWT logical point offset is reset to 0 when new text - * is set in the widget. - *

    - * - * @param pixel horizontal SWT logical point offset relative to the start - * of the line. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.0 - */ -public void setHorizontalPixel(int pixel) { - checkWidget(); - if (getCharCount() == 0) { - return; - } - if (pixel < 0) { - pixel = 0; - } - // allow any value if client area width is unknown or 0. - // offset will be checked in resize handler. - // don't use isVisible since width is known even if widget - // is temporarily invisible - if (clientAreaWidth > 0) { - int width = renderer.getWidth(); - // prevent scrolling if the content fits in the client area. - // align end of longest line with right border of client area - // if offset is out of range. - if (pixel > width - clientAreaWidth) { - pixel = Math.max(0, width - clientAreaWidth); - } - } - scrollHorizontal(pixel - horizontalScrollOffset, true); -} -/** - * Sets the line indentation of the widget. - *

    - * It is the amount of blank space, in points, at the beginning of each line. - * When a line wraps in several lines only the first one is indented. - *

    - * - * @param indent the new indent - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #setLineIndent(int, int, int) - * - * @since 3.2 - */ -public void setIndent(int indent) { - checkWidget(); - if (this.indent == indent || indent < 0) return; - this.indent = indent; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets whether the widget should justify lines. - * - * @param justify whether lines should be justified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #setLineJustify(int, int, boolean) - * - * @since 3.2 - */ -public void setJustify(boolean justify) { - checkWidget(); - if (this.justify == justify) return; - this.justify = justify; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Maps a key to an action. - *

    - * One action can be associated with N keys. However, each key can only - * have one action (key:action is N:1 relation). - *

    - * - * @param key a key code defined in SWT.java or a character. - * Optionally ORd with a state mask. Preferred state masks are one or more of - * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform - * differences. However, there may be cases where using the specific state masks - * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. - * @param action one of the predefined actions defined in ST.java. - * Use SWT.NULL to remove a key binding. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void setKeyBinding(int key, int action) { - checkWidget(); - int modifierValue = key & SWT.MODIFIER_MASK; - int keyInt = key & SWT.KEY_MASK; - char keyChar = (char)keyInt; - /** - * Bug 440535: Make sure the key getting mapped to letter is in defiened - * character range and filter out incorrect int to char typecasting. For - * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p' - */ - if (Character.isDefined(keyInt) && Character.isLetter(keyChar)) { - // make the keybinding case insensitive by adding it - // in its upper and lower case form - char ch = Character.toUpperCase(keyChar); - int newKey = ch | modifierValue; - if (action == SWT.NULL) { - keyActionMap.remove(newKey); - } else { - keyActionMap.put(newKey, action); - } - ch = Character.toLowerCase(keyChar); - newKey = ch | modifierValue; - if (action == SWT.NULL) { - keyActionMap.remove(newKey); - } else { - keyActionMap.put(newKey, action); - } - } else { - if (action == SWT.NULL) { - keyActionMap.remove(key); - } else { - keyActionMap.put(key, action); - } - } -} -/** - * Sets the left margin. - * - * @param leftMargin the left margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setLeftMargin (int leftMargin) { - checkWidget(); - setMargins(leftMargin, topMargin, rightMargin, bottomMargin); -} -/** - * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT, - * SWT.CENTER or SWT.RIGHT. - *

    - * Note that if SWT.MULTI is set, then SWT.WRAP must also be set - * in order to stabilize the right edge before setting alignment. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - * - * @param startLine first line the alignment is applied to, 0 based - * @param lineCount number of lines the alignment applies to. - * @param alignment line alignment - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @see #setAlignment(int) - * @since 3.2 - */ -public void setLineAlignment(int startLine, int lineCount, int alignment) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - - renderer.setLineAlignment(startLine, lineCount, alignment); - resetCache(startLine, lineCount); - redrawLines(startLine, lineCount, false); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } - setAlignment(); -} -/** - * Sets the background color of the specified lines. - *

    - * The background color is drawn for the width of the widget. All - * line background colors are discarded when setText is called. - * The text background color if defined in a StyleRange overlays the - * line background color. - *

    - * Should not be called if a LineBackgroundListener has been set since the - * listener maintains the line backgrounds. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the color is applied to, 0 based - * @param lineCount number of lines the color applies to. - * @param background line background color - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - */ -public void setLineBackground(int startLine, int lineCount, Color background) { - checkWidget(); - if (isListening(ST.LineGetBackground)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - if (background != null) { - renderer.setLineBackground(startLine, lineCount, background); - } else { - renderer.clearLineBackground(startLine, lineCount); - } - redrawLines(startLine, lineCount, false); -} -/** - * Sets the bullet of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the bullet is applied to, 0 based - * @param lineCount number of lines the bullet applies to. - * @param bullet line bullet - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @since 3.2 - */ -public void setLineBullet(int startLine, int lineCount, Bullet bullet) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int oldBottom = getLinePixel(startLine + lineCount); - renderer.setLineBullet(startLine, lineCount, bullet); - resetCache(startLine, lineCount); - int newBottom = getLinePixel(startLine + lineCount); - redrawLines(startLine, lineCount, oldBottom != newBottom); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } -} -/** - * Returns true if StyledText is in word wrap mode and false otherwise. - * - * @return true if StyledText is in word wrap mode and false otherwise. - */ -boolean isWordWrap() { - return wordWrap || visualWrap; -} -/** - * Sets the indent of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the indent is applied to, 0 based - * @param lineCount number of lines the indent applies to. - * @param indent line indent - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @see #setIndent(int) - * @since 3.2 - */ -public void setLineIndent(int startLine, int lineCount, int indent) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int oldBottom = getLinePixel(startLine + lineCount); - renderer.setLineIndent(startLine, lineCount, indent); - resetCache(startLine, lineCount); - int newBottom = getLinePixel(startLine + lineCount); - redrawLines(startLine, lineCount, oldBottom != newBottom); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } -} - -/** - * Sets the vertical indent of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * Setting both line spacing and vertical indent on a line would result in the - * spacing and indent add up for the line. - *

    - * - * @param lineIndex line index the vertical indent is applied to, 0 based - * @param verticalLineIndent vertical line indent - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line index is invalid
    • - *
    - * @since 3.109 - */ -public void setLineVerticalIndent(int lineIndex, int verticalLineIndent) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (lineIndex < 0 || lineIndex >= content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int previousVerticalIndent = renderer.getLineVerticalIndent(lineIndex); - if (verticalLineIndent == previousVerticalIndent) { - return; - } - int initialTopPixel = getTopPixel(); - int initialTopIndex = getPartialTopIndex(); - int initialBottomIndex = getPartialBottomIndex(); - int verticalIndentDiff = verticalLineIndent - previousVerticalIndent; - renderer.setLineVerticalIndent(lineIndex, verticalLineIndent); - this.hasVerticalIndent = verticalLineIndent != 0 || renderer.hasVerticalIndent(); - ScrollBar verticalScrollbar = getVerticalBar(); - if (lineIndex < initialTopIndex) { - verticalScrollOffset += verticalIndentDiff; // just change value, don't actually scroll/redraw - if (verticalScrollbar != null) { - verticalScrollbar.setSelection(verticalScrollOffset); - verticalScrollbar.setMaximum(verticalScrollbar.getMaximum() + verticalIndentDiff); - } - } else if (lineIndex > initialBottomIndex) { - if (verticalScrollbar != null) { - verticalScrollbar.setMaximum(verticalScrollbar.getMaximum() + verticalIndentDiff); - } - } else { - resetCache(lineIndex, 1); - if((initialTopIndex == 0) && (initialBottomIndex == (content.getLineCount() - 1))) { // not scrollable editor - setCaretLocations(); - redrawLines(lineIndex, getBottomIndex() - lineIndex + 1, true); - } else if (getFirstCaretLine() >= initialTopIndex && getFirstCaretLine() <= initialBottomIndex) { // caret line with caret mustn't move - if (getFirstCaretLine() < lineIndex) { - redrawLines(lineIndex, getPartialBottomIndex() - lineIndex + 1, true); - } else { - setTopPixel(initialTopPixel + verticalIndentDiff); - } - } else { // move as few lines as possible - if (lineIndex - getTopIndex() < getBottomIndex() - lineIndex) { - setTopPixel(initialTopPixel + verticalIndentDiff); - } else { - // redraw below - redrawLines(lineIndex, getPartialBottomIndex() - lineIndex + 1, true); - } - } - setScrollBars(true); - } -} - -/** - * Sets the justify of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the justify is applied to, 0 based - * @param lineCount number of lines the justify applies to. - * @param justify true if lines should be justified - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @see #setJustify(boolean) - * @since 3.2 - */ -public void setLineJustify(int startLine, int lineCount, boolean justify) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - - renderer.setLineJustify(startLine, lineCount, justify); - resetCache(startLine, lineCount); - redrawLines(startLine, lineCount, false); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } -} -/** - * Sets the line spacing of the widget. The line spacing applies for all lines. - * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized, - * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}. - * - * @param lineSpacing the line spacing - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @see #setLineSpacingProvider(StyledTextLineSpacingProvider) - * @since 3.2 - */ -public void setLineSpacing(int lineSpacing) { - checkWidget(); - if (this.lineSpacing == lineSpacing || lineSpacing < 0) return; - this.lineSpacing = lineSpacing; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing - * or reset the customized spacing if the argument is null. - * - * @param lineSpacingProvider the line spacing provider (or null) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @see #setLineSpacingProvider(StyledTextLineSpacingProvider) - * @since 3.107 - */ -public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) { - checkWidget(); - boolean wasFixedLineHeight = isFixedLineHeight(); - if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null - || (renderer.getLineSpacingProvider() != null - && renderer.getLineSpacingProvider().equals(lineSpacingProvider))) - return; - renderer.setLineSpacingProvider(lineSpacingProvider); - // reset lines cache if needed - if (lineSpacingProvider == null) { - if (!wasFixedLineHeight) { - resetCache(0, content.getLineCount()); - } - } else { - if (wasFixedLineHeight) { - int firstLine = -1; - for (int i = 0; i < content.getLineCount(); i++) { - Integer lineSpacing = lineSpacingProvider.getLineSpacing(i); - if (lineSpacing != null && lineSpacing > 0) { - // there is a custom line spacing, set StyledText as variable line height mode - // reset only the line size - renderer.reset(i, 1); - if (firstLine == -1) { - firstLine = i; - } - } - } - if (firstLine != -1) { - // call reset cache for the first line which have changed to recompute scrollbars - resetCache(firstLine, 0); - } - } - } - setCaretLocations(); - super.redraw(); -} -/** - * Sets the tab stops of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the justify is applied to, 0 based - * @param lineCount number of lines the justify applies to. - * @param tabStops tab stops - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @see #setTabStops(int[]) - * @since 3.6 - */ -public void setLineTabStops(int startLine, int lineCount, int[] tabStops) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - if (tabStops != null) { - int pos = 0; - int[] newTabs = new int[tabStops.length]; - for (int i = 0; i < tabStops.length; i++) { - if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - newTabs[i] = pos = tabStops[i]; - } - renderer.setLineTabStops(startLine, lineCount, newTabs); - } else { - renderer.setLineTabStops(startLine, lineCount, null); - } - resetCache(startLine, lineCount); - redrawLines(startLine, lineCount, false); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } -} -/** - * Sets the wrap indent of the specified lines. - *

    - * Should not be called if a LineStyleListener has been set since the listener - * maintains the line attributes. - *

    - * All line attributes are maintained relative to the line text, not the - * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. - *

    - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - *

    - * - * @param startLine first line the wrap indent is applied to, 0 based - * @param lineCount number of lines the wrap indent applies to. - * @param wrapIndent line wrap indent - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • - *
    - * @see #setWrapIndent(int) - * @since 3.6 - */ -public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (startLine < 0 || startLine + lineCount > content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int oldBottom = getLinePixel(startLine + lineCount); - renderer.setLineWrapIndent(startLine, lineCount, wrapIndent); - resetCache(startLine, lineCount); - int newBottom = getLinePixel(startLine + lineCount); - redrawLines(startLine, lineCount, oldBottom != newBottom); - if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { - setCaretLocations(); - } -} - -/** - * Sets the color of the margins. - * - * @param color the new color (or null) - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • - *
    - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setMarginColor(Color color) { - checkWidget(); - if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - marginColor = color; - super.redraw(); -} -/** - * Sets the margins. - * - * @param leftMargin the left margin. - * @param topMargin the top margin. - * @param rightMargin the right margin. - * @param bottomMargin the bottom margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) { - checkWidget(); - this.leftMargin = Math.max(0, leftMargin) + alignmentMargin; - this.topMargin = Math.max(0, topMargin); - this.rightMargin = Math.max(0, rightMargin); - this.bottomMargin = Math.max(0, bottomMargin); - resetCache(0, content.getLineCount()); - setScrollBars(true); - setCaretLocations(); - setAlignment(); - super.redraw(); -} -/** - * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget - * by pressing the middle button and moving the cursor. - * - * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 3.110 - */ -public void setMouseNavigatorEnabled(boolean enabled) { - checkWidget(); - if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) { - return; - } - if (enabled) { - mouseNavigator = new MouseNavigator(this); - } else { - mouseNavigator.dispose(); - mouseNavigator = null; - } -} -/** - * Flips selection anchor based on word selection direction. - */ -void setMouseWordSelectionAnchor() { - if (doubleClickEnabled && clickCount > 1) { - if (caretOffsets[0] < doubleClickSelection.x) { - selectionAnchors[0] = doubleClickSelection.y; - } else if (caretOffsets[0] > doubleClickSelection.y) { - selectionAnchors[0] = doubleClickSelection.x; - } - } -} -/** - * Sets the orientation of the receiver, which must be one - * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. - * - * @param orientation new orientation style - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 2.1.2 - */ -@Override -public void setOrientation(int orientation) { - int oldOrientation = getOrientation(); - super.setOrientation(orientation); - int newOrientation = getOrientation(); - if (oldOrientation != newOrientation) { - resetBidiData(); - } -} -/** - * Sets the right margin. - * - * @param rightMargin the right margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setRightMargin (int rightMargin) { - checkWidget(); - setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); -} -void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) { - int inactive = 1; - if (clientArea < maximum) { - bar.setMaximum(maximum - margin); - bar.setThumb(clientArea - margin); - bar.setPageIncrement(clientArea - margin); - if (!alwaysShowScroll) bar.setVisible(true); - } else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) { - bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive); - } -} -/** - * Adjusts the maximum and the page size of the scroll bars to - * reflect content width/length changes. - * - * @param vertical indicates if the vertical scrollbar also needs to be set - */ -void setScrollBars(boolean vertical) { - ignoreResize++; - if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true; - ScrollBar verticalBar = vertical ? getVerticalBar() : null; - ScrollBar horizontalBar = getHorizontalBar(); - int oldHeight = clientAreaHeight; - int oldWidth = clientAreaWidth; - if (!alwaysShowScroll) { - if (verticalBar != null) verticalBar.setVisible(false); - if (horizontalBar != null) horizontalBar.setVisible(false); - } - if (verticalBar != null) { - setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin); - } - if (horizontalBar != null && !wordWrap) { - setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin); - if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) { - setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin); - if (verticalBar.getVisible()) { - setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin); - } - } - } - if (!alwaysShowScroll) { - redrawMargins(oldHeight, oldWidth); - } - ignoreResize--; -} -/** - * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). - * - * @param start new caret position - * @see #setSelection(int,int) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a - * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
    - */ -public void setSelection(int start) { - // checkWidget test done in setSelectionRange - setSelection(start, start); -} -/** - * Sets the selection and scrolls it into view. - *

    - * Indexing is zero based. Text selections are specified in terms of - * caret positions. In a text widget that contains N characters, there are - * N+1 caret positions, ranging from 0..N - *

    - * - * @param point x=selection start offset, y=selection end offset - * The caret will be placed at the selection start when x > y. - * @see #setSelection(int,int) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when point is null
    • - *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a - * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
    - */ -public void setSelection(Point point) { - checkWidget(); - if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - setSelection(point.x, point.y); -} -/** - * Sets the receiver's selection background color to the color specified - * by the argument, or to the default system color for the control - * if the argument is null. - * - * @param color the new color (or null) - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • - *
    - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.1 - */ -public void setSelectionBackground (Color color) { - checkWidget (); - if (color != null) { - if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - selectionBackground = color; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the receiver's selection foreground color to the color specified - * by the argument, or to the default system color for the control - * if the argument is null. - *

    - * Note that this is a HINT. Some platforms do not allow the application - * to change the selection foreground color. - *

    - * @param color the new color (or null) - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • - *
    - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.1 - */ -public void setSelectionForeground (Color color) { - checkWidget (); - if (color != null) { - if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - selectionForeground = color; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the selection and scrolls it into view. - *

    - * Indexing is zero based. Text selections are specified in terms of - * caret positions. In a text widget that contains N characters, there are - * N+1 caret positions, ranging from 0..N - *

    - * - * @param start selection start offset. The caret will be placed at the - * selection start when start > end. - * @param end selection end offset - * @see #setSelectionRange(int,int) - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a - * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
    - */ -public void setSelection(int start, int end) { - setSelectionRange(start, end - start); - showSelection(); -} -/** - * Sets the selection. - *

    - * The new selection may not be visible. Call showSelection to scroll - * the selection into view. - *

    - * - * @param start offset of the first selected character, start >= 0 must be true. - * @param length number of characters to select, 0 <= start + length - * <= getCharCount() must be true. - * A negative length places the caret at the selection start. - * @param sendEvent a Selection event is sent when set to true and when - * the selection is reset. - */ -void setSelection(int[] regions, boolean sendEvent, boolean doBlock) { - if (regions.length == 2 && selection.length == 1) { // single range before/after - int start = regions[0]; - int length = regions[1]; - int end = start + length; - if (start > end) { - int temp = end; - end = start; - start = temp; - } - int selectionAnchor = selectionAnchors[0]; - // is the selection range different or is the selection direction - // different? - if (selection[0].x != start || selection[0].y != end || - (length > 0 && selectionAnchor != selection[0].x) || - (length < 0 && selectionAnchor != selection[0].y)) { - if (blockSelection && doBlock) { - if (length < 0) { - setBlockSelectionOffset(end, start, sendEvent); - } else { - setBlockSelectionOffset(start, end, sendEvent); - } - } else { - int oldStart = selection[0].x; - int oldLength = selection[0].y - selection[0].x; - int charCount = content.getCharCount(); - // called internally to remove selection after text is removed - // therefore make sure redraw range is valid. - int redrawX = Math.min(selection[0].x, charCount); - int redrawY = Math.min(selection[0].y, charCount); - if (length < 0) { - selectionAnchors[0] = selectionAnchor = selection[0].y = end; - selection[0].x = start; - setCaretOffsets(new int[] {start}, PREVIOUS_OFFSET_TRAILING); - } else { - selectionAnchors[0] = selectionAnchor = selection[0].x = start; - selection[0].y = end; - setCaretOffsets(new int[] {end}, PREVIOUS_OFFSET_TRAILING); - } - redrawX = Math.min(redrawX, selection[0].x); - redrawY = Math.max(redrawY, selection[0].y); - if (redrawY - redrawX > 0) { - internalRedrawRange(redrawX, redrawY - redrawX); - } - if (sendEvent && (oldLength != end - start || (oldLength != 0 && oldStart != start))) { - sendSelectionEvent(); - } - sendAccessibleTextCaretMoved(); - } - } - } else if (!blockSelection || !doBlock) { - boolean caretAtEndOfSelection = regions[1] > 0; - int charCount = content.getCharCount(); - Point[] newRanges = new Point[regions.length / 2]; - for (int i = 0; i < regions.length; i += 2) { - int start = regions[i]; - int length = regions[i + 1]; - int end = start + length; - if (start > end) { - int temp = end; - end = start; - start = temp; - } - newRanges[i / 2] = new Point(start, end); - } - Arrays.sort(newRanges, SELECTION_COMPARATOR); - // merge contiguous ranges - int newRangeIndex = 0; - for (Point range : newRanges) { - if (newRangeIndex > 0) { - Point previousRange = newRanges[newRangeIndex - 1]; - if (previousRange.y >= range.x) { - previousRange.y = Math.max(previousRange.y, range.y); - } else { - newRanges[newRangeIndex] = range; - newRangeIndex++; - } - } else { - newRanges[newRangeIndex] = range; - newRangeIndex++; - } - } - Point[] toRedraw = new Point[newRangeIndex + selection.length]; - System.arraycopy(newRanges, 0, toRedraw, 0, newRangeIndex); - System.arraycopy(selection, 0, toRedraw, newRangeIndex, selection.length); - Arrays.sort(toRedraw, SELECTION_COMPARATOR); - Point[] formerSelection = selection; - selection = Arrays.copyOf(newRanges, newRangeIndex); - Point currentToRedraw = null; - for (Point p : toRedraw) { - if (currentToRedraw == null) { - currentToRedraw = new Point(p.x, p.y); - } else if (currentToRedraw.y >= p.x - 1) { - // expand if necessary - currentToRedraw = new Point(currentToRedraw.x, Math.max(p.y, currentToRedraw.y)); - } else { - currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y)); - internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x); - currentToRedraw = null; - } - } - if (currentToRedraw != null) { - currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y)); - internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x); - } - if (!caretAtEndOfSelection) { - selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.y).toArray(); - setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.x).toArray(), PREVIOUS_OFFSET_TRAILING); - } else { - selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.x).toArray(); - setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.y).toArray(), PREVIOUS_OFFSET_TRAILING); - } - setCaretLocations(); - if (sendEvent && !Arrays.equals(formerSelection, selection)) { - sendSelectionEvent(); - } - sendAccessibleTextCaretMoved(); - } -} -/** - * Sets the selection. - *

    - * The new selection may not be visible. Call showSelection to scroll the selection - * into view. A negative length places the caret at the visual start of the selection. - *

    - * - * @param start offset of the first selected character - * @param length number of characters to select - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a - * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
    - */ -public void setSelectionRange(int start, int length) { - setSelectionRanges(new int[] { start, length }); -} - -/** - * Sets the selected locations/ranges. - *

    - * The new selection may not be visible. Call showSelection to scroll the selection - * into view. A negative length places the caret at the visual start of the selection. - *

    - * - * @param ranges an array of offset/length pairs. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT when either the start or the end of one selection range is inside a - * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
    • - *
    • ERROR_INVALID_ARGUMENT when ranges are null or size isn't valid (not pair)
    • - *
    - * @see #getSelectionRanges() - * @since 3.117 - */ -public void setSelectionRanges(int[] ranges) { - checkWidget(); - int contentLength = getCharCount(); - if (ranges.length % 2 != 0) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int[] fixedRanges = Arrays.copyOf(ranges, ranges.length); - for (int i = 0; i < ranges.length; i+=2) { - int start = ranges[i]; - start = Math.max(0, Math.min(start, contentLength)); - int length = ranges[i + 1]; - int end = start + length; - if (end < 0) { - length = -start; - } else if (end > contentLength) { - length = contentLength - start; - } - if (isLineDelimiter(start) || isLineDelimiter(start + length)) { - // the start offset or end offset of the selection range is inside a - // multi byte line delimiter. This is an illegal operation and an exception - // is thrown. Fixes 1GDKK3R - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - fixedRanges[i] = start; - fixedRanges[i + 1] = length; - } - setSelection(fixedRanges, false, true); - setCaretLocations(); -} - -/** - * Adds the specified style. - *

    - * The new style overwrites existing styles for the specified range. - * Existing style ranges are adjusted if they partially overlap with - * the new style. To clear an individual style, call setStyleRange - * with a StyleRange that has null attributes. - *

    - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param range StyleRange object containing the style information. - * Overwrites the old style in the given range. May be null to delete - * all styles. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
    • - *
    - */ -public void setStyleRange(StyleRange range) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (range != null) { - if (range.isUnstyled()) { - setStyleRanges(range.start, range.length, null, null, false); - } else { - setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); - } - } else { - setStyleRanges(0, 0, null, null, true); - } -} -/** - * Clears the styles in the range specified by start and - * length and adds the new styles. - *

    - * The ranges array contains start and length pairs. Each pair refers to - * the corresponding style in the styles array. For example, the pair - * that starts at ranges[n] with length ranges[n+1] uses the style - * at styles[n/2]. The range fields within each StyleRange are ignored. - * If ranges or styles is null, the specified range is cleared. - *

    - * Note: It is expected that the same instance of a StyleRange will occur - * multiple times within the styles array, reducing memory usage. - *

    - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param start offset of first character where styles will be deleted - * @param length length of the range to delete styles in - * @param ranges the array of ranges. The ranges must not overlap and must be in order. - * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • - *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • - *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • - *
    • ERROR_INVALID_RANGE when a range overlaps
    • - *
    - * - * @since 3.2 - */ -public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (ranges == null || styles == null) { - setStyleRanges(start, length, null, null, false); - } else { - setStyleRanges(start, length, ranges, styles, false); - } -} -/** - * Sets styles to be used for rendering the widget content. - *

    - * All styles in the widget will be replaced with the given set of ranges and styles. - * The ranges array contains start and length pairs. Each pair refers to - * the corresponding style in the styles array. For example, the pair - * that starts at ranges[n] with length ranges[n+1] uses the style - * at styles[n/2]. The range fields within each StyleRange are ignored. - * If either argument is null, the styles are cleared. - *

    - * Note: It is expected that the same instance of a StyleRange will occur - * multiple times within the styles array, reducing memory usage. - *

    - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param ranges the array of ranges. The ranges must not overlap and must be in order. - * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • - *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • - *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • - *
    • ERROR_INVALID_RANGE when a range overlaps
    • - *
    - * - * @since 3.2 - */ -public void setStyleRanges(int[] ranges, StyleRange[] styles) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (ranges == null || styles == null) { - setStyleRanges(0, 0, null, null, true); - } else { - setStyleRanges(0, 0, ranges, styles, true); - } -} -void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) { - int charCount = content.getCharCount(); - if (reset) { - start = 0; - length = charCount; - } - int[] formerRanges = getRanges(start, length); - StyleRange[] formerStyles = getStyleRanges(start, length); - int end = start + length; - final boolean wasFixedLineHeight = isFixedLineHeight(); - if (start > end || start < 0) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (styles != null) { - if (end > charCount) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - if (ranges != null) { - if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - int lastOffset = 0; - for (int i = 0; i < styles.length; i ++) { - if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - int rangeStart, rangeLength; - if (ranges != null) { - rangeStart = ranges[i << 1]; - rangeLength = ranges[(i << 1) + 1]; - } else { - rangeStart = styles[i].start; - rangeLength = styles[i].length; - } - if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - hasStyleWithVariableHeight |= styles[i].isVariableHeight(); - lastOffset = rangeStart + rangeLength; - } - } - int rangeStart = start, rangeEnd = end; - if (styles != null && styles.length > 0) { - if (ranges != null) { - rangeStart = ranges[0]; - rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1]; - } else { - rangeStart = styles[0].start; - rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length; - } - } +// String line = content.getLine(i); +// int lineOffset = content.getOffsetAtLine(i); +// StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line); +// if (event != null && event.lineBackground != null) { +// printerRenderer.setLineBackground(i, 1, event.lineBackground); +// } +// event = styledText.getBidiSegments(lineOffset, line); +// if (event != null) { +// printerRenderer.setLineSegments(i, 1, event.segments); +// printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars); +// } +// event = styledText.getLineStyleData(lineOffset, line); +// if (event != null) { +// printerRenderer.setLineIndent(i, 1, event.indent); +// printerRenderer.setLineAlignment(i, 1, event.alignment); +// printerRenderer.setLineJustify(i, 1, event.justify); +// printerRenderer.setLineBullet(i, 1, event.bullet); +// StyleRange[] styles = event.styles; +// if (styles != null && styles.length > 0) { +// printerRenderer.setStyleRanges(event.ranges, styles); +// } +// } +// } +// } +// Point screenDPI = styledText.getDisplay().getDPI(); +// Point printerDPI = printer.getDPI(); +// resources = new HashMap<> (); +// for (int i = 0; i < lineCount; i++) { +// Color color = printerRenderer.getLineBackground(i, null); +// if (color != null) { +// if (printOptions.printLineBackground) { +// Color printerColor = (Color)resources.get(color); +// if (printerColor == null) { +// printerColor = new Color (color.getRGB()); +// resources.put(color, printerColor); +// } +// printerRenderer.setLineBackground(i, 1, printerColor); +// } else { +// printerRenderer.setLineBackground(i, 1, null); +// } +// } +// int indent = printerRenderer.getLineIndent(i, 0); +// if (indent != 0) { +// printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x); +// } +// } +// StyleRange[] styles = printerRenderer.styles; +// for (int i = 0; i < printerRenderer.styleCount; i++) { +// StyleRange style = styles[i]; +// Font font = style.font; +// if (style.font != null) { +// Font printerFont = (Font)resources.get(font); +// if (printerFont == null) { +// printerFont = new Font (printer, font.getFontData()); +// resources.put(font, printerFont); +// } +// style.font = printerFont; +// } +// Color color = style.foreground; +// if (color != null) { +// Color printerColor = (Color)resources.get(color); +// if (printOptions.printTextForeground) { +// if (printerColor == null) { +// printerColor = new Color (color.getRGB()); +// resources.put(color, printerColor); +// } +// style.foreground = printerColor; +// } else { +// style.foreground = null; +// } +// } +// color = style.background; +// if (color != null) { +// Color printerColor = (Color)resources.get(color); +// if (printOptions.printTextBackground) { +// if (printerColor == null) { +// printerColor = new Color (color.getRGB()); +// resources.put(color, printerColor); +// } +// style.background = printerColor; +// } else { +// style.background = null; +// } +// } +// if (!printOptions.printTextFontStyle) { +// style.fontStyle = SWT.NORMAL; +// } +// style.rise = style.rise * printerDPI.y / screenDPI.y; +// GlyphMetrics metrics = style.metrics; +// if (metrics != null) { +// metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y; +// metrics.descent = metrics.descent * printerDPI.y / screenDPI.y; +// metrics.width = metrics.width * printerDPI.x / screenDPI.x; +// } +// } +// lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y; +// if (printOptions.printLineNumbers) { +// printMargin = 3 * printerDPI.x / screenDPI.x; +// } +// } +// /** +// * Copies the text of the specified StyledTextContent. +// * +// * @param original the StyledTextContent to copy. +// */ +// StyledTextContent copyContent(StyledTextContent original) { +// StyledTextContent printerContent = new DefaultContent(); +// int insertOffset = 0; +// for (int i = 0; i < original.getLineCount(); i++) { +// int insertEndOffset; +// if (i < original.getLineCount() - 1) { +// insertEndOffset = original.getOffsetAtLine(i + 1); +// } else { +// insertEndOffset = original.getCharCount(); +// } +// printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset)); +// insertOffset = insertEndOffset; +// } +// return printerContent; +// } +// /** +// * Disposes of the resources and the PrintRenderer. +// */ +// void dispose() { +// if (gc != null) { +// gc.dispose(); +// gc = null; +// } +// if (resources != null) { +// for (Resource resource : resources.values()) { +// resource.dispose(); +// } +// resources = null; +// } +// if (printerFont != null) { +// printerFont.dispose(); +// printerFont = null; +// } +// if (printerRenderer != null) { +// printerRenderer.dispose(); +// printerRenderer = null; +// } +// } +// void init() { +// Rectangle trim = printer.computeTrim(0, 0, 0, 0); +// Point dpi = printer.getDPI(); +// +// printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL); +// clientArea = printer.getClientArea(); +// pageWidth = clientArea.width; +// // one inch margin around text +// clientArea.x = dpi.x + trim.x; +// clientArea.y = dpi.y + trim.y; +// clientArea.width -= (clientArea.x + trim.width); +// clientArea.height -= (clientArea.y + trim.height); +// +// int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; +// gc = new GC(printer, style); +// gc.setFont(printerFont); +// printerRenderer.setFont(printerFont, tabLength); +// int lineHeight = printerRenderer.getLineHeight(); +// if (printOptions.header != null) { +// clientArea.y += lineHeight * 2; +// clientArea.height -= lineHeight * 2; +// } +// if (printOptions.footer != null) { +// clientArea.height -= lineHeight * 2; +// } +// +// // TODO not wrapped +// StyledTextContent content = printerRenderer.content; +// startLine = 0; +// endLine = singleLine ? 0 : content.getLineCount() - 1; +// if (scope == PrinterData.PAGE_RANGE) { +// int pageSize = clientArea.height / lineHeight;//WRONG +// startLine = (startPage - 1) * pageSize; +// } else if (scope == PrinterData.SELECTION) { +// startLine = content.getLineAtOffset(selection[0].x); +// if (selection[0].y > 0) { +// endLine = content.getLineAtOffset(selection[0].y); +// } else { +// endLine = startLine - 1; +// } +// } +// } +// /** +// * Prints the lines in the specified page range. +// */ +// void print() { +// Color background = gc.getBackground(); +// Color foreground = gc.getForeground(); +// int paintY = clientArea.y; +// int paintX = clientArea.x; +// int width = clientArea.width; +// int page = startPage; +// int pageBottom = clientArea.y + clientArea.height; +// int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT); +// TextLayout printLayout = null; +// if (printOptions.printLineNumbers || printOptions.header != null || printOptions.footer != null) { +// printLayout = new TextLayout(printer); +// printLayout.setFont(printerFont); +// } +// if (printOptions.printLineNumbers) { +// int numberingWidth = 0; +// int count = endLine - startLine + 1; +// String[] lineLabels = printOptions.lineLabels; +// if (lineLabels != null) { +// for (int i = startLine; i < Math.min(count, lineLabels.length); i++) { +// if (lineLabels[i] != null) { +// printLayout.setText(lineLabels[i]); +// int lineWidth = printLayout.getBounds().width; +// numberingWidth = Math.max(numberingWidth, lineWidth); +// } +// } +// } else { +// StringBuilder buffer = new StringBuilder("0"); +// while ((count /= 10) > 0) buffer.append("0"); +// printLayout.setText(buffer.toString()); +// numberingWidth = printLayout.getBounds().width; +// } +// numberingWidth += printMargin; +// if (numberingWidth > width) numberingWidth = width; +// paintX += numberingWidth; +// width -= numberingWidth; +// } +// for (int i = startLine; i <= endLine && page <= endPage; i++) { +// if (paintY == clientArea.y) { +// printer.startPage(); +// printDecoration(page, true, printLayout); +// } +// TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); +// Color lineBackground = printerRenderer.getLineBackground(i, background); +// int paragraphBottom = paintY + layout.getBounds().height; +// if (paragraphBottom <= pageBottom) { +// //normal case, the whole paragraph fits in the current page +// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); +// paintY = paragraphBottom; +// } else { +// int lineCount = layout.getLineCount(); +// while (paragraphBottom > pageBottom && lineCount > 0) { +// lineCount--; +// paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing(); +// } +// if (lineCount == 0) { +// //the whole paragraph goes to the next page +// printDecoration(page, false, printLayout); +// printer.endPage(); +// page++; +// if (page <= endPage) { +// printer.startPage(); +// printDecoration(page, true, printLayout); +// paintY = clientArea.y; +// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); +// paintY += layout.getBounds().height; +// } +// } else { +// //draw paragraph top in the current page and paragraph bottom in the next +// int height = paragraphBottom - paintY; +// gc.setClipping(clientArea.x, paintY, clientArea.width, height); +// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); +// gc.setClipping((Rectangle)null); +// printDecoration(page, false, printLayout); +// printer.endPage(); +// page++; +// if (page <= endPage) { +// printer.startPage(); +// printDecoration(page, true, printLayout); +// paintY = clientArea.y - height; +// int layoutHeight = layout.getBounds().height; +// gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height); +// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); +// gc.setClipping((Rectangle)null); +// paintY += layoutHeight; +// } +// } +// } +// printerRenderer.disposeTextLayout(layout); +// } +// if (page <= endPage && paintY > clientArea.y) { +// // close partial page +// printDecoration(page, false, printLayout); +// printer.endPage(); +// } +// if (printLayout != null) printLayout.dispose(); +// } +// /** +// * Print header or footer decorations. +// * +// * @param page page number to print, if specified in the StyledTextPrintOptions header or footer. +// * @param header true = print the header, false = print the footer +// */ +// void printDecoration(int page, boolean header, TextLayout layout) { +// String text = header ? printOptions.header : printOptions.footer; +// if (text == null) return; +// int lastSegmentIndex = 0; +// for (int i = 0; i < 3; i++) { +// int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); +// String segment; +// if (segmentIndex == -1) { +// segment = text.substring(lastSegmentIndex); +// printDecorationSegment(segment, i, page, header, layout); +// break; +// } else { +// segment = text.substring(lastSegmentIndex, segmentIndex); +// printDecorationSegment(segment, i, page, header, layout); +// lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); +// } +// } +// } +// /** +// * Print one segment of a header or footer decoration. +// * Headers and footers have three different segments. +// * One each for left aligned, centered, and right aligned text. +// * +// * @param segment decoration segment to print +// * @param alignment alignment of the segment. 0=left, 1=center, 2=right +// * @param page page number to print, if specified in the decoration segment. +// * @param header true = print the header, false = print the footer +// */ +// void printDecorationSegment(String segment, int alignment, int page, boolean header, TextLayout layout) { +// int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); +// if (pageIndex != -1) { +// int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); +// StringBuilder buffer = new StringBuilder(segment.substring (0, pageIndex)); +// buffer.append (page); +// buffer.append (segment.substring(pageIndex + pageTagLength)); +// segment = buffer.toString(); +// } +// if (segment.length() > 0) { +// layout.setText(segment); +// int segmentWidth = layout.getBounds().width; +// int segmentHeight = printerRenderer.getLineHeight(); +// int drawX = 0, drawY; +// if (alignment == LEFT) { +// drawX = clientArea.x; +// } else if (alignment == CENTER) { +// drawX = (pageWidth - segmentWidth) / 2; +// } else if (alignment == RIGHT) { +// drawX = clientArea.x + clientArea.width - segmentWidth; +// } +// if (header) { +// drawY = clientArea.y - segmentHeight * 2; +// } else { +// drawY = clientArea.y + clientArea.height + segmentHeight; +// } +// layout.draw(gc, drawX, drawY); +// } +// } +// void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) { +// if (background != null) { +// Rectangle rect = layout.getBounds(); +// gc.setBackground(background); +// gc.fillRectangle(x, y, rect.width, rect.height); +// +//// int lineCount = layout.getLineCount(); +//// for (int i = 0; i < lineCount; i++) { +//// Rectangle rect = layout.getLineBounds(i); +//// rect.x += paintX; +//// rect.y += paintY + layout.getSpacing(); +//// rect.width = width;//layout bounds +//// gc.fillRectangle(rect); +//// } +// } +// if (printOptions.printLineNumbers) { +// FontMetrics metrics = layout.getLineMetrics(0); +// printLayout.setAscent(metrics.getAscent() + metrics.getLeading()); +// printLayout.setDescent(metrics.getDescent()); +// String[] lineLabels = printOptions.lineLabels; +// if (lineLabels != null) { +// if (0 <= index && index < lineLabels.length && lineLabels[index] != null) { +// printLayout.setText(lineLabels[index]); +// } else { +// printLayout.setText(""); +// } +// } else { +// printLayout.setText(String.valueOf(index)); +// } +// int paintX = x - printMargin - printLayout.getBounds().width; +// printLayout.draw(gc, paintX, y); +// printLayout.setAscent(-1); +// printLayout.setDescent(-1); +// } +// gc.setForeground(foreground); +// layout.draw(gc, x, y); +// } +// /** +// * Starts a print job and prints the pages specified in the constructor. +// */ +// @Override +// public void run() { +// String jobName = printOptions.jobName; +// if (jobName == null) { +// jobName = "Printing"; +// } +// if (printer.startJob(jobName)) { +// init(); +// print(); +// dispose(); +// printer.endJob(); +// } +// } +// } +// +///** +// * Constructs a new instance of this class given its parent +// * and a style value describing its behavior and appearance. +// *

    +// * The style value is either one of the style constants defined in +// * class SWT which is applicable to instances of this +// * class, or must be built by bitwise OR'ing together +// * (that is, using the int "|" operator) two or more +// * of those SWT style constants. The class description +// * lists the style constants that are applicable to the class. +// * Style bits are also inherited from superclasses. +// *

    +// * +// * @param parent a widget which will be the parent of the new instance (cannot be null) +// * @param style the style of widget to construct +// * +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • +// *
    +// * +// * @see SWT#FULL_SELECTION +// * @see SWT#MULTI +// * @see SWT#READ_ONLY +// * @see SWT#SINGLE +// * @see SWT#WRAP +// * @see #getStyle +// */ +//public StyledText(Composite parent, int style) { +// super(parent, checkStyle(style)); +// // set the fg in the OS to ensure that these are the same as StyledText, necessary +// // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses +// super.setForeground(getForeground()); +// super.setDragDetect(false); +// Display display = getDisplay(); +// if ((style & SWT.READ_ONLY) != 0) { +// setEditable(false); +// } +// leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0; +// if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) { +// leftMargin = topMargin = rightMargin = bottomMargin = 2; +// } +// alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); +// if (alignment == 0) alignment = SWT.LEFT; +// clipboard = new Clipboard(display); +// installDefaultContent(); +// renderer = new StyledTextRenderer(getDisplay(), this); +// renderer.setContent(content); +// renderer.setFont(getFont(), tabLength); +// ime = new IME(this, SWT.NONE); +// defaultCaret = new Caret(this, SWT.NONE); +// if ((style & SWT.WRAP) != 0) { +// setWordWrap(true); +// } +// if (isBidiCaret()) { +// createCaretBitmaps(); +// Runnable runnable = () -> { +// int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT; +// if (direction == caretDirection) return; +// if (getCaret() != defaultCaret) return; +// setCaretLocations(Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new), direction); +// }; +// BidiUtil.addLanguageListener(this, runnable); +// } +// setCaret(defaultCaret); +// calculateScrollBars(); +// createKeyBindings(); +// super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM)); +// installListeners(); +// initializeAccessible(); +// setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); +// if (IS_MAC) setData(STYLEDTEXT_KEY); +//} +///** +// * Adds an extended modify listener. An ExtendedModify event is sent by the +// * widget when the widget text has changed. +// * +// * @param extendedModifyListener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { +// checkWidget(); +// if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// StyledTextListener typedListener = new StyledTextListener(extendedModifyListener); +// addListener(ST.ExtendedModify, typedListener); +//} +///** +// * Adds a bidirectional segment listener. +// *

    +// * A BidiSegmentEvent is sent +// * whenever a line of text is measured or rendered. You can +// * specify text ranges in the line that should be treated as if they +// * had a different direction than the surrounding text. +// * This may be used when adjacent segments of right-to-left text should +// * not be reordered relative to each other. +// * E.g., multiple Java string literals in a right-to-left language +// * should generally remain in logical order to each other, that is, the +// * way they are stored. +// *

    +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * @see BidiSegmentEvent +// * @since 2.0 +// */ +//public void addBidiSegmentListener(BidiSegmentListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// addListener(ST.LineGetSegments, new StyledTextListener(listener)); +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Adds a caret listener. CaretEvent is sent when the caret offset changes. +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @since 3.5 +// */ +//public void addCaretListener(CaretListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// addListener(ST.CaretMoved, new StyledTextListener(listener)); +//} +///** +// * Adds a line background listener. A LineGetBackground event is sent by the +// * widget to determine the background color for a line. +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addLineBackgroundListener(LineBackgroundListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// if (!isListening(ST.LineGetBackground)) { +// renderer.clearLineBackground(0, content.getLineCount()); +// } +// addListener(ST.LineGetBackground, new StyledTextListener(listener)); +//} +///** +// * Adds a line style listener. A LineGetStyle event is sent by the widget to +// * determine the styles for a line. +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addLineStyleListener(LineStyleListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// if (!isListening(ST.LineGetStyle)) { +// setStyleRanges(0, 0, null, null, true); +// renderer.clearLineStyle(0, content.getLineCount()); +// } +// addListener(ST.LineGetStyle, new StyledTextListener(listener)); +// setCaretLocations(); +//} +///** +// * Adds a modify listener. A Modify event is sent by the widget when the widget text +// * has changed. +// * +// * @param modifyListener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addModifyListener(ModifyListener modifyListener) { +// addTypedListener(modifyListener, SWT.Modify); +//} +///** +// * Adds a paint object listener. A paint object event is sent by the widget when an object +// * needs to be drawn. +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @since 3.2 +// * +// * @see PaintObjectListener +// * @see PaintObjectEvent +// */ +//public void addPaintObjectListener(PaintObjectListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// addListener(ST.PaintObject, new StyledTextListener(listener)); +//} +///** +// * Adds a selection listener. A Selection event is sent by the widget when the +// * user changes the selection. +// *

    +// * When widgetSelected is called, the event x and y fields contain +// * the start and end caret indices of the selection[0]. The selection values returned are visual +// * (i.e., x will always always be <= y). +// * No event is sent when the caret is moved while the selection length is 0. +// *

    +// * widgetDefaultSelected is not called for StyledTexts. +// *

    +// * +// * @param listener the listener which should be notified when the user changes the receiver's selection +// +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see SelectionListener +// * @see #removeSelectionListener +// * @see SelectionEvent +// */ +//public void addSelectionListener(SelectionListener listener) { +// addTypedListener(listener, SWT.Selection); +//} +///** +// * Adds a verify key listener. A VerifyKey event is sent by the widget when a key +// * is pressed. The widget ignores the key press if the listener sets the doit field +// * of the event to false. +// * +// * @param listener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addVerifyKeyListener(VerifyKeyListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// addListener(ST.VerifyKey, new StyledTextListener(listener)); +//} +///** +// * Adds a verify listener. A Verify event is sent by the widget when the widget text +// * is about to change. The listener can set the event text and the doit field to +// * change the text that is set in the widget or to force the widget to ignore the +// * text change. +// * +// * @param verifyListener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void addVerifyListener(VerifyListener verifyListener) { +// addTypedListener(verifyListener, SWT.Verify); +//} +///** +// * Adds a word movement listener. A movement event is sent when the boundary +// * of a word is needed. For example, this occurs during word next and word +// * previous actions. +// * +// * @param movementListener the listener +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @see MovementEvent +// * @see MovementListener +// * @see #removeWordMovementListener +// * +// * @since 3.3 +// */ +//public void addWordMovementListener(MovementListener movementListener) { +// checkWidget(); +// if (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// addListener(ST.WordNext, new StyledTextListener(movementListener)); +// addListener(ST.WordPrevious, new StyledTextListener(movementListener)); +//} +///** +// * Appends a string to the text at the end of the widget. +// * +// * @param string the string to be appended +// * @see #replaceTextRange(int,int,String) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void append(String string) { +// checkWidget(); +// if (string == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// int lastChar = Math.max(getCharCount(), 0); +// replaceTextRange(lastChar, 0, string); +//} +///** +// * Calculates the scroll bars +// */ +//void calculateScrollBars() { +// ScrollBar horizontalBar = getHorizontalBar(); +// ScrollBar verticalBar = getVerticalBar(); +// setScrollBars(true); +// if (verticalBar != null) { +// verticalBar.setIncrement(getVerticalIncrement()); +// } +// if (horizontalBar != null) { +// horizontalBar.setIncrement(getHorizontalIncrement()); +// } +//} +///** +// * Calculates the top index based on the current vertical scroll offset. +// * The top index is the index of the topmost fully visible line or the +// * topmost partially visible line if no line is fully visible. +// * The top index starts at 0. +// */ +//void calculateTopIndex(int delta) { +// int oldDelta = delta; +// int oldTopIndex = topIndex; +// int oldTopIndexY = topIndexY; +// if (isFixedLineHeight()) { +// int verticalIncrement = getVerticalIncrement(); +// if (verticalIncrement == 0) { +// return; +// } +// topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); +// // Set top index to partially visible top line if no line is fully +// // visible but at least some of the widget client area is visible. +// // Fixes bug 15088. +// if (topIndex >= 0) { +// if (clientAreaHeight > 0) { +// int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; +// topIndexY = getLinePixel(topIndex); +// int fullLineTopPixel = topIndex * verticalIncrement; +// int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; +// // set top index to partially visible line if no line fully fits in +// // client area or if space is available but not used (the latter should +// // never happen because we use claimBottomFreeSpace) +// if (fullLineVisibleHeight < verticalIncrement) { +// topIndex = getVerticalScrollOffset() / verticalIncrement; +// } +// } else if (topIndex >= content.getLineCount()) { +// topIndex = content.getLineCount() - 1; +// } +// } +// } else { +// if (delta >= 0) { +// delta -= topIndexY; +// int lineIndex = topIndex; +// int lineCount = content.getLineCount(); +// while (lineIndex < lineCount) { +// if (delta <= 0) break; +// delta -= renderer.getCachedLineHeight(lineIndex++); +// } +// if (lineIndex < lineCount && -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { +// topIndex = lineIndex; +// topIndexY = -delta; +// } else { +// topIndex = lineIndex - 1; +// topIndexY = -renderer.getCachedLineHeight(topIndex) - delta; +// } +// } else { +// delta -= topIndexY; +// int lineIndex = topIndex; +// while (lineIndex > 0) { +// int lineHeight = renderer.getCachedLineHeight(lineIndex - 1); +// if (delta + lineHeight > 0) break; +// delta += lineHeight; +// lineIndex--; +// } +// if (lineIndex == 0 || -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { +// topIndex = lineIndex; +// topIndexY = - delta; +// } else { +// topIndex = lineIndex - 1; +// topIndexY = - renderer.getCachedLineHeight(topIndex) - delta; +// } +// } +// } +// if (topIndex < 0) { +// // TODO: This logging is in place to determine why topIndex is getting set to negative values. +// // It should be deleted once we fix the root cause of this issue. See bug 487254 for details. +// System.err.println("StyledText: topIndex was " + topIndex +// + ", isFixedLineHeight() = " + isFixedLineHeight() +// + ", delta = " + delta +// + ", content.getLineCount() = " + content.getLineCount() +// + ", clientAreaHeight = " + clientAreaHeight +// + ", oldTopIndex = " + oldTopIndex +// + ", oldTopIndexY = " + oldTopIndexY +// + ", getVerticalScrollOffset = " + getVerticalScrollOffset() +// + ", oldDelta = " + oldDelta +// + ", getVerticalIncrement() = " + getVerticalIncrement()); +// topIndex = 0; +// } +// if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) { +// int width = renderer.getWidth(); +// renderer.calculateClientArea(); +// if (width != renderer.getWidth()) { +// setScrollBars(false); +// } +// } +//} +///** +// * Hides the scroll bars if widget is created in single line mode. +// */ +//static int checkStyle(int style) { +// if ((style & SWT.SINGLE) != 0) { +// style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI); +// } else { +// style |= SWT.MULTI; +// if ((style & SWT.WRAP) != 0) { +// style &= ~SWT.H_SCROLL; +// } +// } +// style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND; +// /* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */ +// return style & ~SWT.CENTER; +//} +///** +// * Scrolls down the text to use new space made available by a resize or by +// * deleted lines. +// */ +//void claimBottomFreeSpace() { +// if (ime.getCompositionOffset() != -1) return; +// if (isFixedLineHeight()) { +// int newVerticalOffset = Math.max(0, renderer.getHeight() - clientAreaHeight); +// if (newVerticalOffset < getVerticalScrollOffset()) { +// scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true); +// } +// } else { +// int bottomIndex = getPartialBottomIndex(); +// int height = getLinePixel(bottomIndex + 1); +// if (clientAreaHeight > height) { +// scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true); +// } +// } +//} +///** +// * Scrolls text to the right to use new space made available by a resize. +// */ +//void claimRightFreeSpace() { +// int newHorizontalOffset = Math.max(0, renderer.getWidth() - clientAreaWidth); +// if (newHorizontalOffset < horizontalScrollOffset) { +// // item is no longer drawn past the right border of the client area +// // align the right end of the item with the right border of the +// // client area (window is scrolled right). +// scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); +// } +//} +//void clearBlockSelection(boolean reset, boolean sendEvent) { +// if (reset) resetSelection(); +// blockXAnchor = blockYAnchor = -1; +// blockXLocation = blockYLocation = -1; +// caretDirection = SWT.NULL; +// updateCaretVisibility(); +// super.redraw(); +// if (sendEvent) sendSelectionEvent(); +//} +///** +// * Removes the widget selection. +// * +// * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. +// */ +//void clearSelection(boolean sendEvent) { +// int selectionStart = selection[0].x; +// int selectionEnd = selection[0].y; +// resetSelection(); +// // redraw old selection, if any +// if (selectionEnd - selectionStart > 0) { +// int length = content.getCharCount(); +// // called internally to remove selection after text is removed +// // therefore make sure redraw range is valid. +// int redrawStart = Math.min(selectionStart, length); +// int redrawEnd = Math.min(selectionEnd, length); +// if (redrawEnd - redrawStart > 0) { +// internalRedrawRange(redrawStart, redrawEnd - redrawStart); +// } +// if (sendEvent) { +// sendSelectionEvent(); +// } +// } +//} +//@Override +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget(); +// int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount(); +// int width = 0; +// int height = 0; +// if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { +// Display display = getDisplay(); +// int maxHeight = display.getClientArea().height; +// for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int wrapWidth = layout.getWidth(); +// if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin)); +// Rectangle rect = layout.getBounds(); +// height += rect.height; +// width = Math.max(width, rect.width); +// layout.setWidth(wrapWidth); +// renderer.disposeTextLayout(layout); +// if (isFixedLineHeight() && height > maxHeight) break; +// } +// if (isFixedLineHeight()) { +// height = lineCount * renderer.getLineHeight(); +// } +// } +// // Use default values if no text is defined. +// if (width == 0) width = DEFAULT_WIDTH; +// if (height == 0) height = DEFAULT_HEIGHT; +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// int wTrim = getLeftMargin() + rightMargin + getCaretWidth(); +// int hTrim = topMargin + bottomMargin; +// Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim); +// return new Point (rect.width, rect.height); +//} +///** +// * Copies the selected text to the DND.CLIPBOARD clipboard. +// *

    +// * The text will be put on the clipboard in plain text, HTML, and RTF formats. +// * The DND.CLIPBOARD clipboard is used for data that is +// * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or +// * by menu action. +// *

    +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void copy() { +// checkWidget(); +// copySelection(DND.CLIPBOARD); +//} +///** +// * Copies the selected text to the specified clipboard. The text will be put in the +// * clipboard in plain text, HTML, and RTF formats. +// *

    +// * The clipboardType is one of the clipboard constants defined in class +// * DND. The DND.CLIPBOARD clipboard is +// * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) +// * or by menu action. The DND.SELECTION_CLIPBOARD +// * clipboard is used for data that is transferred by selecting text and pasting +// * with the middle mouse button. +// *

    +// * +// * @param clipboardType indicates the type of clipboard +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.1 +// */ +//public void copy(int clipboardType) { +// checkWidget(); +// copySelection(clipboardType); +//} +//boolean copySelection(int type) { +// if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false; +// try { +// if (blockSelection && blockXLocation != -1) { +// String text = getBlockSelectionText(PlatformLineDelimiter); +// if (text.length() > 0) { +// //TODO RTF support +// TextTransfer plainTextTransfer = TextTransfer.getInstance(); +// Object[] data = new Object[]{text}; +// Transfer[] types = new Transfer[]{plainTextTransfer}; +// clipboard.setContents(data, types, type); +// return true; +// } +// } else if (getSelectionRanges().length > 2) { +// StringBuilder text = new StringBuilder(); +// int[] ranges = getSelectionRanges(); +// for (int i = 0; i < ranges.length; i += 2) { +// int offset = ranges[i]; +// int length = ranges[i + 1]; +// text.append(length == 0 ? "" : getText(offset, offset + length - 1)); +// text.append(PlatformLineDelimiter); +// } +// text.delete(text.length() - PlatformLineDelimiter.length(), text.length()); +// if (text.length() > 0) { +// //TODO RTF support +// clipboard.setContents(new Object[]{text.toString()}, new Transfer[]{TextTransfer.getInstance()}, type); +// return true; +// } +// } else { +// int length = selection[0].y - selection[0].x; +// if (length > 0) { +// setClipboardContent(selection[0].x, length, type); +// return true; +// } +// } +// } catch (SWTError error) { +// // Copy to clipboard failed. This happens when another application +// // is accessing the clipboard while we copy. Ignore the error. +// // Rethrow all other errors. Fixes bug 17578. +// if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { +// throw error; +// } +// } +// return false; +//} +///** +// * Returns the alignment of the widget. +// * +// * @return the alignment +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// *R +// * @see #getLineAlignment(int) +// * +// * @since 3.2 +// */ +//public int getAlignment() { +// checkWidget(); +// return alignment; +//} +///** +// * Returns the Always Show Scrollbars flag. True if the scrollbars are +// * always shown even if they are not required. False if the scrollbars are only +// * visible when some part of the content needs to be scrolled to be seen. +// * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the +// * horizontal and vertical directions. +// * +// * @return the Always Show Scrollbars flag value +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.8 +// */ +//public boolean getAlwaysShowScrollBars() { +// checkWidget(); +// return alwaysShowScroll; +//} +//int getAvailableHeightAbove(int height) { +// int maxHeight = verticalScrollOffset; +// if (maxHeight == -1) { +// int lineIndex = topIndex - 1; +// maxHeight = -topIndexY; +// if (topIndexY > 0) { +// maxHeight += renderer.getLineHeight(lineIndex--); +// } +// while (height > maxHeight && lineIndex >= 0) { +// maxHeight += renderer.getLineHeight(lineIndex--); +// } +// } +// return Math.min(height, maxHeight); +//} +//int getAvailableHeightBellow(int height) { +// int partialBottomIndex = getPartialBottomIndex(); +// int topY = getLinePixel(partialBottomIndex); +// int lineHeight = renderer.getLineHeight(partialBottomIndex); +// int availableHeight = 0; +// int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; +// if (topY + lineHeight > clientAreaHeight) { +// availableHeight = lineHeight - (clientAreaHeight - topY); +// } +// int lineIndex = partialBottomIndex + 1; +// int lineCount = content.getLineCount(); +// while (height > availableHeight && lineIndex < lineCount) { +// availableHeight += renderer.getLineHeight(lineIndex++); +// } +// return Math.min(height, availableHeight); +//} +///** +// * Returns the color of the margins. +// * +// * @return the color of the margins. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public Color getMarginColor() { +// checkWidget(); +// return marginColor != null ? marginColor : getBackground(); +//} +///** +// * Returns a string that uses only the line delimiter specified by the +// * StyledTextContent implementation. +// *

    +// * Returns only the first line if the widget has the SWT.SINGLE style. +// *

    +// * +// * @param text the text that may have line delimiters that don't +// * match the model line delimiter. Possible line delimiters +// * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") +// * @return the converted text that only uses the line delimiter +// * specified by the model. Returns only the first line if the widget +// * has the SWT.SINGLE style. +// */ +//String getModelDelimitedText(String text) { +// int length = text.length(); +// if (length == 0) { +// return text; +// } +// int crIndex = 0; +// int lfIndex = 0; +// int i = 0; +// StringBuilder convertedText = new StringBuilder(length); +// String delimiter = getLineDelimiter(); +// while (i < length) { +// if (crIndex != -1) { +// crIndex = text.indexOf(SWT.CR, i); +// } +// if (lfIndex != -1) { +// lfIndex = text.indexOf(SWT.LF, i); +// } +// if (lfIndex == -1 && crIndex == -1) { // no more line breaks? +// break; +// } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { +// convertedText.append(text.substring(i, crIndex)); +// if (lfIndex == crIndex + 1) { // CR/LF combination? +// i = lfIndex + 1; +// } else { +// i = crIndex + 1; +// } +// } else { // LF occurs before CR! +// convertedText.append(text.substring(i, lfIndex)); +// i = lfIndex + 1; +// } +// if (isSingleLine()) { +// break; +// } +// convertedText.append(delimiter); +// } +// // copy remaining text if any and if not in single line mode or no +// // text copied thus far (because there only is one line) +// if (i < length && (!isSingleLine() || convertedText.length() == 0)) { +// convertedText.append(text.substring(i)); +// } +// return convertedText.toString(); +//} +//boolean checkDragDetect(Event event) { +// if (!isListening(SWT.DragDetect)) return false; +// if (event.button != 1) return false; +// if (blockSelection && blockXLocation != -1) { +// Rectangle rect = getBlockSelectionRectangle(); +// if (rect.contains(event.x, event.y)) { +// return dragDetect(event); +// } +// } else { +// if (selection[0].x == selection[0].y) return false; +// int offset = getOffsetAtPoint(event.x, event.y, null, true); +// if (selection[0].x <= offset && offset < selection[0].y) { +// return dragDetect(event); +// } +// +// } +// return false; +//} +// +///** +// * Creates default key bindings. +// */ +//void createKeyBindings() { +// int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT; +// int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT; +// +// // Navigation +// setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); +// setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); +// if (IS_MAC) { +// setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START); +// setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END); +// setKeyBinding(SWT.HOME, ST.TEXT_START); +// setKeyBinding(SWT.END, ST.TEXT_END); +// setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START); +// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END); +// setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT); +// setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS); +// } else { +// setKeyBinding(SWT.HOME, ST.LINE_START); +// setKeyBinding(SWT.END, ST.LINE_END); +// setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); +// setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); +// setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT); +// setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS); +// } +// setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); +// setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); +// setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); +// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); +// setKeyBinding(nextKey, ST.COLUMN_NEXT); +// setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); +// +// // Selection +// setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); +// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); +// if (IS_MAC) { +// setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START); +// setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END); +// setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START); +// setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END); +// setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); +// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); +// setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT); +// setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS); +// } else { +// setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); +// setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); +// setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); +// setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); +// setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); +// setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); +// } +// setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); +// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); +// setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); +// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); +// setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT); +// setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); +// +// // Modification +// // Cut, Copy, Paste +// setKeyBinding('X' | SWT.MOD1, ST.CUT); +// setKeyBinding('C' | SWT.MOD1, ST.COPY); +// setKeyBinding('V' | SWT.MOD1, ST.PASTE); +// if (IS_MAC) { +// setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT); +// setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS); +// setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT); +// } else { +// // Cut, Copy, Paste Wordstar style +// setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); +// setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); +// setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); +// } +// setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); +// setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); +// setKeyBinding(SWT.DEL, ST.DELETE_NEXT); +// setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS); +// setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT); +// +// // Miscellaneous +// setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); +//} +///** +// * Create the bitmaps to use for the caret in bidi mode. This +// * method only needs to be called upon widget creation and when the +// * font changes (the caret bitmap height needs to match font height). +// */ +//void createCaretBitmaps() { +// int caretWidth = BIDI_CARET_WIDTH; +// Display display = getDisplay(); +// if (leftCaretBitmap != null) { +// if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) { +// defaultCaret.setImage(null); +// } +// leftCaretBitmap.dispose(); +// } +// int lineHeight = renderer.getLineHeight(); +// leftCaretBitmap = new Image(display, caretWidth, lineHeight); +// GC gc = new GC (leftCaretBitmap); +// gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); +// gc.fillRectangle(0, 0, caretWidth, lineHeight); +// gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); +// gc.drawLine(0,0,0,lineHeight); +// gc.drawLine(0,0,caretWidth-1,0); +// gc.drawLine(0,1,1,1); +// gc.dispose(); +// +// if (rightCaretBitmap != null) { +// if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) { +// defaultCaret.setImage(null); +// } +// rightCaretBitmap.dispose(); +// } +// rightCaretBitmap = new Image(display, caretWidth, lineHeight); +// gc = new GC (rightCaretBitmap); +// gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); +// gc.fillRectangle(0, 0, caretWidth, lineHeight); +// gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); +// gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); +// gc.drawLine(0,0,caretWidth-1,0); +// gc.drawLine(caretWidth-1,1,1,1); +// gc.dispose(); +//} +///** +// * Moves the selected text to the clipboard. The text will be put in the +// * clipboard in plain text, HTML, and RTF formats. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void cut() { +// checkWidget(); +// // Abort cut operation if copy to clipboard fails. +// // Fixes bug 21030. +// if (copySelection(DND.CLIPBOARD)) { +// if (blockSelection && blockXLocation != -1) { +// insertBlockSelectionText((char)0, SWT.NULL); +// } else { +// doDelete(); +// } +// } +//} +///** +// * A mouse move event has occurred. See if we should start autoscrolling. If +// * the move position is outside of the client area, initiate autoscrolling. +// * Otherwise, we've moved back into the widget so end autoscrolling. +// */ +//void doAutoScroll(Event event) { +// int caretLine = getFirstCaretLine(); +// if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) { +// doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin)); +// } else if (event.y < topMargin && caretLine != 0) { +// doAutoScroll(SWT.UP, topMargin - event.y); +// } else if (event.x < leftMargin && !wordWrap) { +// doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x); +// } else if (event.x > clientAreaWidth - rightMargin && !wordWrap) { +// doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - rightMargin)); +// } else { +// endAutoScroll(); +// } +//} +///** +// * Initiates autoscrolling. +// * +// * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS +// */ +//void doAutoScroll(int direction, int distance) { +// autoScrollDistance = distance; +// // If we're already autoscrolling in the given direction do nothing +// if (autoScrollDirection == direction) { +// return; +// } +// +// Runnable timer = null; +// final Display display = getDisplay(); +// // Set a timer that will simulate the user pressing and holding +// // down a cursor key (i.e., arrowUp, arrowDown). +// if (direction == SWT.UP) { +// timer = new Runnable() { +// @Override +// public void run() { +// /* Bug 437357 - NPE in StyledText.getCaretLine +// * StyledText.content is null at times, probably because the +// * widget itself has been disposed. +// */ +// if (isDisposed()) return; +// if (autoScrollDirection == SWT.UP) { +// if (blockSelection) { +// int verticalScrollOffset = getVerticalScrollOffset(); +// int y = blockYLocation - verticalScrollOffset; +// int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset); +// if (pixels != 0) { +// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true); +// scrollVertical(pixels, true); +// } +// } else { +// doSelectionPageUp(autoScrollDistance); +// } +// display.timerExec(V_SCROLL_RATE, this); +// } +// } +// }; +// autoScrollDirection = direction; +// display.timerExec(V_SCROLL_RATE, timer); +// } else if (direction == SWT.DOWN) { +// timer = new Runnable() { +// @Override +// public void run() { +// /* Bug 437357 - NPE in StyledText.getCaretLine +// * StyledText.content is null at times, probably because the +// * widget itself has been disposed. +// */ +// if (isDisposed()) return; +// if (autoScrollDirection == SWT.DOWN) { +// if (blockSelection) { +// int verticalScrollOffset = getVerticalScrollOffset(); +// int y = blockYLocation - verticalScrollOffset; +// int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight; +// int pixels = Math.min(autoScrollDistance, Math.max(0,max)); +// if (pixels != 0) { +// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true); +// scrollVertical(pixels, true); +// } +// } else { +// doSelectionPageDown(autoScrollDistance); +// } +// display.timerExec(V_SCROLL_RATE, this); +// } +// } +// }; +// autoScrollDirection = direction; +// display.timerExec(V_SCROLL_RATE, timer); +// } else if (direction == ST.COLUMN_NEXT) { +// timer = new Runnable() { +// @Override +// public void run() { +// /* Bug 437357 - NPE in StyledText.getCaretLine +// * StyledText.content is null at times, probably because the +// * widget itself has been disposed. +// */ +// if (isDisposed()) return; +// if (autoScrollDirection == ST.COLUMN_NEXT) { +// if (blockSelection) { +// int x = blockXLocation - horizontalScrollOffset; +// int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth; +// int pixels = Math.min(autoScrollDistance, Math.max(0,max)); +// if (pixels != 0) { +// setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true); +// scrollHorizontal(pixels, true); +// } +// } else { +// doVisualNext(); +// setMouseWordSelectionAnchor(); +// doMouseSelection(); +// } +// display.timerExec(H_SCROLL_RATE, this); +// } +// } +// }; +// autoScrollDirection = direction; +// display.timerExec(H_SCROLL_RATE, timer); +// } else if (direction == ST.COLUMN_PREVIOUS) { +// timer = new Runnable() { +// @Override +// public void run() { +// /* Bug 437357 - NPE in StyledText.getCaretLine +// * StyledText.content is null at times, probably because the +// * widget itself has been disposed. +// */ +// if (isDisposed()) return; +// if (autoScrollDirection == ST.COLUMN_PREVIOUS) { +// if (blockSelection) { +// int x = blockXLocation - horizontalScrollOffset; +// int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset); +// if (pixels != 0) { +// setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true); +// scrollHorizontal(pixels, true); +// } +// } else { +// doVisualPrevious(); +// setMouseWordSelectionAnchor(); +// doMouseSelection(); +// } +// display.timerExec(H_SCROLL_RATE, this); +// } +// } +// }; +// autoScrollDirection = direction; +// display.timerExec(H_SCROLL_RATE, timer); +// } +//} +///** +// * Deletes the previous character. Delete the selected text if any. +// * Move the caret in front of the deleted text. +// */ +//void doBackspace() { +// Event event = new Event(); +// event.text = ""; +// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { // at least one range to delete +// for (int i = selection.length - 1; i >= 0; i--) { // from bottom to top to avoid moving ranges +// Point sel = selection[i]; +// event.start = sel.x; +// event.end = sel.y; +// sendKeyEvent(event); +// } +// } else { +// for (int i = caretOffsets.length - 1; i >= 0; i--) { // reverse loop, process from bottom to top +// int caretOffset = caretOffsets[i]; +// if (caretOffset > 0) { +// int lineIndex = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// if (caretOffset == lineOffset) { +// lineOffset = content.getOffsetAtLine(lineIndex - 1); +// event.start = lineOffset + content.getLine(lineIndex - 1).length(); +// event.end = caretOffset; +// } else { +// boolean isSurrogate = false; +// String lineText = content.getLine(lineIndex); +// char ch = lineText.charAt(caretOffset - lineOffset - 1); +// if (0xDC00 <= ch && ch <= 0xDFFF) { +// if (caretOffset - lineOffset - 2 >= 0) { +// ch = lineText.charAt(caretOffset - lineOffset - 2); +// isSurrogate = 0xD800 <= ch && ch <= 0xDBFF; +// } +// } +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR); +// renderer.disposeTextLayout(layout); +// event.start = start + lineOffset; +// event.end = caretOffset; +// } +// sendKeyEvent(event); +// } +// } +// } +//} +//void doBlockColumn(boolean next) { +// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); +// int x = blockXLocation - horizontalScrollOffset; +// int y = blockYLocation - getVerticalScrollOffset(); +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(x, y, trailing, true); +// if (offset != -1) { +// offset += trailing[0]; +// int lineIndex = content.getLineAtOffset(offset); +// int newOffset; +// if (next) { +// newOffset = getClusterNext(offset, lineIndex); +// } else { +// newOffset = getClusterPrevious(offset, lineIndex); +// } +// offset = newOffset != offset ? newOffset : -1; +// } +// if (offset != -1) { +// setBlockSelectionOffset(offset, true); +// showCaret(); +// } else { +// int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth; +// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); +// x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset; +// setBlockSelectionLocation(x, y, true); +// Rectangle rect = new Rectangle(x, y, 0, 0); +// showLocation(rect, true); +// } +//} +//void doBlockContentStartEnd(boolean end) { +// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); +// int offset = end ? content.getCharCount() : 0; +// setBlockSelectionOffset(offset, true); +// showCaret(); +//} +//void doBlockWord(boolean next) { +// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); +// int x = blockXLocation - horizontalScrollOffset; +// int y = blockYLocation - getVerticalScrollOffset(); +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(x, y, trailing, true); +// if (offset != -1) { +// offset += trailing[0]; +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// String lineText = content.getLine(lineIndex); +// int lineLength = lineText.length(); +// int newOffset = offset; +// if (next) { +// if (offset < lineOffset + lineLength) { +// newOffset = getWordNext(offset, SWT.MOVEMENT_WORD); +// } +// } else { +// if (offset > lineOffset) { +// newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD); +// } +// } +// offset = newOffset != offset ? newOffset : -1; +// } +// if (offset != -1) { +// setBlockSelectionOffset(offset, true); +// showCaret(); +// } else { +// int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6; +// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); +// x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset; +// setBlockSelectionLocation(x, y, true); +// Rectangle rect = new Rectangle(x, y, 0, 0); +// showLocation(rect, true); +// } +//} +//void doBlockLineVertical(boolean up) { +// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); +// int y = blockYLocation - getVerticalScrollOffset(); +// int lineIndex = getLineIndex(y); +// if (up) { +// if (lineIndex > 0) { +// y = getLinePixel(lineIndex - 1); +// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true); +// if (y < topMargin) { +// scrollVertical(y - topMargin, true); +// } +// } +// } else { +// int lineCount = content.getLineCount(); +// if (lineIndex + 1 < lineCount) { +// y = getLinePixel(lineIndex + 2) - 1; +// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true); +// int bottom = clientAreaHeight - bottomMargin; +// if (y > bottom) { +// scrollVertical(y - bottom, true); +// } +// } +// } +//} +//void doBlockLineHorizontal(boolean end) { +// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false); +// int x = blockXLocation - horizontalScrollOffset; +// int y = blockYLocation - getVerticalScrollOffset(); +// int lineIndex = getLineIndex(y); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// String lineText = content.getLine(lineIndex); +// int lineLength = lineText.length(); +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(x, y, trailing, true); +// if (offset != -1) { +// offset += trailing[0]; +// int newOffset = offset; +// if (end) { +// if (offset < lineOffset + lineLength) { +// newOffset = lineOffset + lineLength; +// } +// } else { +// if (offset > lineOffset) { +// newOffset = lineOffset; +// } +// } +// offset = newOffset != offset ? newOffset : -1; +// } else { +// if (!end) offset = lineOffset + lineLength; +// } +// if (offset != -1) { +// setBlockSelectionOffset(offset, true); +// showCaret(); +// } else { +// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth()); +// x = (end ? maxWidth : 0) - horizontalScrollOffset; +// setBlockSelectionLocation(x, y, true); +// Rectangle rect = new Rectangle(x, y, 0, 0); +// showLocation(rect, true); +// } +//} +//void doBlockSelection(boolean sendEvent) { +// if (caretOffsets[0] > selectionAnchors[0]) { +// selection[0].x = selectionAnchors[0]; +// selection[0].y = caretOffsets[0]; +// } else { +// selection[0].x = caretOffsets[0]; +// selection[0].y = selectionAnchors[0]; +// } +// updateCaretVisibility(); +// setCaretLocations(); +// super.redraw(); +// if (sendEvent) { +// sendSelectionEvent(); +// } +// sendAccessibleTextCaretMoved(); +//} +///** +// * Replaces the selection with the character or insert the character at the +// * current caret position if no selection exists. +// *

    +// * If a carriage return was typed replace it with the line break character +// * used by the widget on this platform. +// *

    +// * +// * @param key the character typed by the user +// */ +//void doContent(final char key) { +// if (blockSelection && blockXLocation != -1) { +// insertBlockSelectionText(key, SWT.NULL); +// return; +// } +// +// for (int i = selection.length - 1; i >= 0; i--) { +// Point sel = selection[i]; +// Event event = new Event(); +// event.start = sel.x; +// event.end = sel.y; +// // replace a CR line break with the widget line break +// // CR does not make sense on Windows since most (all?) applications +// // don't recognize CR as a line break. +// if (key == SWT.CR || key == SWT.LF) { +// if (!isSingleLine()) { +// event.text = getLineDelimiter(); +// } +// } else if (sel.x == sel.y && overwrite && key != TAB) { +// // no selection and overwrite mode is on and the typed key is not a +// // tab character (tabs are always inserted without overwriting)? +// int lineIndex = content.getLineAtOffset(event.end); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// String line = content.getLine(lineIndex); +// // replace character at caret offset if the caret is not at the +// // end of the line +// if (event.end < lineOffset + line.length()) { +// event.end++; +// } +// event.text = new String(new char[] {key}); +// } else { +// event.text = new String(new char[] {key}); +// } +// if (event.text != null) { +// if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { +// return; +// } +// sendKeyEvent(event); +// } +// } +//} +///** +// * Moves the caret after the last character of the widget content. +// */ +//void doContentEnd() { +// // place caret at end of first line if receiver is in single +// // line mode. fixes 4820. +// if (isSingleLine()) { +// doLineEnd(); +// } else { +// int length = content.getCharCount(); +// setCaretOffsets(new int[] {length}, SWT.DEFAULT); +// showCaret(); +// } +//} +///** +// * Moves the caret in front of the first character of the widget content. +// */ +//void doContentStart() { +// setCaretOffsets(new int[] {0}, SWT.DEFAULT); +// showCaret(); +//} +///** +// * Moves the caret to the start of the selection if a selection exists. +// * Otherwise, if no selection exists move the cursor according to the +// * cursor selection rules. +// * +// * @see #doSelectionCursorPrevious +// */ +//void doCursorPrevious() { +// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { +// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), OFFSET_LEADING); +// showCaret(); +// } else { +// doSelectionCursorPrevious(); +// } +//} +///** +// * Moves the caret to the end of the selection if a selection exists. +// * Otherwise, if no selection exists move the cursor according to the +// * cursor selection rules. +// * +// * @see #doSelectionCursorNext +// */ +//void doCursorNext() { +// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { +// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), PREVIOUS_OFFSET_TRAILING); +// showCaret(); +// } else { +// doSelectionCursorNext(); +// } +//} +///** +// * Deletes the next character. Delete the selected text if any. +// */ +//void doDelete() { +// Event event = new Event(); +// event.text = ""; +// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { +// for (Point sel : selection) { +// event.start = sel.x; +// event.end = sel.y; +// sendKeyEvent(event); +// } +// } else { +// for (int i = caretOffsets.length - 1; i >= 0; i--) { +// int caretOffset = caretOffsets[i]; +// if (caretOffset < content.getCharCount()) { +// int line = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(line); +// int lineLength = content.getLine(line).length(); +// if (caretOffset == lineOffset + lineLength) { +// event.start = caretOffset; +// event.end = content.getOffsetAtLine(line + 1); +// } else { +// event.start = caretOffset; +// event.end = getClusterNext(caretOffset, line); +// } +// sendKeyEvent(event); +// } +// } +// } +//} +///** +// * Deletes the next word. +// */ +//void doDeleteWordNext() { +// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { +// // if a selection exists, treat the as if +// // only the delete key was pressed +// doDelete(); +// } else { +// for (int i = caretOffsets.length - 1; i >= 0; i--) { +// int caretOffset = caretOffsets[i]; +// Event event = new Event(); +// event.text = ""; +// event.start = caretOffset; +// event.end = getWordNext(caretOffset, SWT.MOVEMENT_WORD); +// sendKeyEvent(event); +// } +// } +//} +///** +// * Deletes the previous word. +// */ +//void doDeleteWordPrevious() { +// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) { +// // if a selection exists, treat as if +// // only the backspace key was pressed +// doBackspace(); +// } else { +// for (int i = caretOffsets.length - 1; i >= 0; i--) { +// int caretOffset = caretOffsets[i]; +// Event event = new Event(); +// event.text = ""; +// event.start = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD); +// event.end = caretOffset; +// sendKeyEvent(event); +// } +// } +//} +///** +// * Moves the caret one line down and to the same character offset relative +// * to the beginning of the line. Move the caret to the end of the new line +// * if the new line is shorter than the character offset. Moves the caret to +// * the end of the text if the caret already is on the last line. +// */ +//void doLineDown(boolean select) { +// int[] newCaretOffsets = new int[caretOffsets.length]; +// int lineCount = content.getLineCount(); +// int[] alignment = new int[1]; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x; +// int y = 0; +// boolean lastLine = false; +// if (isWordWrap()) { +// int lineOffset = content.getOffsetAtLine(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// TextLayout layout = renderer.getTextLayout(caretLine); +// int lineIndex = getVisualLineIndex(layout, offsetInLine); +// int layoutLineCount = layout.getLineCount(); +// if (lineIndex == layoutLineCount - 1) { +// lastLine = caretLine == lineCount - 1; +// caretLine++; +// } else { +// y = layout.getLineBounds(lineIndex + 1).y; +// y++; // bug 485722: workaround for fractional line heights +// } +// renderer.disposeTextLayout(layout); +// } else { +// lastLine = caretLine == lineCount - 1; +// caretLine++; +// } +// if (lastLine) { +// newCaretOffsets[i] = content.getCharCount(); +// } else { +// newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment); +// } +// } +// boolean hitLastLine = content.getLineAtOffset(newCaretOffsets[newCaretOffsets.length - 1]) == lineCount - 1; +// setCaretOffsets(newCaretOffsets, hitLastLine ? SWT.DEFAULT : alignment[0]); +// int oldColumnX = columnX; +// int oldHScrollOffset = horizontalScrollOffset; +// if (select) { +// setMouseWordSelectionAnchor(); +// // select first and then scroll to reduce flash when key +// // repeat scrolls lots of lines +// doSelection(ST.COLUMN_NEXT); +// } +// showCaret(); +// int hScrollChange = oldHScrollOffset - horizontalScrollOffset; +// columnX = oldColumnX + hScrollChange; +//} +///** +// * Moves the caret to the end of the line. +// */ +//void doLineEnd() { +// int[] newOffsets = new int[caretOffsets.length]; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(caretLine); +// int lineEndOffset; +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// int lineIndex = getVisualLineIndex(layout, offsetInLine); +// int[] offsets = layout.getLineOffsets(); +// lineEndOffset = lineOffset + offsets[lineIndex + 1]; +// renderer.disposeTextLayout(layout); +// } else { +// int lineLength = content.getLine(caretLine).length(); +// lineEndOffset = lineOffset + lineLength; +// } +// newOffsets[i] = lineEndOffset; +// } +// setCaretOffsets(newOffsets, PREVIOUS_OFFSET_TRAILING); +// showCaret(); +//} +///** +// * Moves the caret to the beginning of the line. +// */ +//void doLineStart() { +// int[] newCaretOffsets = new int[caretOffsets.length]; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(caretLine); +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// int lineIndex = getVisualLineIndex(layout, offsetInLine); +// int[] offsets = layout.getLineOffsets(); +// lineOffset += offsets[lineIndex]; +// renderer.disposeTextLayout(layout); +// } +// newCaretOffsets[i] = lineOffset; +// } +// setCaretOffsets(newCaretOffsets, OFFSET_LEADING); +// showCaret(); +//} +///** +// * Moves the caret one line up and to the same character offset relative +// * to the beginning of the line. Move the caret to the end of the new line +// * if the new line is shorter than the character offset. Moves the caret to +// * the beginning of the document if it is already on the first line. +// */ +//void doLineUp(boolean select) { +// int[] newCaretOffsets = new int[caretOffsets.length]; +// int[] alignment = new int[1]; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x; +// int y = 0; +// boolean firstLine = false; +// if (isWordWrap()) { +// int lineOffset = content.getOffsetAtLine(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// TextLayout layout = renderer.getTextLayout(caretLine); +// int lineIndex = getVisualLineIndex(layout, offsetInLine); +// if (lineIndex == 0) { +// firstLine = caretLine == 0; +// if (!firstLine) { +// caretLine--; +// y = renderer.getLineHeight(caretLine) - 1; +// y--; // bug 485722: workaround for fractional line heights +// } +// } else { +// y = layout.getLineBounds(lineIndex - 1).y; +// y++; // bug 485722: workaround for fractional line heights +// } +// renderer.disposeTextLayout(layout); +// } else { +// firstLine = caretLine == 0; +// caretLine--; +// } +// if (firstLine) { +// newCaretOffsets[i] = 0; +// } else { +// newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment); +// } +// } +// setCaretOffsets(newCaretOffsets, newCaretOffsets[0] == 0 ? SWT.DEFAULT : alignment[0]); +// int oldColumnX = columnX; +// int oldHScrollOffset = horizontalScrollOffset; +// if (select) setMouseWordSelectionAnchor(); +// showCaret(); +// if (select) doSelection(ST.COLUMN_PREVIOUS); +// int hScrollChange = oldHScrollOffset - horizontalScrollOffset; +// columnX = oldColumnX + hScrollChange; +//} +//void doMouseLinkCursor() { +// Display display = getDisplay(); +// Point point = display.getCursorLocation(); +// point = display.map(null, this, point); +// doMouseLinkCursor(point.x, point.y); +//} +//void doMouseLinkCursor(int x, int y) { +// int offset = getOffsetAtPoint(x, y, null, true); +// Display display = getDisplay(); +// Cursor newCursor = cursor; +// if (renderer.hasLink(offset)) { +// newCursor = display.getSystemCursor(SWT.CURSOR_HAND); +// } else { +// if (cursor == null) { +// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; +// newCursor = display.getSystemCursor(type); +// } +// } +// if (newCursor != getCursor()) super.setCursor(newCursor); +//} +///** +// * Moves the caret to the specified location. +// * +// * @param x x location of the new caret position +// * @param y y location of the new caret position +// * @param select the location change is a selection operation. +// * include the line delimiter in the selection +// */ +//void doMouseLocationChange(int x, int y, boolean select) { +// int line = getLineIndex(y); +// +// updateCaretDirection = true; +// +// if (blockSelection) { +// x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin)); +// y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin)); +// if (doubleClickEnabled && clickCount > 1) { +// boolean wordSelect = (clickCount & 1) == 0; +// if (wordSelect) { +// Point left = getPointAtOffset(doubleClickSelection.x); +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(x, y, trailing, true); +// if (offset != -1) { +// if (x > left.x) { +// offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END); +// setBlockSelectionOffset(doubleClickSelection.x, offset, true); +// } else { +// offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START); +// setBlockSelectionOffset(doubleClickSelection.y, offset, true); +// } +// } else { +// if (x > left.x) { +// setBlockSelectionLocation(left.x, left.y, x, y, true); +// } else { +// Point right = getPointAtOffset(doubleClickSelection.y); +// setBlockSelectionLocation(right.x, right.y, x, y, true); +// } +// } +// } else { +// setBlockSelectionLocation(blockXLocation, y, true); +// } +// return; +// } else { +// if (select) { +// if (blockXLocation == -1) { +// setBlockSelectionOffset(caretOffsets[0], false); +// } +// } else { +// clearBlockSelection(true, false); +// } +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(x, y, trailing, true); +// if (offset != -1) { +// if (select) { +// setBlockSelectionOffset(offset + trailing[0], true); +// return; +// } +// } else { +// if (isFixedLineHeight() && renderer.fixedPitch) { +// int avg = renderer.averageCharWidth; +// x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; +// } +// setBlockSelectionLocation(x, y, true); +// return; +// } +// } +// } +// +// // allow caret to be placed below first line only if receiver is +// // not in single line mode. fixes 4820. +// if (line < 0 || (isSingleLine() && line > 0)) { +// return; +// } +// int[] alignment = new int[1]; +// int newCaretOffset = getOffsetAtPoint(x, y, alignment); +// int newCaretAlignemnt = alignment[0]; +// +// if (doubleClickEnabled && clickCount > 1) { +// newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); +// } +// +// int newCaretLine = content.getLineAtOffset(newCaretOffset); +// +// // Is the mouse within the left client area border or on +// // a different line? If not the autoscroll selection +// // could be incorrectly reset. Fixes 1GKM3XS +// boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1; +// boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffsets[0]); +// if (vchange && hchange && (newCaretOffset != caretOffsets[0] || newCaretAlignemnt != caretAlignment)) { +// setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt); +// if (select) doMouseSelection(); +// showCaret(); +// } +// if (!select) { +// setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt); +// clearSelection(true); +// } +//} +///** +// * Updates the selection based on the caret position +// */ +//void doMouseSelection() { +// if (caretOffsets[0] <= selection[0].x || +// (caretOffsets[0] > selection[0].x && +// caretOffsets[0] < selection[0].y && selectionAnchors[0] == selection[0].x)) { +// doSelection(ST.COLUMN_PREVIOUS); +// } else { +// doSelection(ST.COLUMN_NEXT); +// } +//} +///** +// * Returns the offset of the word at the specified offset. +// * If the current selection extends from high index to low index +// * (i.e., right to left, or caret is at left border of selection on +// * non-bidi platforms) the start offset of the word preceding the +// * selection is returned. If the current selection extends from +// * low index to high index the end offset of the word following +// * the selection is returned. +// * +// * @param x mouse x location +// * @param newCaretOffset caret offset of the mouse cursor location +// * @param line line index of the mouse cursor location +// */ +//int doMouseWordSelect(int x, int newCaretOffset, int line) { +// // flip selection anchor based on word selection direction from +// // base double click. Always do this here (and don't rely on doAutoScroll) +// // because auto scroll only does not cover all possible mouse selections +// // (e.g., mouse x < 0 && mouse y > caret line y) +// if (newCaretOffset < selectionAnchors[0] && selectionAnchors[0] == selection[0].x) { +// selectionAnchors[0] = doubleClickSelection.y; +// } else if (newCaretOffset > selectionAnchors[0] && selectionAnchors[0] == selection[0].y) { +// selectionAnchors[0] = doubleClickSelection.x; +// } +// if (0 <= x && x < clientAreaWidth) { +// boolean wordSelect = (clickCount & 1) == 0; +// if (caretOffsets[0] == selection[0].x) { +// if (wordSelect) { +// newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START); +// } else { +// newCaretOffset = content.getOffsetAtLine(line); +// } +// } else { +// if (wordSelect) { +// newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END); +// } else { +// int lineEnd = content.getCharCount(); +// if (line + 1 < content.getLineCount()) { +// lineEnd = content.getOffsetAtLine(line + 1); +// } +// newCaretOffset = lineEnd; +// } +// } +// } +// return newCaretOffset; +//} +///** +// * Scrolls one page down so that the last line (truncated or whole) +// * of the current page becomes the fully visible top line. +// *

    +// * The caret is scrolled the same number of lines so that its location +// * relative to the top line remains the same. The exception is the end +// * of the text where a full page scroll is not possible. In this case +// * the caret is moved after the last character. +// *

    +// * +// * @param select whether or not to select the page +// */ +//void doPageDown(boolean select, int height) { +// if (isSingleLine()) return; +// int oldColumnX = columnX; +// int oldHScrollOffset = horizontalScrollOffset; +// if (isFixedLineHeight()) { +// int lineCount = content.getLineCount(); +// int caretLine = getFirstCaretLine(); +// if (caretLine < lineCount - 1) { +// int lineHeight = renderer.getLineHeight(); +// int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; +// int scrollLines = Math.min(lineCount - caretLine - 1, lines); +// // ensure that scrollLines never gets negative and at least one +// // line is scrolled. fixes bug 5602. +// scrollLines = Math.max(1, scrollLines); +// int[] alignment = new int[1]; +// int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment); +// setCaretOffsets(new int[] {offset}, alignment[0]); +// if (select) { +// doSelection(ST.COLUMN_NEXT); +// } +// // scroll one page down or to the bottom +// int verticalMaximum = lineCount * getVerticalIncrement(); +// int pageSize = clientAreaHeight; +// int verticalScrollOffset = getVerticalScrollOffset(); +// int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); +// if (scrollOffset + pageSize > verticalMaximum) { +// scrollOffset = verticalMaximum - pageSize; +// } +// if (scrollOffset > verticalScrollOffset) { +// scrollVertical(scrollOffset - verticalScrollOffset, true); +// } +// } +// } else { +// int lineCount = content.getLineCount(); +// int lineIndex, lineHeight; +// if (height == -1) { +// lineIndex = getPartialBottomIndex(); +// int topY = getLinePixel(lineIndex); +// lineHeight = renderer.getLineHeight(lineIndex); +// height = topY; +// if (topY + lineHeight <= clientAreaHeight) { +// height += lineHeight; +// } else { +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int y = clientAreaHeight - topY; +// for (int i = 0; i < layout.getLineCount(); i++) { +// Rectangle bounds = layout.getLineBounds(i); +// if (bounds.contains(bounds.x, y)) { +// height += bounds.y; +// break; +// } +// } +// renderer.disposeTextLayout(layout); +// } +// } +// } else { +// lineIndex = getLineIndex(height); +// int topLineY = getLinePixel(lineIndex); +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int y = height - topLineY; +// for (int i = 0; i < layout.getLineCount(); i++) { +// Rectangle bounds = layout.getLineBounds(i); +// if (bounds.contains(bounds.x, y)) { +// height = topLineY + bounds.y + bounds.height; +// break; +// } +// } +// renderer.disposeTextLayout(layout); +// } else { +// height = topLineY + renderer.getLineHeight(lineIndex); +// } +// } +// int caretHeight = height; +// if (isWordWrap()) { +// for (int caretOffset : caretOffsets) { +// int caretLine = content.getLineAtOffset(caretOffset); +// TextLayout layout = renderer.getTextLayout(caretLine); +// int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); +// lineIndex = getVisualLineIndex(layout, offsetInLine); +// caretHeight += layout.getLineBounds(lineIndex).y; +// renderer.disposeTextLayout(layout); +// } +// } +// lineIndex = getFirstCaretLine(); +// lineHeight = renderer.getLineHeight(lineIndex); +// while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) { +// caretHeight -= lineHeight; +// lineHeight = renderer.getLineHeight(++lineIndex); +// } +// int[] alignment = new int[1]; +// int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment); +// setCaretOffsets(new int[] {offset}, alignment[0]); +// if (select) doSelection(ST.COLUMN_NEXT); +// height = getAvailableHeightBellow(height); +// scrollVertical(height, true); +// if (height == 0) setCaretLocations(); +// } +// showCaret(); +// int hScrollChange = oldHScrollOffset - horizontalScrollOffset; +// columnX = oldColumnX + hScrollChange; +//} +///** +// * Moves the cursor to the end of the last fully visible line. +// */ +//void doPageEnd() { +// // go to end of line if in single line mode. fixes 5673 +// if (isSingleLine()) { +// doLineEnd(); +// } else if (caretOffsets.length == 1) { // pageEnd doesn't make sense with multi-carets +// int bottomOffset; +// if (isWordWrap()) { +// int lineIndex = getPartialBottomIndex(); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex); +// int index = layout.getLineCount() - 1; +// while (index >= 0) { +// Rectangle bounds = layout.getLineBounds(index); +// if (y >= bounds.y + bounds.height) break; +// index--; +// } +// if (index == -1 && lineIndex > 0) { +// bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); +// } else { +// bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); +// } +// renderer.disposeTextLayout(layout); +// } else { +// int lineIndex = getBottomIndex(); +// bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length(); +// } +// if (caretOffsets[0] < bottomOffset) { +// setCaretOffsets(new int[] {bottomOffset}, OFFSET_LEADING); +// showCaret(); +// } +// } +//} +///** +// * Moves the cursor to the beginning of the first fully visible line. +// */ +//void doPageStart() { +// int topOffset; +// if (isWordWrap()) { +// int y, lineIndex; +// if (topIndexY > 0) { +// lineIndex = topIndex - 1; +// y = renderer.getLineHeight(lineIndex) - topIndexY; +// } else { +// lineIndex = topIndex; +// y = -topIndexY; +// } +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int index = 0; +// int lineCount = layout.getLineCount(); +// while (index < lineCount) { +// Rectangle bounds = layout.getLineBounds(index); +// if (y <= bounds.y) break; +// index++; +// } +// if (index == lineCount) { +// topOffset = content.getOffsetAtLine(lineIndex + 1); +// } else { +// topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; +// } +// renderer.disposeTextLayout(layout); +// } else { +// topOffset = content.getOffsetAtLine(topIndex); +// } +// if (caretOffsets[0] > topOffset) { +// setCaretOffsets(new int[] {topOffset}, OFFSET_LEADING); +// showCaret(); +// } +//} +///** +// * Scrolls one page up so that the first line (truncated or whole) +// * of the current page becomes the fully visible last line. +// * The caret is scrolled the same number of lines so that its location +// * relative to the top line remains the same. The exception is the beginning +// * of the text where a full page scroll is not possible. In this case the +// * caret is moved in front of the first character. +// */ +//void doPageUp(boolean select, int height) { +// if (isSingleLine()) return; +// int oldHScrollOffset = horizontalScrollOffset; +// int oldColumnX = columnX; +// if (isFixedLineHeight()) { +// int caretLine = getFirstCaretLine(); +// if (caretLine > 0) { +// int lineHeight = renderer.getLineHeight(); +// int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; +// int scrollLines = Math.max(1, Math.min(caretLine, lines)); +// caretLine -= scrollLines; +// int[] alignment = new int[1]; +// int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment); +// setCaretOffsets(new int[] {offset}, alignment[0]); +// if (select) { +// doSelection(ST.COLUMN_PREVIOUS); +// } +// int verticalScrollOffset = getVerticalScrollOffset(); +// int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); +// if (scrollOffset < verticalScrollOffset) { +// scrollVertical(scrollOffset - verticalScrollOffset, true); +// } +// } +// } else { +// int lineHeight, lineIndex; +// if (height == -1) { +// if (topIndexY == 0) { +// height = clientAreaHeight; +// } else { +// int y; +// if (topIndex > 0) { +// lineIndex = topIndex - 1; +// lineHeight = renderer.getLineHeight(lineIndex); +// height = clientAreaHeight - topIndexY; +// y = lineHeight - topIndexY; +// } else { +// lineIndex = topIndex; +// lineHeight = renderer.getLineHeight(lineIndex); +// height = clientAreaHeight - (lineHeight + topIndexY); +// y = -topIndexY; +// } +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// for (int i = 0; i < layout.getLineCount(); i++) { +// Rectangle bounds = layout.getLineBounds(i); +// if (bounds.contains(bounds.x, y)) { +// height += lineHeight - (bounds.y + bounds.height); +// break; +// } +// } +// renderer.disposeTextLayout(layout); +// } +// } +// } else { +// lineIndex = getLineIndex(clientAreaHeight - height); +// int topLineY = getLinePixel(lineIndex); +// if (isWordWrap()) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int y = topLineY; +// for (int i = 0; i < layout.getLineCount(); i++) { +// Rectangle bounds = layout.getLineBounds(i); +// if (bounds.contains(bounds.x, y)) { +// height = clientAreaHeight - (topLineY + bounds.y); +// break; +// } +// } +// renderer.disposeTextLayout(layout); +// } else { +// height = clientAreaHeight - topLineY; +// } +// } +// int caretHeight = height; +// if (isWordWrap()) { +// for (int caretOffset : caretOffsets) { +// int caretLine = content.getLineAtOffset(caretOffset); +// TextLayout layout = renderer.getTextLayout(caretLine); +// int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); +// lineIndex = getVisualLineIndex(layout, offsetInLine); +// caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y; +// renderer.disposeTextLayout(layout); +// } +// } +// lineIndex = getFirstCaretLine(); +// lineHeight = renderer.getLineHeight(lineIndex); +// while (caretHeight - lineHeight >= 0 && lineIndex > 0) { +// caretHeight -= lineHeight; +// lineHeight = renderer.getLineHeight(--lineIndex); +// } +// lineHeight = renderer.getLineHeight(lineIndex); +// int[] alignment = new int[1]; +// int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment); +// setCaretOffsets(new int[] {offset}, alignment[0]); +// if (select) doSelection(ST.COLUMN_PREVIOUS); +// height = getAvailableHeightAbove(height); +// scrollVertical(-height, true); +// if (height == 0) setCaretLocations(); +// } +// showCaret(); +// int hScrollChange = oldHScrollOffset - horizontalScrollOffset; +// columnX = oldColumnX + hScrollChange; +//} +///** +// * Updates the selection to extend to the current caret position. +// */ +//void doSelection(int direction) { +// if (caretOffsets.length != selection.length) { +// return; +// } +// if (selectionAnchors.length != selection.length) { +// selectionAnchors = new int[selection.length]; +// Arrays.fill(selectionAnchors, -1); +// } +// boolean selectionChanged = false; +// Point[] newSelection = Arrays.stream(selection).map(p -> new Point(p.x, p.y)).toArray(Point[]::new); +// boolean[] caretAtBeginning = new boolean[newSelection.length]; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// Point currentSelection = newSelection[i]; +// int selectionAnchor = selectionAnchors[i]; +// if (selectionAnchor == -1) { +// selectionAnchor = selectionAnchors[i] = currentSelection.x; +// } +// int redrawStart = -1; +// int redrawEnd = -1; +// if (direction == ST.COLUMN_PREVIOUS) { +// if (caretOffset < currentSelection.x) { +// caretAtBeginning[i] = true; +// // grow selection +// redrawEnd = currentSelection.x; +// redrawStart = currentSelection.x = caretOffset; +// // check if selection has reversed direction +// if (currentSelection.y != selectionAnchor) { +// redrawEnd = currentSelection.y; +// currentSelection.y = selectionAnchor; +// } +// // test whether selection actually changed. Fixes 1G71EO1 +// } else if (selectionAnchor == currentSelection.x && caretOffset < currentSelection.y) { +// // caret moved towards selection anchor (left side of selection). +// // shrink selection +// redrawEnd = currentSelection.y; +// redrawStart = currentSelection.y = caretOffset; +// } +// } else { +// if (caretOffset > currentSelection.y) { +// // grow selection +// redrawStart = currentSelection.y; +// redrawEnd = currentSelection.y = caretOffset; +// // check if selection has reversed direction +// if (currentSelection.x != selectionAnchor) { +// redrawStart = currentSelection.x; +// currentSelection.x = selectionAnchor; +// } +// // test whether selection actually changed. Fixes 1G71EO1 +// } else if (selectionAnchor == currentSelection.y && caretOffset > currentSelection.x) { +// // caret moved towards selection anchor (right side of selection). +// // shrink selection +// caretAtBeginning[i] = true; +// redrawStart = currentSelection.x; +// redrawEnd = currentSelection.x = caretOffset; +// } +// } +// if (redrawStart != -1 && redrawEnd != -1) { +// internalRedrawRange(redrawStart, redrawEnd - redrawStart); +// selectionChanged = true; +// } +// } +// if (selectionChanged) { +// int[] regions = new int[newSelection.length * 2]; +// for (int i = 0; i < newSelection.length; i++) { +// Point p = newSelection[i]; +// if (caretAtBeginning[i]) { +// regions[2 * i] = p.y; +// regions[2 * i + 1] = p.x - p.y; +// } else { +// regions[2 * i] = p.x; +// regions[2 * i + 1] = p.y - p.x; +// } +// } +// setSelection(regions, false, blockSelection); +// sendSelectionEvent(); +// } +// sendAccessibleTextCaretMoved(); +//} +///** +// * Moves the caret to the next character or to the beginning of the +// * next line if the cursor is at the end of a line. +// */ +//void doSelectionCursorNext() { +// int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length); +// int newAlignment = Integer.MIN_VALUE; +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// int offset; +// if (offsetInLine < content.getLine(caretLine).length()) { +// TextLayout layout = renderer.getTextLayout(caretLine); +// offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); +// int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; +// renderer.disposeTextLayout(layout); +// offset = offsetInLine + lineOffset; +// newAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; +// newCarets[i] = offset; +// } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { +// caretLine++; +// offset = content.getOffsetAtLine(caretLine); +// newAlignment = PREVIOUS_OFFSET_TRAILING; +// newCarets[i] = offset; +// } +// } +// if (newAlignment > Integer.MIN_VALUE) { +// setCaretOffsets(newCarets, newAlignment); +// showCaret(); +// } +//} +///** +// * Moves the caret to the previous character or to the end of the previous +// * line if the cursor is at the beginning of a line. +// */ +//void doSelectionCursorPrevious() { +// int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length); +// for (int i = 0; i < caretOffsets.length; i++) { +// int caretOffset = caretOffsets[i]; +// int caretLine = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(caretLine); +// int offsetInLine = caretOffset - lineOffset; +// if (offsetInLine > 0) { +// newCarets[i] = getClusterPrevious(caretOffset, caretLine); +// } else if (caretLine > 0) { +// caretLine--; +// lineOffset = content.getOffsetAtLine(caretLine); +// newCarets[i] = lineOffset + content.getLine(caretLine).length(); +// } +// } +// if (!Arrays.equals(caretOffsets, newCarets)) { +// setCaretOffsets(newCarets, OFFSET_LEADING); +// showCaret(); +// } +//} +///** +// * Moves the caret one line down and to the same character offset relative +// * to the beginning of the line. Moves the caret to the end of the new line +// * if the new line is shorter than the character offset. +// * Moves the caret to the end of the text if the caret already is on the +// * last line. +// * Adjusts the selection according to the caret change. This can either add +// * to or subtract from the old selection, depending on the previous selection +// * direction. +// */ +//void doSelectionLineDown() { +// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; +// doLineDown(true); +// columnX = oldColumnX; +//} +///** +// * Moves the caret one line up and to the same character offset relative +// * to the beginning of the line. Moves the caret to the end of the new line +// * if the new line is shorter than the character offset. +// * Moves the caret to the beginning of the document if it is already on the +// * first line. +// * Adjusts the selection according to the caret change. This can either add +// * to or subtract from the old selection, depending on the previous selection +// * direction. +// */ +//void doSelectionLineUp() { +// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; +// doLineUp(true); +// columnX = oldColumnX; +//} +///** +// * Scrolls one page down so that the last line (truncated or whole) +// * of the current page becomes the fully visible top line. +// *

    +// * The caret is scrolled the same number of lines so that its location +// * relative to the top line remains the same. The exception is the end +// * of the text where a full page scroll is not possible. In this case +// * the caret is moved after the last character. +// *

    +// * Adjusts the selection according to the caret change. This can either add +// * to or subtract from the old selection, depending on the previous selection +// * direction. +// *

    +// */ +//void doSelectionPageDown(int pixels) { +// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; +// doPageDown(true, pixels); +// columnX = oldColumnX; +//} +///** +// * Scrolls one page up so that the first line (truncated or whole) +// * of the current page becomes the fully visible last line. +// *

    +// * The caret is scrolled the same number of lines so that its location +// * relative to the top line remains the same. The exception is the beginning +// * of the text where a full page scroll is not possible. In this case the +// * caret is moved in front of the first character. +// *

    +// * Adjusts the selection according to the caret change. This can either add +// * to or subtract from the old selection, depending on the previous selection +// * direction. +// *

    +// */ +//void doSelectionPageUp(int pixels) { +// if (caretOffsets.length > 1) { // operation doesn't make sense for multi-carets +// return; +// } +// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x; +// doPageUp(true, pixels); +// columnX = oldColumnX; +//} +///** +// * Moves the caret to the end of the next word . +// */ +//void doSelectionWordNext() { +// int[] offsets = Arrays.stream(caretOffsets).map(offset -> getWordNext(offset, SWT.MOVEMENT_WORD)).toArray(); +// // don't change caret position if in single line mode and the cursor +// // would be on a different line. fixes 5673 +// if (!isSingleLine()) { +// // Force symmetrical movement for word next and previous. Fixes 14536 +// setCaretOffsets(offsets, OFFSET_LEADING); +// showCaret(); +// } else { +// int[] linesForCurrentCarets = Arrays.stream(caretOffsets).map(offset -> content.getLineAtOffset(offset)).toArray(); +// int[] linesForNewCarets = Arrays.stream(offsets).map(offset -> content.getLineAtOffset(offset)).toArray(); +// if (Arrays.equals(linesForCurrentCarets, linesForNewCarets)) { +// // Force symmetrical movement for word next and previous. Fixes 14536 +// setCaretOffsets(offsets, OFFSET_LEADING); +// showCaret(); +// } +// } +//} +///** +// * Moves the caret to the start of the previous word. +// */ +//void doSelectionWordPrevious() { +// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getWordPrevious(offset, SWT.MOVEMENT_WORD)).toArray(), OFFSET_LEADING); +// showCaret(); +//} +///** +// * Moves the caret one character to the left. Do not go to the previous line. +// * When in a bidi locale and at a R2L character the caret is moved to the +// * beginning of the R2L segment (visually right) and then one character to the +// * left (visually left because it's now in a L2R segment). +// */ +//void doVisualPrevious() { +// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterPrevious(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT); +// showCaret(); +//} +///** +// * Moves the caret one character to the right. Do not go to the next line. +// * When in a bidi locale and at a R2L character the caret is moved to the +// * end of the R2L segment (visually left) and then one character to the +// * right (visually right because it's now in a L2R segment). +// */ +//void doVisualNext() { +// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterNext(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT); +// showCaret(); +//} +///** +// * Moves the caret to the end of the next word. +// * If a selection exists, move the caret to the end of the selection +// * and remove the selection. +// */ +//void doWordNext() { +// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { +// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), SWT.DEFAULT); +// showCaret(); +// } else { +// doSelectionWordNext(); +// } +//} +///** +// * Moves the caret to the start of the previous word. +// * If a selection exists, move the caret to the start of the selection +// * and remove the selection. +// */ +//void doWordPrevious() { +// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { +// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), SWT.DEFAULT); +// showCaret(); +// } else { +// doSelectionWordPrevious(); +// } +//} +///** +// * Ends the autoscroll process. +// */ +//void endAutoScroll() { +// autoScrollDirection = SWT.NULL; +//} +//@Override +//public Color getBackground() { +// checkWidget(); +// if (background == null) { +// return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); +// } +// return background; +//} +///** +// * Returns the baseline, in points. +// * +// * Note: this API should not be used if a StyleRange attribute causes lines to +// * have different heights (i.e. different fonts, rise, etc). +// * +// * @return baseline the baseline +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 3.0 +// * +// * @see #getBaseline(int) +// */ +//public int getBaseline() { +// checkWidget(); +// return renderer.getBaseline(); +//} +///** +// * Returns the baseline at the given offset, in points. +// * +// * @param offset the offset +// * +// * @return baseline the baseline +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • +// *
    +// * +// * @since 3.2 +// */ +//public int getBaseline(int offset) { +// checkWidget(); +// if (!(0 <= offset && offset <= content.getCharCount())) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (isFixedLineHeight()) { +// return renderer.getBaseline(); +// } +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); +// FontMetrics metrics = layout.getLineMetrics(lineInParagraph); +// renderer.disposeTextLayout(layout); +// return metrics.getAscent() + metrics.getLeading(); +//} +///** +// * Gets the BIDI coloring mode. When true the BIDI text display +// * algorithm is applied to segments of text that are the same +// * color. +// * +// * @return the current coloring mode +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @deprecated use BidiSegmentListener instead. +// */ +//@Deprecated +//public boolean getBidiColoring() { +// checkWidget(); +// return bidiColoring; +//} +///** +// * Returns whether the widget is in block selection mode. +// * +// * @return true if widget is in block selection mode, false otherwise +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public boolean getBlockSelection() { +// checkWidget(); +// return blockSelection; +//} +//Rectangle getBlockSelectionPosition() { +// int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset()); +// int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset()); +// if (firstLine > lastLine) { +// int temp = firstLine; +// firstLine = lastLine; +// lastLine = temp; +// } +// int left = blockXAnchor; +// int right = blockXLocation; +// if (left > right) { +// left = blockXLocation; +// right = blockXAnchor; +// } +// return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine); +//} +///** +// * Returns the block selection bounds. The bounds is +// * relative to the upper left corner of the document. +// * +// * @return the block selection bounds +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public Rectangle getBlockSelectionBounds() { +// Rectangle rect; +// if (blockSelection && blockXLocation != -1) { +// rect = getBlockSelectionRectangle(); +// } else { +// Point startPoint = getPointAtOffset(selection[0].x); +// Point endPoint = getPointAtOffset(selection[0].y); +// int height = getLineHeight(selection[0].y); +// rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y); +// if (selection[0].x == selection[0].y) { +// rect.width = getCaretWidth(); +// } +// } +// rect.x += horizontalScrollOffset; +// rect.y += getVerticalScrollOffset(); +// return rect; +//} +//Rectangle getBlockSelectionRectangle() { +// Rectangle rect = getBlockSelectionPosition(); +// rect.y = getLinePixel(rect.y); +// rect.width = rect.width - rect.x; +// rect.height = getLinePixel(rect.height + 1) - rect.y; +// return rect; +//} +//String getBlockSelectionText(String delimiter) { +// Rectangle rect = getBlockSelectionPosition(); +// int firstLine = rect.y; +// int lastLine = rect.height; +// int left = rect.x; +// int right = rect.width; +// StringBuilder buffer = new StringBuilder(); +// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { +// int start = getOffsetAtPoint(left, 0, lineIndex, null); +// int end = getOffsetAtPoint(right, 0, lineIndex, null); +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// String text = content.getTextRange(start, end - start); +// buffer.append(text); +// if (lineIndex < lastLine) buffer.append(delimiter); +// } +// return buffer.toString(); +//} +///** +// * Returns the index of the last fully visible line. +// * +// * @return index of the last fully visible line. +// */ +//int getBottomIndex() { +// int bottomIndex; +// if (isFixedLineHeight()) { +// int lineCount = 1; +// int lineHeight = renderer.getLineHeight(); +// if (lineHeight != 0) { +// // calculate the number of lines that are fully visible +// int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset(); +// lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight; +// } +// bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); +// } else { +// int clientAreaHeight = this.clientAreaHeight - bottomMargin; +// bottomIndex = getLineIndex(clientAreaHeight); +// if (bottomIndex > 0) { +// int linePixel = getLinePixel(bottomIndex); +// int lineHeight = renderer.getLineHeight(bottomIndex); +// if (linePixel + lineHeight > clientAreaHeight) { +// if (getLinePixel(bottomIndex - 1) >= topMargin) { +// bottomIndex--; +// } +// } +// } +// } +// return bottomIndex; +//} +///** +// * Returns the bottom margin. +// * +// * @return the bottom margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public int getBottomMargin() { +// checkWidget(); +// return bottomMargin; +//} +//Rectangle getBoundsAtOffset(int offset) { +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// String line = content.getLine(lineIndex); +// Rectangle bounds; +// if (line.length() != 0) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset)); +// bounds = layout.getBounds(offsetInLine, offsetInLine); +// if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) { +// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); +// Point point = layout.getLocation(offsetInLine, true); +// bounds = new Rectangle (point.x, point.y, 0, bounds.height); +// } +// renderer.disposeTextLayout(layout); +// } else { +// bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); +// } +// if (Arrays.binarySearch(caretOffsets, offset) >= 0 && !isWordWrap()) { +// int lineEnd = lineOffset + line.length(); +// if (offset == lineEnd) { +// bounds.width += getCaretWidth(); +// } +// } +// bounds.x += leftMargin - horizontalScrollOffset; +// bounds.y += getLinePixel(lineIndex); +// return bounds; +//} +///** +// * Returns the caret position relative to the start of the text. +// * +// * @return the caret position relative to the start of the text. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getCaretOffset() { +// checkWidget(); +// return caretOffsets[0]; +//} +///** +// * Returns the caret width. +// * +// * @return the caret width, 0 if caret is null. +// */ +//int getCaretWidth() { +// Caret caret = getCaret(); +// if (caret == null) return 0; +// return caret.getSize().x; +//} +//Object getClipboardContent(int clipboardType) { +// TextTransfer plainTextTransfer = TextTransfer.getInstance(); +// return clipboard.getContents(plainTextTransfer, clipboardType); +//} +//int getClusterNext(int offset, int lineIndex) { +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// offset -= lineOffset; +// offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER); +// offset += lineOffset; +// renderer.disposeTextLayout(layout); +// return offset; +//} +//int getClusterPrevious(int offset, int lineIndex) { +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// offset -= lineOffset; +// offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER); +// offset += lineOffset; +// renderer.disposeTextLayout(layout); +// return offset; +//} +///** +// * Returns the content implementation that is used for text storage. +// * +// * @return content the user defined content implementation that is used for +// * text storage or the default content implementation if no user defined +// * content implementation has been set. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public StyledTextContent getContent() { +// checkWidget(); +// return content; +//} +//@Override +//public boolean getDragDetect () { +// checkWidget (); +// return dragDetect; +//} +///** +// * Returns whether the widget implements double click mouse behavior. +// * +// * @return true if double clicking a word selects the word, false if double clicks +// * have the same effect as regular mouse clicks +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public boolean getDoubleClickEnabled() { +// checkWidget(); +// return doubleClickEnabled; +//} +///** +// * Returns whether the widget content can be edited. +// * +// * @return true if content can be edited, false otherwise +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public boolean getEditable() { +// checkWidget(); +// return editable; +//} +//@Override +//public Color getForeground() { +// checkWidget(); +// if (foreground == null) { +// return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); +// } +// return foreground; +//} +///** +// * Returns the horizontal scroll increment. +// * +// * @return horizontal scroll increment. +// */ +//int getHorizontalIncrement() { +// return renderer.averageCharWidth; +//} +///** +// * Returns the horizontal scroll offset relative to the start of the line. +// * +// * @return horizontal scroll offset relative to the start of the line, +// * measured in character increments starting at 0, if > 0 the content is scrolled +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getHorizontalIndex() { +// checkWidget(); +// return horizontalScrollOffset / getHorizontalIncrement(); +//} +///** +// * Returns the horizontal scroll offset relative to the start of the line. +// * +// * @return the horizontal scroll offset relative to the start of the line, +// * measured in SWT logical point starting at 0, if > 0 the content is scrolled. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getHorizontalPixel() { +// checkWidget(); +// return horizontalScrollOffset; +//} +///** +// * Returns the line indentation of the widget. +// * +// * @return the line indentation +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getLineIndent(int) +// * +// * @since 3.2 +// */ +//public int getIndent() { +// checkWidget(); +// return indent; +//} +///** +// * Returns whether the widget justifies lines. +// * +// * @return whether lines are justified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getLineJustify(int) +// * +// * @since 3.2 +// */ +//public boolean getJustify() { +// checkWidget(); +// return justify; +//} +///** +// * Returns the action assigned to the key. +// * Returns SWT.NULL if there is no action associated with the key. +// * +// * @param key a key code defined in SWT.java or a character. +// * Optionally ORd with a state mask. Preferred state masks are one or more of +// * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform +// * differences. However, there may be cases where using the specific state masks +// * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. +// * @return one of the predefined actions defined in ST.java or SWT.NULL +// * if there is no action associated with the key. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getKeyBinding(int key) { +// checkWidget(); +// Integer action = keyActionMap.get(key); +// return action == null ? SWT.NULL : action.intValue(); +//} +///** +// * Gets the number of characters. +// * +// * @return number of characters in the widget +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getCharCount() { +// checkWidget(); +// return content.getCharCount(); +//} +///** +// * Returns the line at the given line index without delimiters. +// * Index 0 is the first line of the content. When there are not +// * any lines, getLine(0) is a valid call that answers an empty string. +// * +// * @param lineIndex index of the line to return. +// * @return the line text without delimiters +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
    • +// *
    +// * @since 3.4 +// */ +//public String getLine(int lineIndex) { +// checkWidget(); +// if (lineIndex < 0 || +// (lineIndex > 0 && lineIndex >= content.getLineCount())) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return content.getLine(lineIndex); +//} +///** +// * Returns the alignment of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the line alignment +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @see #getAlignment() +// * +// * @since 3.2 +// */ +//public int getLineAlignment(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return renderer.getLineAlignment(index, alignment); +//} +///** +// * Returns the line at the specified offset in the text +// * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) +// * returns the line of the insert location. +// * +// * @param offset offset relative to the start of the content. +// * 0 <= offset <= getCharCount() +// * @return line at the specified offset in the text +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • +// *
    +// */ +//public int getLineAtOffset(int offset) { +// checkWidget(); +// if (offset < 0 || offset > getCharCount()) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return content.getLineAtOffset(offset); +//} +///** +// * Returns the background color of the line at the given index. +// * Returns null if a LineBackgroundListener has been set or if no background +// * color has been specified for the line. Should not be called if a +// * LineBackgroundListener has been set since the listener maintains the +// * line background colors. +// * +// * @param index the index of the line +// * @return the background color of the line at the given index. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// */ +//public Color getLineBackground(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetBackground) ? null : renderer.getLineBackground(index, null); +//} +///** +// * Returns the bullet of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the line bullet +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @since 3.2 +// */ +//public Bullet getLineBullet(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetStyle) ? null : renderer.getLineBullet(index, null); +//} +///** +// * Returns the line background data for the given line or null if +// * there is none. +// * +// * @param lineOffset offset of the line start relative to the start +// * of the content. +// * @param line line to get line background data for +// * @return line background data for the given line. +// */ +//StyledTextEvent getLineBackgroundData(int lineOffset, String line) { +// return sendLineEvent(ST.LineGetBackground, lineOffset, line); +//} +///** +// * Gets the number of text lines. +// * +// * @return the number of lines in the widget +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getLineCount() { +// checkWidget(); +// return content.getLineCount(); +//} +///** +// * Returns the number of lines that can be completely displayed in the +// * widget client area. +// * +// * @return number of lines that can be completely displayed in the widget +// * client area. +// */ +//int getLineCountWhole() { +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// return lineHeight != 0 ? clientAreaHeight / lineHeight : 1; +// } +// return getBottomIndex() - topIndex + 1; +//} +///** +// * Returns the line delimiter used for entering new lines by key down +// * or paste operation. +// * +// * @return line delimiter used for entering new lines by key down +// * or paste operation. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public String getLineDelimiter() { +// checkWidget(); +// return content.getLineDelimiter(); +//} +///** +// * Returns the line height. +// *

    +// * Note: this API should not be used if a StyleRange attribute causes lines to +// * have different heights (i.e. different fonts, rise, etc). +// *

    +// * +// * @return line height in points. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @see #getLineHeight(int) +// */ +//public int getLineHeight() { +// checkWidget(); +// return renderer.getLineHeight(); +//} +///** +// * Returns the line height at the given offset. +// * +// * @param offset the offset +// * +// * @return line height in points +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • +// *
    +// * +// * @since 3.2 +// */ +//public int getLineHeight(int offset) { +// checkWidget(); +// if (!(0 <= offset && offset <= content.getCharCount())) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (isFixedLineHeight()) { +// return renderer.getLineHeight(); +// } +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); +// int height = layout.getLineBounds(lineInParagraph).height; +// renderer.disposeTextLayout(layout); +// return height; +//} +///** +// * Returns the indentation of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the line indentation +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @see #getIndent() +// * +// * @since 3.2 +// */ +//public int getLineIndent(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent); +//} +///** +// * Returns the vertical indentation of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the line vertical indentation +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @since 3.109 +// */ +//public int getLineVerticalIndent(int index) { +// checkWidget(); +// if (index < 0 || index >= content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index); +//} +///** +// * Returns whether the line at the given index is justified. +// * +// * @param index the index of the line +// * +// * @return whether the line is justified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @see #getJustify() +// * +// * @since 3.2 +// */ +//public boolean getLineJustify(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetStyle) ? false : renderer.getLineJustify(index, justify); +//} +///** +// * Returns the line spacing of the widget. +// * +// * @return the line spacing +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.2 +// */ +//public int getLineSpacing() { +// checkWidget(); +// return lineSpacing; +//} +///** +// * Returns the line style data for the given line or null if there is +// * none. +// *

    +// * If there is a LineStyleListener but it does not set any styles, +// * the StyledTextEvent.styles field will be initialized to an empty +// * array. +// *

    +// * +// * @param lineOffset offset of the line start relative to the start of +// * the content. +// * @param line line to get line styles for +// * @return line style data for the given line. Styles may start before +// * line start and end after line end +// */ +//StyledTextEvent getLineStyleData(int lineOffset, String line) { +// return sendLineEvent(ST.LineGetStyle, lineOffset, line); +//} +///** +// * Returns the top SWT logical point, relative to the client area, of a given line. +// * Clamps out of ranges index. +// * +// * @param lineIndex the line index, the max value is lineCount. If +// * lineIndex == lineCount it returns the bottom SWT logical point of the last line. +// * It means this function can be used to retrieve the bottom SWT logical point of any line. +// * +// * @return the top SWT logical point of a given line index +// * +// * @since 3.2 +// */ +//public int getLinePixel(int lineIndex) { +// checkWidget(); +// int lineCount = content.getLineCount(); +// lineIndex = Math.max(0, Math.min(lineCount, lineIndex)); +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin; +// } +// if (lineIndex == topIndex) +// return topIndexY + topMargin; +// int height = topIndexY; +// if (lineIndex > topIndex) { +// for (int i = topIndex; i < lineIndex; i++) { +// height += renderer.getLineHeight(i); +// } +// } else { +// for (int i = topIndex - 1; i >= lineIndex; i--) { +// height -= renderer.getLineHeight(i); +// } +// } +// return height + topMargin; +//} +///** +// * Returns the line index for a y, relative to the client area. +// * The line index returned is always in the range 0..lineCount - 1. +// * +// * @param y the y-coordinate point +// * +// * @return the line index for a given y-coordinate point +// * +// * @since 3.2 +// */ +//public int getLineIndex(int y) { +// checkWidget(); +// y -= topMargin; +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// int lineIndex = (y + getVerticalScrollOffset()) / lineHeight; +// int lineCount = content.getLineCount(); +// lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex)); +// return lineIndex; +// } +// if (y == topIndexY) return topIndex; +// int line = topIndex; +// if (y < topIndexY) { +// while (y < topIndexY && line > 0) { +// y += renderer.getLineHeight(--line); +// } +// } else { +// int lineCount = content.getLineCount(); +// int lineHeight = renderer.getLineHeight(line); +// while (y - lineHeight >= topIndexY && line < lineCount - 1) { +// y -= lineHeight; +// lineHeight = renderer.getLineHeight(++line); +// } +// } +// return line; +//} +///** +// * Returns the tab stops of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the tab stops for the line +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @see #getTabStops() +// * +// * @since 3.6 +// */ +//public int[] getLineTabStops(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// if (isListening(ST.LineGetStyle)) return null; +// int[] tabs = renderer.getLineTabStops(index, null); +// if (tabs == null) tabs = this.tabs; +// if (tabs == null) return new int [] {renderer.tabWidth}; +// int[] result = new int[tabs.length]; +// System.arraycopy(tabs, 0, result, 0, tabs.length); +// return result; +//} +///** +// * Returns the wrap indentation of the line at the given index. +// * +// * @param index the index of the line +// * +// * @return the wrap indentation +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • +// *
    +// * +// * @see #getWrapIndent() +// * +// * @since 3.6 +// */ +//public int getLineWrapIndent(int index) { +// checkWidget(); +// if (index < 0 || index > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent); +//} +///** +// * Returns the left margin. +// * +// * @return the left margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public int getLeftMargin() { +// checkWidget(); +// return leftMargin - alignmentMargin; +//} +///** +// * Returns the x, y location of the upper left corner of the character +// * bounding box at the specified offset in the text. The point is +// * relative to the upper left corner of the widget client area. +// * +// * @param offset offset relative to the start of the content. +// * 0 <= offset <= getCharCount() +// * @return x, y location of the upper left corner of the character +// * bounding box at the specified offset in the text. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • +// *
    +// */ +//public Point getLocationAtOffset(int offset) { +// checkWidget(); +// if (offset < 0 || offset > getCharCount()) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return getPointAtOffset(offset); +//} +///** +// * Returns true if the mouse navigator is enabled. +// * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor +// * +// * @return the mouse navigator's enabled state +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getEnabled +// * @since 3.110 +// */ +//public boolean getMouseNavigatorEnabled () { +// checkWidget (); +// return mouseNavigator != null; +//} +///** +// * Returns the character offset of the first character of the given line. +// * +// * @param lineIndex index of the line, 0 based relative to the first +// * line in the content. 0 <= lineIndex < getLineCount(), except +// * lineIndex may always be 0 +// * @return offset offset of the first character of the line, relative to +// * the beginning of the document. The first character of the document is +// * at offset 0. +// * When there are not any lines, getOffsetAtLine(0) is a valid call that +// * answers 0. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
    • +// *
    +// * @since 2.0 +// */ +//public int getOffsetAtLine(int lineIndex) { +// checkWidget(); +// if (lineIndex < 0 || +// (lineIndex > 0 && lineIndex >= content.getLineCount())) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return content.getOffsetAtLine(lineIndex); +//} +///** +// * Returns the offset of the character at the given location relative +// * to the first character in the document. +// *

    +// * The return value reflects the character offset that the caret will +// * be placed at if a mouse click occurred at the specified location. +// * If the x coordinate of the location is beyond the center of a character +// * the returned offset will be behind the character. +// *

    +// * +// * @param point the origin of character bounding box relative to +// * the origin of the widget client area. +// * @return offset of the character at the given location relative +// * to the first character in the document. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when point is null
    • +// *
    • ERROR_INVALID_ARGUMENT when there is no character at the specified location
    • +// *
    +// * +// * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance +// */ +//@Deprecated +//public int getOffsetAtLocation(Point point) { +// checkWidget(); +// if (point == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(point.x, point.y, trailing, true); +// if (offset == -1) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// return offset + trailing[0]; +//} +// +///** +// * Returns the offset of the character at the given point relative +// * to the first character in the document. +// *

    +// * The return value reflects the character offset that the caret will +// * be placed at if a mouse click occurred at the specified point. +// * If the x coordinate of the point is beyond the center of a character +// * the returned offset will be behind the character. +// *

    +// * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that +// * it does not throw an exception when no character is found and thus performs faster. +// * +// * @param point the origin of character bounding box relative to +// * the origin of the widget client area. +// * @return offset of the character at the given point relative +// * to the first character in the document. +// * -1 when there is no character at the specified location. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when point is null
    • +// *
    +// * +// * @since 3.107 +// */ +//public int getOffsetAtPoint(Point point) { +// checkWidget(); +// if (point == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// int[] trailing = new int[1]; +// int offset = getOffsetAtPoint(point.x, point.y, trailing, true); +// return offset != -1 ? offset + trailing[0] : -1; +//} +// +//int getOffsetAtPoint(int x, int y, int[] alignment) { +// int lineIndex = getLineIndex(y); +// y -= getLinePixel(lineIndex); +// return getOffsetAtPoint(x, y, lineIndex, alignment); +//} +//int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// x += horizontalScrollOffset - leftMargin; +// int[] trailing = new int[1]; +// int offsetInLine = layout.getOffset(x, y, trailing); +// if (alignment != null) alignment[0] = OFFSET_LEADING; +// if (trailing[0] != 0) { +// int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); +// int lineStart = layout.getLineOffsets()[lineInParagraph]; +// if (offsetInLine + trailing[0] == lineStart) { +// offsetInLine += trailing[0]; +// if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING; +// } else { +// String line = content.getLine(lineIndex); +// int level = 0; +// if (alignment != null) { +// int offset = offsetInLine; +// while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; +// if (offset == 0 && Character.isDigit(line.charAt(offset))) { +// level = isMirrored() ? 1 : 0; +// } else { +// level = layout.getLevel(offset) & 0x1; +// } +// } +// offsetInLine += trailing[0]; +// if (alignment != null) { +// int trailingLevel = layout.getLevel(offsetInLine) & 0x1; +// if (level != trailingLevel) { +// alignment[0] = PREVIOUS_OFFSET_TRAILING; +// } else { +// alignment[0] = OFFSET_LEADING; +// } +// } +// } +// } +// renderer.disposeTextLayout(layout); +// return offsetInLine + content.getOffsetAtLine(lineIndex); +//} +//int getOffsetAtPoint(int x, int y, int[] trailing, boolean inTextOnly) { +// if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) { +// return -1; +// } +// int bottomIndex = getPartialBottomIndex(); +// int height = getLinePixel(bottomIndex + 1); +// if (inTextOnly && y > height) { +// return -1; +// } +// int lineIndex = getLineIndex(y); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// x += horizontalScrollOffset - leftMargin; +// y -= getLinePixel(lineIndex); +// int offset = layout.getOffset(x, y, trailing); +// Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset)); +// renderer.disposeTextLayout(layout); +// if (inTextOnly && !(rect.x <= x && x <= rect.x + rect.width)) { +// return -1; +// } +// return offset + lineOffset; +//} +///** +// * Returns the orientation of the receiver. +// * +// * @return the orientation style +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 2.1.2 +// */ +//@Override +//public int getOrientation () { +// return super.getOrientation (); +//} +///** +// * Returns the index of the last partially visible line. +// * +// * @return index of the last partially visible line. +// */ +//int getPartialBottomIndex() { +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); +// return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1); +// } +// return getLineIndex(clientAreaHeight - bottomMargin); +//} +///** +// * Returns the index of the first partially visible line. +// * +// * @return index of the first partially visible line. +// */ +//int getPartialTopIndex() { +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// return getVerticalScrollOffset() / lineHeight; +// } +// return topIndexY <= 0 ? topIndex : topIndex - 1; +//} +///** +// * Returns the content in the specified range using the platform line +// * delimiter to separate lines. +// * +// * @param writer the TextWriter to write line text into +// * @return the content in the specified range using the platform line +// * delimiter to separate lines as written by the specified TextWriter. +// */ +//String getPlatformDelimitedText(TextWriter writer) { +// int end = writer.getStart() + writer.getCharCount(); +// int startLine = content.getLineAtOffset(writer.getStart()); +// int endLine = content.getLineAtOffset(end); +// String endLineText = content.getLine(endLine); +// int endLineOffset = content.getOffsetAtLine(endLine); +// +// for (int i = startLine; i <= endLine; i++) { +// writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); +// if (i < endLine) { +// writer.writeLineDelimiter(PlatformLineDelimiter); +// } +// } +// if (end > endLineOffset + endLineText.length()) { +// writer.writeLineDelimiter(PlatformLineDelimiter); +// } +// writer.close(); +// return writer.toString(); +//} +///** +// * Returns all the ranges of text that have an associated StyleRange. +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * The ranges array contains start and length pairs. Each pair refers to +// * the corresponding style in the styles array. For example, the pair +// * that starts at ranges[n] with length ranges[n+1] uses the style +// * at styles[n/2] returned by getStyleRanges(int, int, boolean). +// *

    +// * +// * @return the ranges or an empty array if a LineStyleListener has been set. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.2 +// * +// * @see #getStyleRanges(boolean) +// */ +//public int[] getRanges() { +// checkWidget(); +// if (!isListening(ST.LineGetStyle)) { +// int[] ranges = renderer.getRanges(0, content.getCharCount()); +// if (ranges != null) return ranges; +// } +// return new int[0]; +//} +///** +// * Returns the ranges of text that have an associated StyleRange. +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * The ranges array contains start and length pairs. Each pair refers to +// * the corresponding style in the styles array. For example, the pair +// * that starts at ranges[n] with length ranges[n+1] uses the style +// * at styles[n/2] returned by getStyleRanges(int, int, boolean). +// *

    +// * +// * @param start the start offset of the style ranges to return +// * @param length the number of style ranges to return +// * +// * @return the ranges or an empty array if a LineStyleListener has been set. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE if start or length are outside the widget content
    • +// *
    +// * +// * @since 3.2 +// * +// * @see #getStyleRanges(int, int, boolean) +// */ +//public int[] getRanges(int start, int length) { +// checkWidget(); +// int contentLength = getCharCount(); +// int end = start + length; +// if (start > end || start < 0 || end > contentLength) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (!isListening(ST.LineGetStyle)) { +// int[] ranges = renderer.getRanges(start, length); +// if (ranges != null) return ranges; +// } +// return new int[0]; +//} +///** +// * Returns the right margin. +// * +// * @return the right margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public int getRightMargin() { +// checkWidget(); +// return rightMargin; +//} +///** +// * Returns the selection. +// *

    +// * Text selections are specified in terms of caret positions. In a text +// * widget that contains N characters, there are N+1 caret positions, +// * ranging from 0..N +// *

    +// *

    +// * It is usually better to use {@link #getSelectionRanges()} which better +// * support multiple selection and carets and block selection. +// *

    +// * +// * @return start and end of the selection, x is the offset of the first +// * selected character, y is the offset after the last selected character. +// * The selection values returned are visual (i.e., x will always always be +// * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right +// * (LtoR), compare the caretOffset to the start and end of the selection +// * (e.g., caretOffset == start of selection implies that the selection is RtoL). +// * @see #getSelectionRanges +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public Point getSelection() { +// checkWidget(); +// return new Point(selection[0].x, selection[0].y); +//} +///** +// * Returns the selection. +// *

    +// * It is usually better to use {@link #getSelectionRanges()} which better +// * support multiple selection and carets and block selection. +// *

    +// * +// * @return start and length of the selection, x is the offset of the +// * first selected character, relative to the first character of the +// * widget content. y is the length of the selection. +// * The selection values returned are visual (i.e., length will always always be +// * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right +// * (LtoR), compare the caretOffset to the start and end of the selection +// * (e.g., caretOffset == start of selection implies that the selection is RtoL). +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @see #getSelectionRanges +// */ +//public Point getSelectionRange() { +// checkWidget(); +// return new Point(selection[0].x, selection[0].y - selection[0].x); +//} +///** +// * Returns the selected ranges of text. +// * If block is enabled, return the ranges that are inside the block selection rectangle. +// *

    +// * The ranges array contains start and length pairs. +// *

    +// * When the receiver is not +// * in block selection mode the return arrays contains the start and length of +// * the regular selections. +// * +// * @return the ranges array +// * +// * @exception SWTException

      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// * @see #setSelectionRanges(int[]) +// */ +//public int[] getSelectionRanges() { +// checkWidget(); +// if (blockSelection && blockXLocation != -1) { +// Rectangle rect = getBlockSelectionPosition(); +// int firstLine = rect.y; +// int lastLine = rect.height; +// int left = rect.x; +// int right = rect.width; +// int[] ranges = new int[(lastLine - firstLine + 1) * 2]; +// int index = 0; +// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { +// int start = getOffsetAtPoint(left, 0, lineIndex, null); +// int end = getOffsetAtPoint(right, 0, lineIndex, null); +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// ranges[index++] = start; +// ranges[index++] = end - start; +// } +// return ranges; +// } +// int[] res = new int[2 * selection.length]; +// int index = 0; +// for (Point p : selection) { +// res[index++] = p.x; +// res[index++] = p.y - p.x; +// } +// return res; +//} +///** +// * Returns the receiver's selection background color. +// * +// * @return the selection background color +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.1 +// */ +//public Color getSelectionBackground() { +// checkWidget(); +// if (selectionBackground == null) { +// return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); +// } +// return selectionBackground; +//} +///** +// * Gets the number of selected characters. +// * +// * @return the number of selected characters. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getSelectionCount() { +// checkWidget(); +// if (blockSelection && blockXLocation != -1) { +// return getBlockSelectionText(content.getLineDelimiter()).length(); +// } +// return Arrays.stream(selection).collect(Collectors.summingInt(sel -> sel.y - sel.x)); +//} +///** +// * Returns the receiver's selection foreground color. +// * +// * @return the selection foreground color +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.1 +// */ +//public Color getSelectionForeground() { +// checkWidget(); +// if (selectionForeground == null) { +// return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); +// } +// return selectionForeground; +//} +///** +// * Returns the selected text. +// * +// * @return selected text, or an empty String if there is no selection. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public String getSelectionText() { +// checkWidget(); +// if (blockSelection && blockXLocation != -1) { +// return getBlockSelectionText(content.getLineDelimiter()); +// } +// return Arrays.stream(selection).map(sel -> content.getTextRange(sel.x, sel.y - sel.x)).collect(Collectors.joining()); +//} +//StyledTextEvent getBidiSegments(int lineOffset, String line) { +// if (!isListening(ST.LineGetSegments)) { +// if (!bidiColoring) return null; +// StyledTextEvent event = new StyledTextEvent(content); +// event.segments = getBidiSegmentsCompatibility(line, lineOffset); +// return event; +// } +// StyledTextEvent event = sendLineEvent(ST.LineGetSegments, lineOffset, line); +// if (event == null || event.segments == null || event.segments.length == 0) return null; +// int lineLength = line.length(); +// int[] segments = event.segments; +// if (segments[0] > lineLength) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// char[] segmentsChars = event.segmentsChars; +// boolean hasSegmentsChars = segmentsChars != null; +// for (int i = 1; i < segments.length; i++) { +// if ((hasSegmentsChars ? segments[i] < segments[i - 1] : segments[i] <= segments[i - 1]) || segments[i] > lineLength) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// } +// if (hasSegmentsChars && !visualWrap) { +// for (char segmentsChar : segmentsChars) { +// if (segmentsChar == '\n' || segmentsChar == '\r') { +// visualWrap = true; +// break; +// } +// } +// } +// return event; +//} +///** +// * @see #getBidiSegments +// * Supports deprecated setBidiColoring API. Remove when API is removed. +// */ +//int [] getBidiSegmentsCompatibility(String line, int lineOffset) { +// int lineLength = line.length(); +// StyleRange [] styles = null; +// StyledTextEvent event = getLineStyleData(lineOffset, line); +// if (event != null) { +// styles = event.styles; +// } else { +// styles = renderer.getStyleRanges(lineOffset, lineLength, true); +// } +// if (styles == null || styles.length == 0) { +// return new int[] {0, lineLength}; +// } +// int k=0, count = 1; +// while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) { +// k++; +// } +// int[] offsets = new int[(styles.length - k) * 2 + 2]; +// for (int i = k; i < styles.length; i++) { +// StyleRange style = styles[i]; +// int styleLineStart = Math.max(style.start - lineOffset, 0); +// int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); +// styleLineEnd = Math.min (styleLineEnd, line.length ()); +// if (i > 0 && count > 1 && +// ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || +// (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && +// style.similarTo(styles[i-1])) { +// offsets[count-2] = Math.min(offsets[count-2], styleLineStart); +// offsets[count-1] = Math.max(offsets[count-1], styleLineEnd); +// } else { +// if (styleLineStart > offsets[count - 1]) { +// offsets[count] = styleLineStart; +// count++; +// } +// offsets[count] = styleLineEnd; +// count++; +// } +// } +// // add offset for last non-colored segment in line, if any +// if (lineLength > offsets[count-1]) { +// offsets [count] = lineLength; +// count++; +// } +// if (count == offsets.length) { +// return offsets; +// } +// int [] result = new int [count]; +// System.arraycopy (offsets, 0, result, 0, count); +// return result; +//} +///** +// * Returns the style range at the given offset. +// *

    +// * Returns null if a LineStyleListener has been set or if a style is not set +// * for the offset. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param offset the offset to return the style for. +// * 0 <= offset < getCharCount() must be true. +// * @return a StyleRange with start == offset and length == 1, indicating +// * the style at the given offset. null if a LineStyleListener has been set +// * or if a style is not set for the given offset. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the offset is invalid
    • +// *
    +// */ +//public StyleRange getStyleRangeAtOffset(int offset) { +// checkWidget(); +// if (offset < 0 || offset >= getCharCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// if (!isListening(ST.LineGetStyle)) { +// StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true); +// if (ranges != null) return ranges[0]; +// } +// return null; +//} +///** +// * Returns the styles. +// *

    +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * Note: Because a StyleRange includes the start and length, the +// * same instance cannot occur multiple times in the array of styles. +// * If the same style attributes, such as font and color, occur in +// * multiple StyleRanges, getStyleRanges(boolean) +// * can be used to get the styles without the ranges. +// *

    +// * +// * @return the styles or an empty array if a LineStyleListener has been set. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getStyleRanges(boolean) +// */ +//public StyleRange[] getStyleRanges() { +// checkWidget(); +// return getStyleRanges(0, content.getCharCount(), true); +//} +///** +// * Returns the styles. +// *

    +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * Note: When includeRanges is true, the start and length +// * fields of each StyleRange will be valid, however the StyleRange +// * objects may need to be cloned. When includeRanges is +// * false, getRanges(int, int) can be used to get the +// * associated ranges. +// *

    +// * +// * @param includeRanges whether the start and length field of the StyleRanges should be set. +// * +// * @return the styles or an empty array if a LineStyleListener has been set. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.2 +// * +// * @see #getRanges(int, int) +// * @see #setStyleRanges(int[], StyleRange[]) +// */ +//public StyleRange[] getStyleRanges(boolean includeRanges) { +// checkWidget(); +// return getStyleRanges(0, content.getCharCount(), includeRanges); +//} +///** +// * Returns the styles for the given text range. +// *

    +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * Note: Because the StyleRange includes the start and length, the +// * same instance cannot occur multiple times in the array of styles. +// * If the same style attributes, such as font and color, occur in +// * multiple StyleRanges, getStyleRanges(int, int, boolean) +// * can be used to get the styles without the ranges. +// *

    +// * @param start the start offset of the style ranges to return +// * @param length the number of style ranges to return +// * +// * @return the styles or an empty array if a LineStyleListener has +// * been set. The returned styles will reflect the given range. The first +// * returned StyleRange will have a starting offset >= start +// * and the last returned StyleRange will have an ending +// * offset <= start + length - 1 +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • +// *
    +// * +// * @see #getStyleRanges(int, int, boolean) +// * +// * @since 3.0 +// */ +//public StyleRange[] getStyleRanges(int start, int length) { +// checkWidget(); +// return getStyleRanges(start, length, true); +//} +///** +// * Returns the styles for the given text range. +// *

    +// * Returns an empty array if a LineStyleListener has been set. +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * Note: When includeRanges is true, the start and length +// * fields of each StyleRange will be valid, however the StyleRange +// * objects may need to be cloned. When includeRanges is +// * false, getRanges(int, int) can be used to get the +// * associated ranges. +// *

    +// * +// * @param start the start offset of the style ranges to return +// * @param length the number of style ranges to return +// * @param includeRanges whether the start and length field of the StyleRanges should be set. +// * +// * @return the styles or an empty array if a LineStyleListener has +// * been set. The returned styles will reflect the given range. The first +// * returned StyleRange will have a starting offset >= start +// * and the last returned StyleRange will have an ending +// * offset >= start + length - 1 +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • +// *
    +// * +// * @since 3.2 +// * +// * @see #getRanges(int, int) +// * @see #setStyleRanges(int[], StyleRange[]) +// */ +//public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { +// checkWidget(); +// int contentLength = getCharCount(); +// int end = start + length; +// if (start > end || start < 0 || end > contentLength) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (!isListening(ST.LineGetStyle)) { +// StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges); +// if (ranges != null) return ranges; +// } +// return new StyleRange[0]; +//} +///** +// * Returns the tab width measured in characters. +// * +// * @return tab width measured in characters +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getTabStops() +// */ +//public int getTabs() { +// checkWidget(); +// return tabLength; +//} +// +///** +// * Returns the tab list of the receiver. +// * +// * @return the tab list +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.6 +// */ +//public int[] getTabStops() { +// checkWidget(); +// if (tabs == null) return new int [] {renderer.tabWidth}; +// int[] result = new int[tabs.length]; +// System.arraycopy(tabs, 0, result, 0, tabs.length); +// return result; +//} +// +///** +// * Returns a copy of the widget content. +// * +// * @return copy of the widget content +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public String getText() { +// checkWidget(); +// return content.getTextRange(0, getCharCount()); +//} +///** +// * Returns the widget content between the two offsets. +// * +// * @param start offset of the first character in the returned String +// * @param end offset of the last character in the returned String +// * @return widget content starting at start and ending at end +// * @see #getTextRange(int,int) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • +// *
    +// */ +//public String getText(int start, int end) { +// checkWidget(); +// int contentLength = getCharCount(); +// if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return content.getTextRange(start, end - start + 1); +//} +///** +// * Returns the smallest bounding rectangle that includes the characters between two offsets. +// * +// * @param start offset of the first character included in the bounding box +// * @param end offset of the last character included in the bounding box +// * @return bounding box of the text between start and end +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • +// *
    +// * @since 3.1 +// */ +//public Rectangle getTextBounds(int start, int end) { +// checkWidget(); +// int contentLength = getCharCount(); +// if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// int lineStart = content.getLineAtOffset(start); +// int lineEnd = content.getLineAtOffset(end); +// Rectangle rect; +// int y = getLinePixel(lineStart); +// int height = 0; +// int left = 0x7fffffff, right = 0; +// for (int i = lineStart; i <= lineEnd; i++) { +// int lineOffset = content.getOffsetAtLine(i); +// TextLayout layout = renderer.getTextLayout(i); +// int length = layout.getText().length(); +// if (length > 0) { +// if (i == lineStart) { +// if (i == lineEnd) { +// rect = layout.getBounds(start - lineOffset, end - lineOffset); +// } else { +// rect = layout.getBounds(start - lineOffset, length); +// } +// y += rect.y; +// } else if (i == lineEnd) { +// rect = layout.getBounds(0, end - lineOffset); +// } else { +// rect = layout.getBounds(); +// } +// left = Math.min(left, rect.x); +// right = Math.max(right, rect.x + rect.width); +// height += rect.height; +// } else { +// height += renderer.getLineHeight(); +// } +// renderer.disposeTextLayout(layout); +// } +// rect = new Rectangle (left, y, right-left, height); +// rect.x += leftMargin - horizontalScrollOffset; +// return rect; +//} +///** +// * Returns the widget content starting at start for length characters. +// * +// * @param start offset of the first character in the returned String +// * @param length number of characters to return +// * @return widget content starting at start and extending length characters. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or length are outside the widget content
    • +// *
    +// */ +//public String getTextRange(int start, int length) { +// checkWidget(); +// int contentLength = getCharCount(); +// int end = start + length; +// if (start > end || start < 0 || end > contentLength) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// return content.getTextRange(start, length); +//} +///** +// * Returns the maximum number of characters that the receiver is capable of holding. +// * +// * @return the text limit +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getTextLimit() { +// checkWidget(); +// return textLimit; +//} +///** +// * Gets the top index. +// *

    +// * The top index is the index of the fully visible line that is currently +// * at the top of the widget or the topmost partially visible line if no line is fully visible. +// * The top index changes when the widget is scrolled. Indexing is zero based. +// *

    +// * +// * @return the index of the top line +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getTopIndex() { +// checkWidget(); +// return topIndex; +//} +///** +// * Returns the top margin. +// * +// * @return the top margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public int getTopMargin() { +// checkWidget(); +// return topMargin; +//} +///** +// * Gets the top SWT logical point. +// *

    +// * The top point is the SWT logical point position of the line that is +// * currently at the top of the widget. The text widget can be scrolled by points +// * by dragging the scroll thumb so that a partial line may be displayed at the top +// * the widget. The top point changes when the widget is scrolled. The top point +// * does not include the widget trimming. +// *

    +// * +// * @return SWT logical point position of the top line +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public int getTopPixel() { +// checkWidget(); +// return getVerticalScrollOffset(); +//} +///** +// * Returns the vertical scroll increment. +// * +// * @return vertical scroll increment. +// */ +//int getVerticalIncrement() { +// return renderer.getLineHeight(); +//} +//int getVerticalScrollOffset() { +// if (verticalScrollOffset == -1) { +// renderer.calculate(0, topIndex); +// int height = 0; +// for (int i = 0; i < topIndex; i++) { +// height += renderer.getCachedLineHeight(i); +// } +// height -= topIndexY; +// verticalScrollOffset = height; +// } +// return verticalScrollOffset; +//} +//int getVisualLineIndex(TextLayout layout, int offsetInLine) { +// int lineIndex = layout.getLineIndex(offsetInLine); +// int[] offsets = layout.getLineOffsets(); +// Caret caret = getCaret(); +// if (caret != null && lineIndex != 0 && offsetInLine == offsets[lineIndex]) { +// int lineY = layout.getLineBounds(lineIndex).y; +// int caretY = caret.getLocation().y - getLinePixel(getFirstCaretLine()); +// if (lineY > caretY) lineIndex--; +// caretAlignment = OFFSET_LEADING; +// } +// return lineIndex; +//} +//int getCaretDirection() { +// if (!isBidiCaret()) return SWT.DEFAULT; +// if (ime.getCompositionOffset() != -1) return SWT.DEFAULT; +// if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection; +// updateCaretDirection = false; +// int caretLine = getFirstCaretLine(); +// int lineOffset = content.getOffsetAtLine(caretLine); +// String line = content.getLine(caretLine); +// int offset = caretOffsets[0] - lineOffset; +// int lineLength = line.length(); +// if (lineLength == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT; +// if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; +// if (offset == lineLength && offset > 0) offset--; +// while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; +// if (offset == 0 && Character.isDigit(line.charAt(offset))) { +// return isMirrored() ? SWT.RIGHT : SWT.LEFT; +// } +// TextLayout layout = renderer.getTextLayout(caretLine); +// int level = layout.getLevel(offset); +// renderer.disposeTextLayout(layout); +// return ((level & 1) != 0) ? SWT.RIGHT : SWT.LEFT; +//} +///* +// * Returns the index of the line the first/top caret is on. +// */ +//int getFirstCaretLine() { +// return content.getLineAtOffset(caretOffsets[0]); +//} +//int getWrapWidth () { +// if (wordWrap && !isSingleLine()) { +// int width = clientAreaWidth - leftMargin - rightMargin; +// return width > 0 ? width : 1; +// } +// return -1; +//} +//int getWordNext (int offset, int movement) { +// return getWordNext(offset, movement, false); +//} +//int getWordNext (int offset, int movement, boolean ignoreListener) { +// int newOffset, lineOffset; +// String lineText; +// if (offset >= getCharCount()) { +// newOffset = offset; +// int lineIndex = content.getLineCount() - 1; +// lineOffset = content.getOffsetAtLine(lineIndex); +// lineText = content.getLine(lineIndex); +// } else { +// int lineIndex = content.getLineAtOffset(offset); +// lineOffset = content.getOffsetAtLine(lineIndex); +// lineText = content.getLine(lineIndex); +// int lineLength = lineText.length(); +// if (offset >= lineOffset + lineLength) { +// newOffset = content.getOffsetAtLine(lineIndex + 1); +// } else { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement); +// renderer.disposeTextLayout(layout); +// } +// } +// if (ignoreListener) return newOffset; +// return sendWordBoundaryEvent(ST.WordNext, movement, offset, newOffset, lineText, lineOffset); +//} +//int getWordPrevious(int offset, int movement) { +// return getWordPrevious(offset, movement, false); +//} +//int getWordPrevious(int offset, int movement, boolean ignoreListener) { +// int newOffset, lineOffset; +// String lineText; +// if (offset <= 0) { +// newOffset = 0; +// int lineIndex = content.getLineAtOffset(newOffset); +// lineOffset = content.getOffsetAtLine(lineIndex); +// lineText = content.getLine(lineIndex); +// } else { +// int lineIndex = content.getLineAtOffset(offset); +// lineOffset = content.getOffsetAtLine(lineIndex); +// lineText = content.getLine(lineIndex); +// if (offset == lineOffset) { +// String nextLineText = content.getLine(lineIndex - 1); +// int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); +// newOffset = nextLineOffset + nextLineText.length(); +// } else { +// int layoutOffset = Math.min(offset - lineOffset, lineText.length()); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// newOffset = lineOffset + layout.getPreviousOffset(layoutOffset, movement); +// renderer.disposeTextLayout(layout); +// } +// } +// if (ignoreListener) return newOffset; +// return sendWordBoundaryEvent(ST.WordPrevious, movement, offset, newOffset, lineText, lineOffset); +//} +///** +// * Returns whether the widget wraps lines. +// * +// * @return true if widget wraps lines, false otherwise +// * @since 2.0 +// */ +//public boolean getWordWrap() { +// checkWidget(); +// return wordWrap; +//} +///** +// * Returns the wrap indentation of the widget. +// * +// * @return the wrap indentation +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #getLineWrapIndent(int) +// * +// * @since 3.6 +// */ +//public int getWrapIndent() { +// checkWidget(); +// return wrapIndent; +//} +///** +// * Returns the location of the given offset. +// *

    +// * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts). +// *

    +// * +// * @return location of the character at the given offset in the line. +// */ +//Point getPointAtOffset(int offset) { +// int lineIndex = content.getLineAtOffset(offset); +// String line = content.getLine(lineIndex); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// int offsetInLine = Math.max (0, offset - lineOffset); +// int lineLength = line.length(); +// if (lineIndex < content.getLineCount() - 1) { +// int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; +// if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { +// offsetInLine = lineLength; +// } +// } +// Point point; +// TextLayout layout = renderer.getTextLayout(lineIndex); +// if (lineLength != 0 && offsetInLine <= lineLength) { +// if (offsetInLine == lineLength) { +// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); +// point = layout.getLocation(offsetInLine, true); +// } else { +// switch (caretAlignment) { +// case OFFSET_LEADING: +// point = layout.getLocation(offsetInLine, false); +// break; +// case PREVIOUS_OFFSET_TRAILING: +// default: +// boolean lineBegin = offsetInLine == 0; +// // If word wrap is enabled, we should also consider offsets +// // of wrapped line parts as line begin and do NOT go back. +// // This prevents clients to jump one line higher than +// // expected, see bug 488172. +// // Respect caretAlignment at the caretOffset, unless there's +// // a non-empty selection, see bug 488172 comment 6. +// if (wordWrap && !lineBegin && (Arrays.binarySearch(caretOffsets, offset) < 0 || Arrays.stream(selection).allMatch(p -> p.x == p.y))) { +// int[] offsets = layout.getLineOffsets(); +// for (int i : offsets) { +// if (i == offsetInLine) { +// lineBegin = true; +// break; +// } +// } +// } +// if (lineBegin) { +// point = layout.getLocation(offsetInLine, false); +// } else { +// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); +// point = layout.getLocation(offsetInLine, true); +// } +// break; +// } +// } +// } else { +// point = new Point(layout.getIndent(), layout.getVerticalIndent()); +// } +// renderer.disposeTextLayout(layout); +// point.x += leftMargin - horizontalScrollOffset; +// point.y += getLinePixel(lineIndex); +// return point; +//} +///** +// * Inserts a string. The old selection is replaced with the new text. +// * +// * @param string the string +// * @see #replaceTextRange(int,int,String) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when string is null
    • +// *
    +// */ +//public void insert(String string) { +// checkWidget(); +// if (string == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// if (blockSelection) { +// insertBlockSelectionText(string, false); +// } else { +// Point sel = getSelectionRange(); +// replaceTextRange(sel.x, sel.y, string); +// } +//} +//int insertBlockSelectionText(String text, boolean fillWithSpaces) { +// int lineCount = 1; +// for (int i = 0; i < text.length(); i++) { +// char ch = text.charAt(i); +// if (ch == '\n' || ch == '\r') { +// lineCount++; +// if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') { +// i++; +// } +// } +// } +// String[] lines = new String[lineCount]; +// int start = 0; +// lineCount = 0; +// for (int i = 0; i < text.length(); i++) { +// char ch = text.charAt(i); +// if (ch == '\n' || ch == '\r') { +// lines[lineCount++] = text.substring(start, i); +// if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') { +// i++; +// } +// start = i + 1; +// } +// } +// lines[lineCount++] = text.substring(start); +// if (fillWithSpaces) { +// int maxLength = 0; +// for (String line : lines) { +// int length = line.length(); +// maxLength = Math.max(maxLength, length); +// } +// for (int i = 0; i < lines.length; i++) { +// String line = lines[i]; +// int length = line.length(); +// if (length < maxLength) { +// int numSpaces = maxLength - length; +// StringBuilder buffer = new StringBuilder(length + numSpaces); +// buffer.append(line); +// for (int j = 0; j < numSpaces; j++) buffer.append(' '); +// lines[i] = buffer.toString(); +// } +// } +// } +// int firstLine, lastLine, left, right; +// if (blockXLocation != -1) { +// Rectangle rect = getBlockSelectionPosition(); +// firstLine = rect.y; +// lastLine = rect.height; +// left = rect.x; +// right = rect.width; +// } else { +// firstLine = lastLine = getFirstCaretLine(); +// left = right = getPointAtOffset(caretOffsets[0]).x; +// } +// start = caretOffsets[0]; +// int caretLine = getFirstCaretLine(); +// int index = 0, lineIndex = firstLine; +// while (lineIndex <= lastLine) { +// String string = index < lineCount ? lines[index++] : ""; +// int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces); +// if (lineIndex == caretLine) start = lineStart; +// lineIndex++; +// } +// while (index < lineCount) { +// int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces); +// if (lineIndex == caretLine) start = lineStart; +// lineIndex++; +// } +// return start; +//} +//void insertBlockSelectionText(char key, int action) { +// if (key == SWT.CR || key == SWT.LF) return; +// Rectangle rect = getBlockSelectionPosition(); +// int firstLine = rect.y; +// int lastLine = rect.height; +// int left = rect.x; +// int right = rect.width; +// int[] trailing = new int[1]; +// int offset = 0, delta = 0; +// String text = key != 0 ? new String(new char[] {key}) : ""; +// int length = text.length(); +// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) { +// String line = content.getLine(lineIndex); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// int lineEndOffset = lineOffset + line.length(); +// int linePixel = getLinePixel(lineIndex); +// int start = getOffsetAtPoint(left, linePixel, trailing, true); +// boolean outOfLine = start == -1; +// if (outOfLine) { +// start = left < leftMargin ? lineOffset : lineEndOffset; +// } else { +// start += trailing[0]; +// } +// int end = getOffsetAtPoint(right, linePixel, trailing, true); +// if (end == -1) { +// end = right < leftMargin ? lineOffset : lineEndOffset; +// } else { +// end += trailing[0]; +// } +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// if (start == end && !outOfLine) { +// switch (action) { +// case ST.DELETE_PREVIOUS: +// if (start > lineOffset) start = getClusterPrevious(start, lineIndex); +// break; +// case ST.DELETE_NEXT: +// if (end < lineEndOffset) end = getClusterNext(end, lineIndex); +// break; +// } +// } +// if (outOfLine) { +// if (line.length() >= delta) { +// delta = line.length(); +// offset = lineEndOffset + length; +// } +// } else { +// offset = start + length; +// delta = content.getCharCount(); +// } +// Event event = new Event(); +// event.text = text; +// event.start = start; +// event.end = end; +// sendKeyEvent(event); +// } +// int x = getPointAtOffset(offset).x; +// int verticalScrollOffset = getVerticalScrollOffset(); +// setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false); +//} +///** +// * Creates content change listeners and set the default content model. +// */ +//void installDefaultContent() { +// textChangeListener = new TextChangeListener() { +// @Override +// public void textChanging(TextChangingEvent event) { +// handleTextChanging(event); +// } +// @Override +// public void textChanged(TextChangedEvent event) { +// handleTextChanged(event); +// } +// @Override +// public void textSet(TextChangedEvent event) { +// handleTextSet(event); +// } +// }; +// content = new DefaultContent(); +// content.addTextChangeListener(textChangeListener); +//} +///** +// * Adds event listeners +// */ +//void installListeners() { +// ScrollBar verticalBar = getVerticalBar(); +// ScrollBar horizontalBar = getHorizontalBar(); +// +// listener = event -> { +// switch (event.type) { +// case SWT.Dispose: handleDispose(event); break; +// case SWT.KeyDown: handleKeyDown(event); break; +// case SWT.KeyUp: handleKeyUp(event); break; +// case SWT.MenuDetect: handleMenuDetect(event); break; +// case SWT.MouseDown: handleMouseDown(event); break; +// case SWT.MouseUp: handleMouseUp(event); break; +// case SWT.MouseMove: handleMouseMove(event); break; +// case SWT.Paint: handlePaint(event); break; +// case SWT.Resize: handleResize(event); break; +// case SWT.Traverse: handleTraverse(event); break; +// } +// }; +// addListener(SWT.Dispose, listener); +// addListener(SWT.KeyDown, listener); +// addListener(SWT.KeyUp, listener); +// addListener(SWT.MenuDetect, listener); +// addListener(SWT.MouseDown, listener); +// addListener(SWT.MouseUp, listener); +// addListener(SWT.MouseMove, listener); +// addListener(SWT.Paint, listener); +// addListener(SWT.Resize, listener); +// addListener(SWT.Traverse, listener); +// ime.addListener(SWT.ImeComposition, event -> { +// if (!editable) { +// event.doit = false; +// event.start = 0; +// event.end = 0; +// event.text = ""; +// return; +// } +// +// switch (event.detail) { +// case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; +// case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; +// case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; +// } +// }); +// if (verticalBar != null) { +// verticalBar.addListener(SWT.Selection, this::handleVerticalScroll); +// } +// if (horizontalBar != null) { +// horizontalBar.addListener(SWT.Selection, this::handleHorizontalScroll); +// } +//} +//void internalRedrawRange(int start, int length) { +// if (length <= 0) return; +// int end = start + length; +// int startLine = content.getLineAtOffset(start); +// int endLine = content.getLineAtOffset(end); +// int partialBottomIndex = getPartialBottomIndex(); +// int partialTopIndex = getPartialTopIndex(); +// if (startLine > partialBottomIndex || endLine < partialTopIndex) { +// return; +// } +// if (partialTopIndex > startLine) { +// startLine = partialTopIndex; +// start = 0; +// } else { +// start -= content.getOffsetAtLine(startLine); +// } +// if (partialBottomIndex < endLine) { +// endLine = partialBottomIndex + 1; +// end = 0; +// } else { +// end -= content.getOffsetAtLine(endLine); +// } +// +// TextLayout layout = renderer.getTextLayout(startLine); +// int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); +// int[] offsets = layout.getLineOffsets(); +// int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); +// +// /* Redraw end of line before start line if wrapped and start offset is first char */ +// if (isWordWrap() && startIndex > 0 && offsets[startIndex] == start) { +// Rectangle rect = layout.getLineBounds(startIndex - 1); +// rect.x = rect.width; +// rect.width = clientAreaWidth - rightMargin - rect.x; +// rect.x += lineX; +// rect.y += startLineY; +// super.redraw(rect.x, rect.y, rect.width, rect.height, false); +// } +// +// if (startLine == endLine) { +// int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); +// if (startIndex == endIndex) { +// /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ +// Rectangle rect = layout.getBounds(start, end - 1); +// rect.x += lineX; +// rect.y += startLineY; +// super.redraw(rect.x, rect.y, rect.width, rect.height, false); +// renderer.disposeTextLayout(layout); +// return; +// } +// } +// +// /* Redraw start line from the start offset to the end of client area */ +// Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1); +// if (startRect.height == 0) { +// Rectangle bounds = layout.getLineBounds(startIndex); +// startRect.x = bounds.width; +// startRect.y = bounds.y; +// startRect.height = bounds.height; +// } +// startRect.x += lineX; +// startRect.y += startLineY; +// startRect.width = clientAreaWidth - rightMargin - startRect.x; +// super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false); +// +// /* Redraw end line from the beginning of the line to the end offset */ +// if (startLine != endLine) { +// renderer.disposeTextLayout(layout); +// layout = renderer.getTextLayout(endLine); +// offsets = layout.getLineOffsets(); +// } +// int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); +// Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); +// if (endRect.height == 0) { +// Rectangle bounds = layout.getLineBounds(endIndex); +// endRect.y = bounds.y; +// endRect.height = bounds.height; +// } +// endRect.x += lineX; +// endRect.y += getLinePixel(endLine); +// super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false); +// renderer.disposeTextLayout(layout); +// +// /* Redraw all lines in between start and end line */ +// int y = startRect.y + startRect.height; +// if (endRect.y > y) { +// super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false); +// } +//} +//void handleCompositionOffset (Event event) { +// int[] trailing = new int [1]; +// event.index = getOffsetAtPoint(event.x, event.y, trailing, true); +// event.count = trailing[0]; +//} +//void handleCompositionSelection (Event event) { +// if (event.start != event.end) { +// int charCount = getCharCount(); +// event.start = Math.max(0, Math.min(event.start, charCount)); +// event.end = Math.max(0, Math.min(event.end, charCount)); +// if (event.text != null) { +// setSelection(event.start, event.end); +// } else { +// event.text = getTextRange(event.start, event.end - event.start); +// } +// } else { +// event.start = selection[0].x; +// event.end = selection[0].y; +// event.text = getSelectionText(); +// } +//} +//void handleCompositionChanged(Event event) { +// String text = event.text; +// int start = event.start; +// int end = event.end; +// int charCount = content.getCharCount(); +// start = Math.min(start, charCount); +// end = Math.min(end, charCount); +// int length = text.length(); +// if (length == ime.getCommitCount()) { +// content.replaceTextRange(start, end - start, ""); +// setCaretOffsets(new int[] {ime.getCompositionOffset()}, SWT.DEFAULT); +// caretWidth = 0; +// caretDirection = SWT.NULL; +// } else { +// content.replaceTextRange(start, end - start, text); +// int alignment = SWT.DEFAULT; +// if (ime.getWideCaret()) { +// start = ime.getCompositionOffset(); +// for (int caretOffset : caretOffsets) { +// int lineIndex = content.getLineAtOffset(caretOffset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; +// renderer.disposeTextLayout(layout); +// } +// alignment = OFFSET_LEADING; +// } +// setCaretOffsets(new int[] {ime.getCaretOffset()}, alignment); +// } +// resetSelection(); +// showCaret(); +//} +///** +// * Frees resources. +// */ +//void handleDispose(Event event) { +// removeListener(SWT.Dispose, listener); +// notifyListeners(SWT.Dispose, event); +// event.type = SWT.None; +// +// clipboard.dispose(); +// if (renderer != null) { +// renderer.dispose(); +// renderer = null; +// } +// if (content != null) { +// content.removeTextChangeListener(textChangeListener); +// content = null; +// } +// if (defaultCaret != null) { +// defaultCaret.dispose(); +// defaultCaret = null; +// } +// if (leftCaretBitmap != null) { +// leftCaretBitmap.dispose(); +// leftCaretBitmap = null; +// } +// if (rightCaretBitmap != null) { +// rightCaretBitmap.dispose(); +// rightCaretBitmap = null; +// } +// if (carets != null) { +// for (Caret caret : carets) { +// if (caret != null) { +// caret.dispose(); +// } +// } +// carets = null; +// } +// if (isBidiCaret()) { +// BidiUtil.removeLanguageListener(this); +// } +// selectionBackground = null; +// selectionForeground = null; +// marginColor = null; +// textChangeListener = null; +// selection = null; +// doubleClickSelection = null; +// keyActionMap = null; +// background = null; +// foreground = null; +// clipboard = null; +// tabs = null; +//} +///** +// * Scrolls the widget horizontally. +// */ +//void handleHorizontalScroll(Event event) { +// int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; +// scrollHorizontal(scrollPixel, false); +//} +///** +// * If an action has been registered for the key stroke execute the action. +// * Otherwise, if a character has been entered treat it as new content. +// * +// * @param event keyboard event +// */ +//void handleKey(Event event) { +// int action; +// caretAlignment = PREVIOUS_OFFSET_TRAILING; +// if (event.keyCode != 0) { +// // special key pressed (e.g., F1) +// action = getKeyBinding(event.keyCode | event.stateMask); +// } else { +// // character key pressed +// action = getKeyBinding(event.character | event.stateMask); +// if (action == SWT.NULL) { +// // see if we have a control character +// if ((event.stateMask & SWT.CTRL) != 0 && event.character <= 31) { +// // get the character from the CTRL+char sequence, the control +// // key subtracts 64 from the value of the key that it modifies +// int c = event.character + 64; +// action = getKeyBinding(c | event.stateMask); +// } +// } +// } +// if (action == SWT.NULL) { +// boolean ignore = false; +// +// if (IS_MAC) { +// // Ignore accelerator key combinations (we do not want to +// // insert a character in the text in this instance). +// ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 0; +// } else { +// // Ignore accelerator key combinations (we do not want to +// // insert a character in the text in this instance). Don't +// // ignore CTRL+ALT combinations since that is the Alt Gr +// // key on some keyboards. See bug 20953. +// ignore = event.stateMask == SWT.ALT || +// event.stateMask == SWT.CTRL || +// event.stateMask == (SWT.ALT | SWT.SHIFT) || +// event.stateMask == (SWT.CTRL | SWT.SHIFT); +// } +// // -ignore anything below SPACE except for line delimiter keys and tab. +// // -ignore DEL +// if (!ignore && event.character > 31 && event.character != SWT.DEL || +// event.character == SWT.CR || event.character == SWT.LF || +// event.character == TAB) { +// doContent(event.character); +// update(); +// } +// } else { +// invokeAction(action); +// } +//} +///** +// * If a VerifyKey listener exists, verify that the key that was entered +// * should be processed. +// * +// * @param event keyboard event +// */ +//void handleKeyDown(Event event) { +// if (clipboardSelection == null) { +// clipboardSelection = new Point(selection[0].x, selection[0].y); +// } +// newOrientation = SWT.NONE; +// event.stateMask &= SWT.MODIFIER_MASK; +// +// Event verifyEvent = new Event(); +// verifyEvent.character = event.character; +// verifyEvent.keyCode = event.keyCode; +// verifyEvent.keyLocation = event.keyLocation; +// verifyEvent.stateMask = event.stateMask; +// verifyEvent.doit = event.doit; +// notifyListeners(ST.VerifyKey, verifyEvent); +// if (verifyEvent.doit) { +// if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) { +// newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT; +// } +// handleKey(event); +// } +//} +///** +// * Update the Selection Clipboard. +// * +// * @param event keyboard event +// */ +//void handleKeyUp(Event event) { +// if (clipboardSelection != null) { +// if (clipboardSelection.x != selection[0].x || clipboardSelection.y != selection[0].y) { +// copySelection(DND.SELECTION_CLIPBOARD); +// } +// } +// clipboardSelection = null; +// +// if (newOrientation != SWT.NONE) { +// if (newOrientation != getOrientation()) { +// Event e = new Event(); +// e.doit = true; +// notifyListeners(SWT.OrientationChange, e); +// if (e.doit) { +// setOrientation(newOrientation); +// } +// } +// newOrientation = SWT.NONE; +// } +//} +///** +// * Update the event location for focus-based context menu triggers. +// * +// * @param event menu detect event +// */ +//void handleMenuDetect(Event event) { +// if (event.detail == SWT.MENU_KEYBOARD) { +// Point point = getDisplay().map(this, null, getPointAtOffset(caretOffsets[0])); +// event.x = point.x; +// event.y = point.y + getLineHeight(caretOffsets[0]); +// } +//} +///** +// * Updates the caret location and selection if mouse button 1 has been +// * pressed. +// */ +//void handleMouseDown(Event event) { +// //force focus (object support) +// forceFocus(); +// +// //drag detect +// if (dragDetect && checkDragDetect(event)) return; +// +// //paste clipboard selection +// if (event.button == 2) { +// // On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from +// // a long middle-click (mouse navigation started) +// if (IS_GTK && mouseNavigator != null) { +// middleClickPressed = true; +// getDisplay().timerExec(200, ()->{ +// boolean click = middleClickPressed; +// middleClickPressed = false; +// if (click && mouseNavigator !=null) { +// mouseNavigator.onMouseDown(event); +// } else { +// pasteOnMiddleClick(event); +// } +// }); +// return; +// } else { +// pasteOnMiddleClick(event); +// } +// } +// +// //set selection +// if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) { +// return; +// } +// clickCount = event.count; +// boolean addSelection = (event.stateMask & SWT.MOD3) != 0; +// if (clickCount == 1) { +// if (addSelection && !blockSelection) { +// int offset = getOffsetAtPoint(event.x, event.y, null); +// addSelection(offset, 0); +// sendSelectionEvent(); +// } else { +// boolean expandSelection = (event.stateMask & SWT.MOD2) != 0; +// doMouseLocationChange(event.x, event.y, expandSelection); +// } +// } else { +// if (doubleClickEnabled) { +// boolean wordSelect = (clickCount & 1) == 0; +// int offset = getOffsetAtPoint(event.x, event.y, null); +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// if (wordSelect) { +// String line = content.getLine(lineIndex); +// int lineLength = line.length(); +// int min = blockSelection ? lineOffset : 0; +// int max = blockSelection ? lineOffset + lineLength : content.getCharCount(); +// final Point offsetPoint = getPointAtOffset(offset); +// if (event.x > offsetPoint.x +// && offset < Math.min(max, lineOffset + lineLength) // Not beyond EOL +// && !Character.isWhitespace(line.charAt(offset - lineOffset))) { // Not on whitespace +// offset++; +// } +// int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START)); +// int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END)); +// int[] regions = new int[2]; +// if (addSelection) { +// int[] current = getSelectionRanges(); +// regions = Arrays.copyOf(current, current.length + 2); +// } +// regions[regions.length - 2] = start; +// regions[regions.length - 1] = end - start; +// setSelection(regions, false, true); +// sendSelectionEvent(); +// } else { +// if (blockSelection) { +// setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true); +// } else { +// int lineEnd = content.getCharCount(); +// if (lineIndex + 1 < content.getLineCount()) { +// lineEnd = content.getOffsetAtLine(lineIndex + 1); +// } +// int[] regions = new int[2]; +// if (addSelection) { +// int[] current = getSelectionRanges(); +// regions = Arrays.copyOf(current, current.length + 2); +// } +// regions[regions.length - 2] = lineOffset; +// regions[regions.length - 1] = lineEnd - lineOffset; +// setSelection(regions, false, false); +// sendSelectionEvent(); +// } +// } +// doubleClickSelection = new Point(selection[0].x, selection[0].y); +// showCaret(); +// } +// } +//} +// +//void addSelection(int offset, int length) { +// int[] ranges = getSelectionRanges(); +// ranges = Arrays.copyOf(ranges, ranges.length + 2); +// ranges[ranges.length - 2] = offset; +// ranges[ranges.length - 1] = length; +// setSelection(ranges, true, true); +//} +// +///** +// * Updates the caret location and selection if mouse button 1 is pressed +// * during the mouse move. +// */ +//void handleMouseMove(Event event) { +// if (clickCount > 0) { +// update(); +// doAutoScroll(event); +// doMouseLocationChange(event.x, event.y, true); +// } +// if (renderer.hasLinks) { +// doMouseLinkCursor(event.x, event.y); +// } +//} +///** +// * Autoscrolling ends when the mouse button is released. +// */ +//void handleMouseUp(Event event) { +// middleClickPressed = false; +// clickCount = 0; +// endAutoScroll(); +// if (event.button == 1) { +// copySelection(DND.SELECTION_CLIPBOARD); +// } +//} +///** +// * Renders the invalidated area specified in the paint event. +// * +// * @param event paint event +// */ +//void handlePaint(Event event) { +// if (event.width == 0 || event.height == 0) return; +// if (clientAreaWidth == 0 || clientAreaHeight == 0) return; +// +// final int endY = event.y + event.height; +// GC gc = event.gc; +// Color background = getBackground(); +// Color foreground = getForeground(); +// if (endY > 0) { +// final int startLine = getLineIndex(event.y); +// final int endLine = isSingleLine() ? 1 : content.getLineCount(); +// final int x = leftMargin - horizontalScrollOffset; +// int y = getLinePixel(startLine); +// y += renderer.drawLines(startLine, endLine, x, y, endY, gc, background, foreground); +// if (y < endY) { +// gc.setBackground(background); +// drawBackground(gc, 0, y, clientAreaWidth, endY - y); +// } +// } +// if (blockSelection && blockXLocation != -1) { +// gc.setBackground(getSelectionBackground()); +// Rectangle rect = getBlockSelectionRectangle(); +// gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1)); +// gc.setAdvanced(true); +// if (gc.getAdvanced()) { +// gc.setAlpha(100); +// gc.fillRectangle(rect); +// gc.setAdvanced(false); +// } +// } +// if(carets != null) { +// for (int i = 1; i < carets.length; i++) { //skip 1st caret that's already drawn +// Caret caret = carets[i]; +// if (caret.isVisible()) { +// if (caret.getImage() != null) { +// gc.drawImage(caret.getImage(), caret.getBounds().x, caret.getBounds().y); +// } else { +// gc.drawRectangle(caret.getBounds().x, caret.getBounds().y, caret.getBounds().width, getLineHeight(caretOffsets[i])); +// } +// } +// } +// } +// +// // fill the margin background +// gc.setBackground(marginColor != null ? marginColor : background); +// if (topMargin > 0) { +// drawBackground(gc, 0, 0, clientAreaWidth, topMargin); +// } +// if (bottomMargin > 0) { +// drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin); +// } +// if (leftMargin - alignmentMargin > 0) { +// drawBackground(gc, 0, 0, leftMargin - alignmentMargin, clientAreaHeight); +// } +// if (rightMargin > 0) { +// drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight); +// } +//} +///** +// * Recalculates the scroll bars. Rewraps all lines when in word +// * wrap mode. +// * +// * @param event resize event +// */ +//void handleResize(Event event) { +// int oldHeight = clientAreaHeight; +// int oldWidth = clientAreaWidth; +// Rectangle clientArea = getClientArea(); +// clientAreaHeight = clientArea.height; +// clientAreaWidth = clientArea.width; +// if (!alwaysShowScroll && ignoreResize != 0) return; +// +// redrawMargins(oldHeight, oldWidth); +// if (wordWrap) { +// if (oldWidth != clientAreaWidth) { +// renderer.reset(0, content.getLineCount()); +// verticalScrollOffset = -1; +// renderer.calculateIdle(); +// super.redraw(); +// } +// if (oldHeight != clientAreaHeight) { +// if (oldHeight == 0) topIndexY = 0; +// setScrollBars(true); +// } +// setCaretLocations(); +// } else { +// renderer.calculateClientArea(); +// setScrollBars(true); +// claimRightFreeSpace(); +// // StyledText allows any value for horizontalScrollOffset when clientArea is zero +// // in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429. +// if (clientAreaWidth != 0) { +// ScrollBar horizontalBar = getHorizontalBar(); +// if (horizontalBar != null && horizontalBar.getVisible()) { +// if (horizontalScrollOffset != horizontalBar.getSelection()) { +// horizontalBar.setSelection(horizontalScrollOffset); +// horizontalScrollOffset = horizontalBar.getSelection(); +// } +// } +// } +// } +// updateCaretVisibility(); +// claimBottomFreeSpace(); +// setAlignment(); +// //TODO FIX TOP INDEX DURING RESIZE +//// if (oldHeight != clientAreaHeight || wordWrap) { +//// calculateTopIndex(0); +//// } +//} +///** +// * Updates the caret position and selection and the scroll bars to reflect +// * the content change. +// */ +//void handleTextChanged(TextChangedEvent event) { +// int offset = ime.getCompositionOffset(); +// if (offset != -1 && lastTextChangeStart < offset) { +// // updating the compositionOffset of the ongoing IME if last IMEs text is deleted meanwhile +// // for example 1.insert IME text 2.open IME menu 3. ctrl+backspace => 4. commit IME would result in IllegalArgumentException +// int compositionOffset = ime.getCaretOffset() + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount; +// // workaround: while ongoing IME non-ime text is deleted it may result in too big compositionOffset +// // for example 1.insert IME text 2.insert space 3.open IME menu 4. ctrl+backspace twice => 5. commit IME would result in IllegalArgumentException +// compositionOffset= Math.min(compositionOffset, getCharCount()); +// ime.setCompositionOffset(compositionOffset); +// } +// int firstLine = content.getLineAtOffset(lastTextChangeStart); +// resetCache(firstLine, 0); +// if (!isFixedLineHeight() && topIndex > firstLine) { +// topIndex = firstLine; +// if (topIndex < 0) { +// // TODO: This logging is in place to determine why topIndex is getting set to negative values. +// // It should be deleted once we fix the root cause of this issue. See bug 487254 for details. +// System.err.println("StyledText: topIndex was " + topIndex +// + ", lastTextChangeStart = " + lastTextChangeStart +// + ", content.getClass() = " + content.getClass() +// ); +// topIndex = 0; +// } +// topIndexY = 0; +// super.redraw(); +// } else { +// int lastLine = firstLine + lastTextChangeNewLineCount; +// int firstLineTop = getLinePixel(firstLine); +// int newLastLineBottom = getLinePixel(lastLine + 1); +// if (lastLineBottom != newLastLineBottom) { +// super.redraw(); +// } else { +// super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); +// redrawLinesBullet(renderer.redrawLines); +// } +// } +// renderer.redrawLines = null; +// // update selection/caret location after styles have been changed. +// // otherwise any text measuring could be incorrect +// // +// // also, this needs to be done after all scrolling. Otherwise, +// // selection redraw would be flushed during scroll which is wrong. +// // in some cases new text would be drawn in scroll source area even +// // though the intent is to scroll it. +// if (!(blockSelection && blockXLocation != -1)) { +// updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); +// } +// if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) { +// claimBottomFreeSpace(); +// } +// if (lastTextChangeReplaceCharCount > 0) { +// claimRightFreeSpace(); +// } +// +// sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0); +// lastCharCount += lastTextChangeNewCharCount; +// lastCharCount -= lastTextChangeReplaceCharCount; +// setAlignment(); +//} +///** +// * Updates the screen to reflect a pending content change. +// * +// * @param event .start the start offset of the change +// * @param event .newText text that is going to be inserted or empty String +// * if no text will be inserted +// * @param event .replaceCharCount length of text that is going to be replaced +// * @param event .newCharCount length of text that is going to be inserted +// * @param event .replaceLineCount number of lines that are going to be replaced +// * @param event .newLineCount number of new lines that are going to be inserted +// */ +//void handleTextChanging(TextChangingEvent event) { +// if (event.replaceCharCount < 0) { +// event.start += event.replaceCharCount; +// event.replaceCharCount *= -1; +// } +// lastTextChangeStart = event.start; +// lastTextChangeNewLineCount = event.newLineCount; +// lastTextChangeNewCharCount = event.newCharCount; +// lastTextChangeReplaceLineCount = event.replaceLineCount; +// lastTextChangeReplaceCharCount = event.replaceCharCount; +// int lineIndex = content.getLineAtOffset(event.start); +// int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); +// int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); +// lastLineBottom = destY; +// if (srcY < 0 && destY < 0) { +// lastLineBottom += srcY - destY; +// verticalScrollOffset += destY - srcY; +// calculateTopIndex(destY - srcY); +// setScrollBars(true); +// } else { +// scrollText(srcY, destY); +// } +// sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount); +// renderer.textChanging(event); +// +// // Update the caret offset if it is greater than the length of the content. +// // This is necessary since style range API may be called between the +// // handleTextChanging and handleTextChanged events and this API sets the +// // caretOffset. +// int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; +// int tooBigOffsets = 0; +// while (tooBigOffsets < caretOffsets.length && caretOffsets[caretOffsets.length - 1 - tooBigOffsets] > newEndOfText) { +// tooBigOffsets++; +// } +// if (tooBigOffsets != 0) { +// int[] newCaretOffsets = Arrays.copyOf(caretOffsets, caretOffsets.length - tooBigOffsets + 1); +// newCaretOffsets[newCaretOffsets.length - 1] = newEndOfText; +// setCaretOffsets(newCaretOffsets, SWT.DEFAULT); +// } +//} +///** +// * Called when the widget content is set programmatically, overwriting +// * the old content. Resets the caret position, selection and scroll offsets. +// * Recalculates the content width and scroll bars. Redraws the widget. +// * +// * @param event text change event. +// */ +//void handleTextSet(TextChangedEvent event) { +// reset(); +// int newCharCount = getCharCount(); +// sendAccessibleTextChanged(0, newCharCount, lastCharCount); +// lastCharCount = newCharCount; +// setAlignment(); +//} +///** +// * Called when a traversal key is pressed. +// * Allow tab next traversal to occur when the widget is in single +// * line mode or in multi line and non-editable mode . +// * When in editable multi line mode we want to prevent the tab +// * traversal and receive the tab key event instead. +// * +// * @param event the event +// */ +//void handleTraverse(Event event) { +// switch (event.detail) { +// case SWT.TRAVERSE_ESCAPE: +// case SWT.TRAVERSE_PAGE_NEXT: +// case SWT.TRAVERSE_PAGE_PREVIOUS: +// event.doit = true; +// break; +// case SWT.TRAVERSE_RETURN: +// case SWT.TRAVERSE_TAB_NEXT: +// case SWT.TRAVERSE_TAB_PREVIOUS: +// if ((getStyle() & SWT.SINGLE) != 0) { +// event.doit = true; +// } else { +// if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) { +// event.doit = true; +// } +// } +// break; +// } +//} +///** +// * Scrolls the widget vertically. +// */ +//void handleVerticalScroll(Event event) { +// int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset(); +// scrollVertical(scrollPixel, false); +//} +///** +// * Add accessibility support for the widget. +// */ +//void initializeAccessible() { +// acc = getAccessible(); +// +// accAdapter = new AccessibleAdapter() { +// @Override +// public void getName (AccessibleEvent e) { +// String name = null; +// String text = getAssociatedLabel (); +// if (text != null) { +// name = stripMnemonic (text); +// } +// e.result = name; +// } +// @Override +// public void getHelp(AccessibleEvent e) { +// e.result = getToolTipText(); +// } +// @Override +// public void getKeyboardShortcut(AccessibleEvent e) { +// String shortcut = null; +// String text = getAssociatedLabel (); +// if (text != null) { +// char mnemonic = _findMnemonic (text); +// if (mnemonic != '\0') { +// shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ +// } +// } +// e.result = shortcut; +// } +// }; +// acc.addAccessibleListener(accAdapter); +// +// accTextExtendedAdapter = new AccessibleTextExtendedAdapter() { +// @Override +// public void getCaretOffset(AccessibleTextEvent e) { +// e.offset = StyledText.this.getCaretOffset(); +// } +// @Override +// public void setCaretOffset(AccessibleTextEvent e) { +// StyledText.this.setCaretOffset(e.offset); +// e.result = ACC.OK; +// } +// @Override +// public void getSelectionRange(AccessibleTextEvent e) { +// Point selection = StyledText.this.getSelectionRange(); +// e.offset = selection.x; +// e.length = selection.y; +// } +// @Override +// public void addSelection(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// Point point = st.getSelection(); +// if (point.x == point.y) { +// int end = e.end; +// if (end == -1) end = st.getCharCount(); +// st.setSelection(e.start, end); +// e.result = ACC.OK; +// } +// } +// @Override +// public void getSelection(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// if (st.blockSelection && st.blockXLocation != -1) { +// Rectangle rect = st.getBlockSelectionPosition(); +// int lineIndex = rect.y + e.index; +// int linePixel = st.getLinePixel(lineIndex); +// e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel); +// if (e.ranges.length > 0) { +// e.start = e.ranges[0]; +// e.end = e.ranges[e.ranges.length - 1]; +// } +// } else { +// if (e.index == 0) { +// Point point = st.getSelection(); +// e.start = point.x; +// e.end = point.y; +// if (e.start > e.end) { +// int temp = e.start; +// e.start = e.end; +// e.end = temp; +// } +// } +// } +// } +// @Override +// public void getSelectionCount(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// if (st.blockSelection && st.blockXLocation != -1) { +// Rectangle rect = st.getBlockSelectionPosition(); +// e.count = rect.height - rect.y + 1; +// } else { +// Point point = st.getSelection(); +// e.count = point.x == point.y ? 0 : 1; +// } +// } +// @Override +// public void removeSelection(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// if (e.index == 0) { +// if (st.blockSelection) { +// st.clearBlockSelection(true, false); +// } else { +// st.clearSelection(false); +// } +// e.result = ACC.OK; +// } +// } +// @Override +// public void setSelection(AccessibleTextEvent e) { +// if (e.index != 0) return; +// StyledText st = StyledText.this; +// Point point = st.getSelection(); +// if (point.x == point.y) return; +// int end = e.end; +// if (end == -1) end = st.getCharCount(); +// st.setSelection(e.start, end); +// e.result = ACC.OK; +// } +// @Override +// public void getCharacterCount(AccessibleTextEvent e) { +// e.count = StyledText.this.getCharCount(); +// } +// @Override +// public void getOffsetAtPoint(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// Point point = new Point (e.x, e.y); +// Display display = st.getDisplay(); +// point = display.map(null, st, point); +// e.offset = st.getOffsetAtPoint(point.x, point.y, null, true); +// } +// @Override +// public void getTextBounds(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// int start = e.start; +// int end = e.end; +// int contentLength = st.getCharCount(); +// start = Math.max(0, Math.min(start, contentLength)); +// end = Math.max(0, Math.min(end, contentLength)); +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// int startLine = st.getLineAtOffset(start); +// int endLine = st.getLineAtOffset(end); +// Rectangle[] rects = new Rectangle[endLine - startLine + 1]; +// Rectangle bounds = null; +// int index = 0; +// Display display = st.getDisplay(); +// for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) { +// Rectangle rect = new Rectangle(0, 0, 0, 0); +// rect.y = st.getLinePixel(lineIndex); +// rect.height = st.renderer.getLineHeight(lineIndex); +// if (lineIndex == startLine) { +// rect.x = st.getPointAtOffset(start).x; +// } else { +// rect.x = st.leftMargin - st.horizontalScrollOffset; +// } +// if (lineIndex == endLine) { +// rect.width = st.getPointAtOffset(end).x - rect.x; +// } else { +// TextLayout layout = st.renderer.getTextLayout(lineIndex); +// rect.width = layout.getBounds().width - rect.x; +// st.renderer.disposeTextLayout(layout); +// } +// rects [index++] = rect = display.map(st, null, rect); +// if (bounds == null) { +// bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height); +// } else { +// bounds.add(rect); +// } +// } +// e.rectangles = rects; +// if (bounds != null) { +// e.x = bounds.x; +// e.y = bounds.y; +// e.width = bounds.width; +// e.height = bounds.height; +// } +// } +// int[] getRanges(int left, int top, int right, int bottom) { +// StyledText st = StyledText.this; +// int lineStart = st.getLineIndex(top); +// int lineEnd = st.getLineIndex(bottom); +// int count = lineEnd - lineStart + 1; +// int[] ranges = new int [count * 2]; +// int index = 0; +// for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) { +// String line = st.content.getLine(lineIndex); +// int lineOffset = st.content.getOffsetAtLine(lineIndex); +// int lineEndOffset = lineOffset + line.length(); +// int linePixel = st.getLinePixel(lineIndex); +// int start = st.getOffsetAtPoint(left, linePixel, null, true); +// if (start == -1) { +// start = left < st.leftMargin ? lineOffset : lineEndOffset; +// } +// int[] trailing = new int[1]; +// int end = st.getOffsetAtPoint(right, linePixel, trailing, true); +// if (end == -1) { +// end = right < st.leftMargin ? lineOffset : lineEndOffset; +// } else { +// end += trailing[0]; +// } +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// ranges[index++] = start; +// ranges[index++] = end; +// } +// return ranges; +// } +// @Override +// public void getRanges(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// Point point = new Point (e.x, e.y); +// Display display = st.getDisplay(); +// point = display.map(null, st, point); +// e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height); +// if (e.ranges.length > 0) { +// e.start = e.ranges[0]; +// e.end = e.ranges[e.ranges.length - 1]; +// } +// } +// @Override +// public void getText(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// int start = e.start; +// int end = e.end; +// int contentLength = st.getCharCount(); +// if (end == -1) end = contentLength; +// start = Math.max(0, Math.min(start, contentLength)); +// end = Math.max(0, Math.min(end, contentLength)); +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// int count = e.count; +// switch (e.type) { +// case ACC.TEXT_BOUNDARY_ALL: +// //nothing to do +// break; +// case ACC.TEXT_BOUNDARY_CHAR: { +// int newCount = 0; +// if (count > 0) { +// while (count-- > 0) { +// int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER); +// if (newEnd == contentLength) break; +// if (newEnd == end) break; +// end = newEnd; +// newCount++; +// } +// start = end; +// end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER); +// } else { +// while (count++ < 0) { +// int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER); +// if (newStart == start) break; +// start = newStart; +// newCount--; +// } +// end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER); +// } +// count = newCount; +// break; +// } +// case ACC.TEXT_BOUNDARY_WORD: { +// int newCount = 0; +// if (count > 0) { +// while (count-- > 0) { +// int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true); +// if (newEnd == end) break; +// newCount++; +// end = newEnd; +// } +// start = end; +// end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true); +// } else { +// if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) { +// //start is a word start already +// count++; +// } +// while (count <= 0) { +// int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true); +// if (newStart == start) break; +// count++; +// start = newStart; +// if (count != 0) newCount--; +// } +// if (count <= 0 && start == 0) { +// end = start; +// } else { +// end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true); +// } +// } +// count = newCount; +// break; +// } +// case ACC.TEXT_BOUNDARY_LINE: +// //TODO implement line +// case ACC.TEXT_BOUNDARY_PARAGRAPH: +// case ACC.TEXT_BOUNDARY_SENTENCE: { +// int offset = count > 0 ? end : start; +// int lineIndex = st.getLineAtOffset(offset) + count; +// lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1)); +// start = st.getOffsetAtLine(lineIndex); +// String line = st.getLine(lineIndex); +// end = start + line.length(); +// count = lineIndex - st.getLineAtOffset(offset); +// break; +// } +// } +// e.start = start; +// e.end = end; +// e.count = count; +// e.result = st.content.getTextRange(start, end - start); +// } +// @Override +// public void getVisibleRanges(AccessibleTextEvent e) { +// e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin); +// if (e.ranges.length > 0) { +// e.start = e.ranges[0]; +// e.end = e.ranges[e.ranges.length - 1]; +// } +// } +// @Override +// public void scrollText(AccessibleTextEvent e) { +// StyledText st = StyledText.this; +// int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel(); +// switch (e.type) { +// case ACC.SCROLL_TYPE_ANYWHERE: +// case ACC.SCROLL_TYPE_TOP_LEFT: +// case ACC.SCROLL_TYPE_LEFT_EDGE: +// case ACC.SCROLL_TYPE_TOP_EDGE: { +// Rectangle rect = st.getBoundsAtOffset(e.start); +// if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) { +// horizontalPixel = horizontalPixel + rect.x - st.leftMargin; +// } +// if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) { +// topPixel = topPixel + rect.y - st.topMargin; +// } +// break; +// } +// case ACC.SCROLL_TYPE_BOTTOM_RIGHT: +// case ACC.SCROLL_TYPE_BOTTOM_EDGE: +// case ACC.SCROLL_TYPE_RIGHT_EDGE: { +// Rectangle rect = st.getBoundsAtOffset(e.end - 1); +// if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) { +// horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin; +// } +// if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) { +// topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin; +// } +// break; +// } +// case ACC.SCROLL_TYPE_POINT: { +// Point point = new Point(e.x, e.y); +// Display display = st.getDisplay(); +// point = display.map(null, st, point); +// Rectangle rect = st.getBoundsAtOffset(e.start); +// topPixel = topPixel - point.y + rect.y; +// horizontalPixel = horizontalPixel - point.x + rect.x; +// break; +// } +// } +// st.setTopPixel(topPixel); +// st.setHorizontalPixel(horizontalPixel); +// e.result = ACC.OK; +// } +// }; +// acc.addAccessibleTextListener(accTextExtendedAdapter); +// +// accEditableTextListener = new AccessibleEditableTextListener() { +// @Override +// public void setTextAttributes(AccessibleTextAttributeEvent e) { +// // This method must be implemented by the application +// e.result = ACC.OK; +// } +// @Override +// public void replaceText(AccessibleEditableTextEvent e) { +// StyledText st = StyledText.this; +// st.replaceTextRange(e.start, e.end - e.start, e.string); +// e.result = ACC.OK; +// } +// @Override +// public void pasteText(AccessibleEditableTextEvent e) { +// StyledText st = StyledText.this; +// st.setSelection(e.start); +// st.paste(); +// e.result = ACC.OK; +// } +// @Override +// public void cutText(AccessibleEditableTextEvent e) { +// StyledText st = StyledText.this; +// st.setSelection(e.start, e.end); +// st.cut(); +// e.result = ACC.OK; +// } +// @Override +// public void copyText(AccessibleEditableTextEvent e) { +// StyledText st = StyledText.this; +// st.setSelection(e.start, e.end); +// st.copy(); +// e.result = ACC.OK; +// } +// }; +// acc.addAccessibleEditableTextListener(accEditableTextListener); +// +// accAttributeAdapter = new AccessibleAttributeAdapter() { +// @Override +// public void getAttributes(AccessibleAttributeEvent e) { +// StyledText st = StyledText.this; +// e.leftMargin = st.getLeftMargin(); +// e.topMargin = st.getTopMargin(); +// e.rightMargin = st.getRightMargin(); +// e.bottomMargin = st.getBottomMargin(); +// e.tabStops = st.getTabStops(); +// e.justify = st.getJustify(); +// e.alignment = st.getAlignment(); +// e.indent = st.getIndent(); +// } +// @Override +// public void getTextAttributes(AccessibleTextAttributeEvent e) { +// StyledText st = StyledText.this; +// int contentLength = st.getCharCount(); +// if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) { +// e.start = 0; +// e.end = contentLength; +// e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background); +// return; +// } +// int offset = Math.max(0, Math.min(e.offset, contentLength - 1)); +// int lineIndex = st.getLineAtOffset(offset); +// int lineOffset = st.getOffsetAtLine(lineIndex); +// int lineCount = st.getLineCount(); +// offset = offset - lineOffset; +// +// TextLayout layout = st.renderer.getTextLayout(lineIndex); +// int lineLength = layout.getText().length(); +// if (lineLength > 0) { +// e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1))); +// } +// +// // If no override info available, use defaults. Don't supply default colors, though. +// if (e.textStyle == null) { +// e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background); +// } else { +// if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) { +// TextStyle textStyle = new TextStyle(e.textStyle); +// if (textStyle.foreground == null) textStyle.foreground = st.foreground; +// if (textStyle.background == null) textStyle.background = st.background; +// if (textStyle.font == null) textStyle.font = st.getFont(); +// e.textStyle = textStyle; +// } +// } +// +// //offset at line delimiter case +// if (offset >= lineLength) { +// e.start = lineOffset + lineLength; +// if (lineIndex + 1 < lineCount) { +// e.end = st.getOffsetAtLine(lineIndex + 1); +// } else { +// e.end = contentLength; +// } +// return; +// } +// +// int[] ranges = layout.getRanges(); +// st.renderer.disposeTextLayout(layout); +// int index = 0; +// int end = 0; +// while (index < ranges.length) { +// int styleStart = ranges[index++]; +// int styleEnd = ranges[index++]; +// if (styleStart <= offset && offset <= styleEnd) { +// e.start = lineOffset + styleStart; +// e.end = lineOffset + styleEnd + 1; +// return; +// } +// if (styleStart > offset) { +// e.start = lineOffset + end; +// e.end = lineOffset + styleStart; +// return; +// } +// end = styleEnd + 1; +// } +// if (index == ranges.length) { +// e.start = lineOffset + end; +// if (lineIndex + 1 < lineCount) { +// e.end = st.getOffsetAtLine(lineIndex + 1); +// } else { +// e.end = contentLength; +// } +// } +// } +// }; +// acc.addAccessibleAttributeListener(accAttributeAdapter); +// +// accControlAdapter = new AccessibleControlAdapter() { +// @Override +// public void getRole(AccessibleControlEvent e) { +// e.detail = ACC.ROLE_TEXT; +// } +// @Override +// public void getState(AccessibleControlEvent e) { +// int state = 0; +// if (isEnabled()) state |= ACC.STATE_FOCUSABLE; +// if (isFocusControl()) state |= ACC.STATE_FOCUSED; +// if (!isVisible()) state |= ACC.STATE_INVISIBLE; +// if (!getEditable()) state |= ACC.STATE_READONLY; +// if (isSingleLine()) state |= ACC.STATE_SINGLELINE; +// else state |= ACC.STATE_MULTILINE; +// e.detail = state; +// } +// @Override +// public void getValue(AccessibleControlEvent e) { +// e.result = StyledText.this.getText(); +// } +// }; +// acc.addAccessibleControlListener(accControlAdapter); +// +// addListener(SWT.FocusIn, event -> acc.setFocus(ACC.CHILDID_SELF)); +// +// addListener(SWT.Dispose, event -> { +// // Issue 448: A 3rd party program that uses Accessible may +// // cache obtained connection and query it even after StyledText +// // is disposed. Disconnect all listeners to avoid querying a +// // disposed control. +// acc.removeAccessibleControlListener(accControlAdapter); +// acc.removeAccessibleAttributeListener(accAttributeAdapter); +// acc.removeAccessibleEditableTextListener(accEditableTextListener); +// acc.removeAccessibleTextListener(accTextExtendedAdapter); +// acc.removeAccessibleListener(accAdapter); +// }); +//} +// +///* +// * Return the Label immediately preceding the receiver in the z-order, +// * or null if none. +// */ +//String getAssociatedLabel () { +// Control[] siblings = getParent ().getChildren (); +// for (int i = 0; i < siblings.length; i++) { +// if (siblings [i] == StyledText.this) { +// if (i > 0) { +// Control sibling = siblings [i-1]; +// if (sibling instanceof Label) return ((Label) sibling).getText(); +// if (sibling instanceof CLabel) return ((CLabel) sibling).getText(); +// } +// break; +// } +// } +// return null; +//} +//String stripMnemonic (String string) { +// int index = 0; +// int length = string.length (); +// do { +// while ((index < length) && (string.charAt (index) != '&')) index++; +// if (++index >= length) return string; +// if (string.charAt (index) != '&') { +// return string.substring(0, index-1) + string.substring(index, length); +// } +// index++; +// } while (index < length); +// return string; +//} +///* +// * Return the lowercase of the first non-'&' character following +// * an '&' character in the given string. If there are no '&' +// * characters in the given string, return '\0'. +// */ +//char _findMnemonic (String string) { +// if (string == null) return '\0'; +// int index = 0; +// int length = string.length (); +// do { +// while (index < length && string.charAt (index) != '&') index++; +// if (++index >= length) return '\0'; +// if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index)); +// index++; +// } while (index < length); +// return '\0'; +//} +///** +// * Executes the action. +// * +// * @param action one of the actions defined in ST.java +// */ +//public void invokeAction(int action) { +// checkWidget(); +// if (blockSelection && invokeBlockAction(action)) return; +// updateCaretDirection = true; +// switch (action) { +// // Navigation +// case ST.LINE_UP: +// doLineUp(false); +// clearSelection(true); +// break; +// case ST.LINE_DOWN: +// doLineDown(false); +// clearSelection(true); +// break; +// case ST.LINE_START: +// doLineStart(); +// clearSelection(true); +// break; +// case ST.LINE_END: +// doLineEnd(); +// clearSelection(true); +// break; +// case ST.COLUMN_PREVIOUS: +// doCursorPrevious(); +// clearSelection(true); +// break; +// case ST.COLUMN_NEXT: +// doCursorNext(); +// clearSelection(true); +// break; +// case ST.PAGE_UP: +// doPageUp(false, -1); +// clearSelection(true); +// break; +// case ST.PAGE_DOWN: +// doPageDown(false, -1); +// clearSelection(true); +// break; +// case ST.WORD_PREVIOUS: +// doWordPrevious(); +// clearSelection(true); +// break; +// case ST.WORD_NEXT: +// doWordNext(); +// clearSelection(true); +// break; +// case ST.TEXT_START: +// doContentStart(); +// clearSelection(true); +// break; +// case ST.TEXT_END: +// doContentEnd(); +// clearSelection(true); +// break; +// case ST.WINDOW_START: +// doPageStart(); +// clearSelection(true); +// break; +// case ST.WINDOW_END: +// doPageEnd(); +// clearSelection(true); +// break; +// // Selection +// case ST.SELECT_LINE_UP: +// doSelectionLineUp(); +// break; +// case ST.SELECT_ALL: +// selectAll(); +// break; +// case ST.SELECT_LINE_DOWN: +// doSelectionLineDown(); +// break; +// case ST.SELECT_LINE_START: +// doLineStart(); +// doSelection(ST.COLUMN_PREVIOUS); +// break; +// case ST.SELECT_LINE_END: +// doLineEnd(); +// doSelection(ST.COLUMN_NEXT); +// break; +// case ST.SELECT_COLUMN_PREVIOUS: +// doSelectionCursorPrevious(); +// doSelection(ST.COLUMN_PREVIOUS); +// break; +// case ST.SELECT_COLUMN_NEXT: +// doSelectionCursorNext(); +// doSelection(ST.COLUMN_NEXT); +// break; +// case ST.SELECT_PAGE_UP: +// doSelectionPageUp(-1); +// break; +// case ST.SELECT_PAGE_DOWN: +// doSelectionPageDown(-1); +// break; +// case ST.SELECT_WORD_PREVIOUS: +// doSelectionWordPrevious(); +// doSelection(ST.COLUMN_PREVIOUS); +// break; +// case ST.SELECT_WORD_NEXT: +// doSelectionWordNext(); +// doSelection(ST.COLUMN_NEXT); +// break; +// case ST.SELECT_TEXT_START: +// doContentStart(); +// doSelection(ST.COLUMN_PREVIOUS); +// break; +// case ST.SELECT_TEXT_END: +// doContentEnd(); +// doSelection(ST.COLUMN_NEXT); +// break; +// case ST.SELECT_WINDOW_START: +// doPageStart(); +// doSelection(ST.COLUMN_PREVIOUS); +// break; +// case ST.SELECT_WINDOW_END: +// doPageEnd(); +// doSelection(ST.COLUMN_NEXT); +// break; +// // Modification +// case ST.CUT: +// cut(); +// break; +// case ST.COPY: +// copy(); +// break; +// case ST.PASTE: +// paste(); +// break; +// case ST.DELETE_PREVIOUS: +// doBackspace(); +// break; +// case ST.DELETE_NEXT: +// doDelete(); +// break; +// case ST.DELETE_WORD_PREVIOUS: +// doDeleteWordPrevious(); +// break; +// case ST.DELETE_WORD_NEXT: +// doDeleteWordNext(); +// break; +// // Miscellaneous +// case ST.TOGGLE_OVERWRITE: +// overwrite = !overwrite; // toggle insert/overwrite mode +// break; +// case ST.TOGGLE_BLOCKSELECTION: +// setBlockSelection(!blockSelection); +// break; +// } +//} +///** +//* Returns true if an action should not be performed when block +//* selection in active +//*/ +//boolean invokeBlockAction(int action) { +// switch (action) { +// // Navigation +// case ST.LINE_UP: +// case ST.LINE_DOWN: +// case ST.LINE_START: +// case ST.LINE_END: +// case ST.COLUMN_PREVIOUS: +// case ST.COLUMN_NEXT: +// case ST.PAGE_UP: +// case ST.PAGE_DOWN: +// case ST.WORD_PREVIOUS: +// case ST.WORD_NEXT: +// case ST.TEXT_START: +// case ST.TEXT_END: +// case ST.WINDOW_START: +// case ST.WINDOW_END: +// clearBlockSelection(false, false); +// return false; +// // Selection +// case ST.SELECT_LINE_UP: +// doBlockLineVertical(true); +// return true; +// case ST.SELECT_LINE_DOWN: +// doBlockLineVertical(false); +// return true; +// case ST.SELECT_LINE_START: +// doBlockLineHorizontal(false); +// return true; +// case ST.SELECT_LINE_END: +// doBlockLineHorizontal(true); +// return false; +// case ST.SELECT_COLUMN_PREVIOUS: +// doBlockColumn(false); +// return true; +// case ST.SELECT_COLUMN_NEXT: +// doBlockColumn(true); +// return true; +// case ST.SELECT_WORD_PREVIOUS: +// doBlockWord(false); +// return true; +// case ST.SELECT_WORD_NEXT: +// doBlockWord(true); +// return true; +// case ST.SELECT_ALL: +// return false; +// case ST.SELECT_TEXT_START: +// doBlockContentStartEnd(false); +// break; +// case ST.SELECT_TEXT_END: +// doBlockContentStartEnd(true); +// break; +// case ST.SELECT_PAGE_UP: +// case ST.SELECT_PAGE_DOWN: +// case ST.SELECT_WINDOW_START: +// case ST.SELECT_WINDOW_END: +// //blocked actions +// return true; +// // Modification +// case ST.CUT: +// case ST.COPY: +// case ST.PASTE: +// return false; +// case ST.DELETE_PREVIOUS: +// case ST.DELETE_NEXT: +// if (blockXLocation != -1) { +// insertBlockSelectionText((char)0, action); +// return true; +// } +// return false; +// case ST.DELETE_WORD_PREVIOUS: +// case ST.DELETE_WORD_NEXT: +// //blocked actions +// return blockXLocation != -1; +// } +// return false; +//} +//boolean isBidiCaret() { +// return BidiUtil.isBidiPlatform(); +//} +//boolean isFixedLineHeight() { +// return !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent; +//} +///** +// * Returns whether the given offset is inside a multi byte line delimiter. +// * Example: +// * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true +// * +// * @return true if the given offset is inside a multi byte line delimiter. +// * false if the given offset is before or after a line delimiter. +// */ +//boolean isLineDelimiter(int offset) { +// int line = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(line); +// int offsetInLine = offset - lineOffset; +// // offsetInLine will be greater than line length if the line +// // delimiter is longer than one character and the offset is set +// // in between parts of the line delimiter. +// return offsetInLine > content.getLine(line).length(); +//} +///** +// * Returns whether the widget is mirrored (right oriented/right to left +// * writing order). +// * +// * @return isMirrored true=the widget is right oriented, false=the widget +// * is left oriented +// */ +//boolean isMirrored() { +// return (getStyle() & SWT.MIRRORED) != 0; +//} +///** +// * Returns true if any text in the widget is selected, +// * and false otherwise. +// * +// * @return the text selection state +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.103 +// */ +//public boolean isTextSelected() { +// checkWidget(); +// if (blockSelection && blockXLocation != -1) { +// Rectangle rect = getBlockSelectionPosition(); +// return !rect.isEmpty(); +// } +// return Arrays.stream(selection).anyMatch(range -> range.x != range.y); +//} +///** +// * Returns whether the widget can have only one line. +// * +// * @return true if widget can have only one line, false if widget can have +// * multiple lines +// */ +//boolean isSingleLine() { +// return (getStyle() & SWT.SINGLE) != 0; +//} +// +///** +// * Sends the specified verify event, replace/insert text as defined by +// * the event and send a modify event. +// * +// * @param event the text change event. +// *
      +// *
    • event.start - the replace start offset
    • +// *
    • event.end - the replace end offset
    • +// *
    • event.text - the new text
    • +// *
    +// * @param updateCaret whether or not he caret should be set behind +// * the new text +// */ +//void modifyContent(Event event, boolean updateCaret) { +// event.doit = true; +// notifyListeners(SWT.Verify, event); +// if (event.doit) { +// StyledTextEvent styledTextEvent = null; +// int replacedLength = event.end - event.start; +// if (isListening(ST.ExtendedModify)) { +// styledTextEvent = new StyledTextEvent(content); +// styledTextEvent.start = event.start; +// styledTextEvent.end = event.start + event.text.length(); +// styledTextEvent.text = content.getTextRange(event.start, replacedLength); +// } +// if (updateCaret) { +// //Fix advancing flag for delete/backspace key on direction boundary +// if (event.text.length() == 0) { +// int lineIndex = content.getLineAtOffset(event.start); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// TextLayout layout = renderer.getTextLayout(lineIndex); +// int levelStart = layout.getLevel(event.start - lineOffset); +// int lineIndexEnd = content.getLineAtOffset(event.end); +// if (lineIndex != lineIndexEnd) { +// renderer.disposeTextLayout(layout); +// lineOffset = content.getOffsetAtLine(lineIndexEnd); +// layout = renderer.getTextLayout(lineIndexEnd); +// } +// int levelEnd = layout.getLevel(event.end - lineOffset); +// renderer.disposeTextLayout(layout); +// if (levelStart != levelEnd) { +// caretAlignment = PREVIOUS_OFFSET_TRAILING; +// } else { +// caretAlignment = OFFSET_LEADING; +// } +// } +// } +// content.replaceTextRange(event.start, replacedLength, event.text); +// // set the caret position prior to sending the modify event. +// // fixes 1GBB8NJ +// if (updateCaret && !(blockSelection && blockXLocation != -1)) { +// // always update the caret location. fixes 1G8FODP +// setSelection(Arrays.stream(selection).map(sel -> { +// if (sel.y < event.start || sel.x > event.end) { +// return sel; +// } else { // current range edited +// return new Point(event.start + event.text.length(), event.start + event.text.length()); +// } +// }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)).toArray(), true, false); +// showCaret(); +// } +// notifyListeners(SWT.Modify, event); +// if (isListening(ST.ExtendedModify)) { +// notifyListeners(ST.ExtendedModify, styledTextEvent); +// } +// } +//} +//void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) { +// if (isListening(ST.PaintObject)) { +// StyledTextEvent event = new StyledTextEvent (content) ; +// event.gc = gc; +// event.x = x; +// event.y = y; +// event.ascent = ascent; +// event.descent = descent; +// event.style = style; +// event.bullet = bullet; +// event.bulletIndex = bulletIndex; +// notifyListeners(ST.PaintObject, event); +// } +//} +///** +// * Replaces the selection with the text on the DND.CLIPBOARD +// * clipboard or, if there is no selection, inserts the text at the current +// * caret offset. If the widget has the SWT.SINGLE style and the +// * clipboard text contains more than one line, only the first line without +// * line delimiters is inserted in the widget. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void paste(){ +// checkWidget(); +// String text = (String) getClipboardContent(DND.CLIPBOARD); +// if (text != null && text.length() > 0) { +// if (blockSelection) { +// boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch; +// int offset = insertBlockSelectionText(text, fillWithSpaces); +// setCaretOffsets(new int[] {offset}, SWT.DEFAULT); +// clearBlockSelection(true, true); +// setCaretLocations(); +// return; +// } else if (getSelectionRanges().length / 2 > 1) { // multi selection +// insertMultiSelectionText(text); +// setCaretLocations(); +// return; +// } +// Event event = new Event(); +// event.start = selection[0].x; +// event.end = selection[0].y; +// String delimitedText = getModelDelimitedText(text); +// if (textLimit > 0) { +// int uneditedTextLength = getCharCount() - (selection[0].y - selection[0].x); +// if ((uneditedTextLength + delimitedText.length()) > textLimit) { +// int endIndex = textLimit - uneditedTextLength; +// delimitedText = delimitedText.substring(0, Math.max(endIndex, 0)); +// } +// } +// event.text = delimitedText; +// sendKeyEvent(event); +// } +//} +// +//private void insertMultiSelectionText(String text) { +// String[] blocks = text.split(PlatformLineDelimiter); +// int[] ranges = getSelectionRanges(); +// for (int i = ranges.length / 2 - 1; i >= 0; i --) { +// int offset = ranges[2 * i]; +// int length = ranges[2 * i + 1]; +// String toPaste = blocks.length > i ? blocks[i] : blocks[blocks.length - 1]; +// Event event = new Event(); +// event.start = offset; +// event.end = offset + length; +// event.text = toPaste; +// sendKeyEvent(event); +// } +//} +// +//private void pasteOnMiddleClick(Event event) { +// String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD); +// if (text != null && text.length() > 0) { +// // position cursor +// doMouseLocationChange(event.x, event.y, false); +// // insert text +// Event e = new Event(); +// e.start = selection[0].x; +// e.end = selection[0].y; +// e.text = getModelDelimitedText(text); +// sendKeyEvent(e); +// } +//} +///** +// * Prints the widget's text to the default printer. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void print() { +// checkWidget(); +// Printer printer = new Printer(); +// StyledTextPrintOptions options = new StyledTextPrintOptions(); +// options.printTextForeground = true; +// options.printTextBackground = true; +// options.printTextFontStyle = true; +// options.printLineBackground = true; +// new Printing(this, printer, options).run(); +// printer.dispose(); +//} +///** +// * Returns a runnable that will print the widget's text +// * to the specified printer. +// *

    +// * The runnable may be run in a non-UI thread. +// *

    +// * +// * @param printer the printer to print to +// * +// * @return a Runnable for printing the receiver's text +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when printer is null
    • +// *
    +// */ +//public Runnable print(Printer printer) { +// checkWidget(); +// if (printer == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// StyledTextPrintOptions options = new StyledTextPrintOptions(); +// options.printTextForeground = true; +// options.printTextBackground = true; +// options.printTextFontStyle = true; +// options.printLineBackground = true; +// return print(printer, options); +//} +///** +// * Returns a runnable that will print the widget's text +// * to the specified printer. +// *

    +// * The runnable may be run in a non-UI thread. +// *

    +// * +// * @param printer the printer to print to +// * @param options print options to use during printing +// * +// * @return a Runnable for printing the receiver's text +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when printer or options is null
    • +// *
    +// * @since 2.1 +// */ +//public Runnable print(Printer printer, StyledTextPrintOptions options) { +// checkWidget(); +// if (printer == null || options == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// return new Printing(this, printer, options); +//} +///** +// * Causes the entire bounds of the receiver to be marked +// * as needing to be redrawn. The next time a paint request +// * is processed, the control will be completely painted. +// *

    +// * Recalculates the content width for all lines in the bounds. +// * When a LineStyleListener is used a redraw call +// * is the only notification to the widget that styles have changed +// * and that the content width may have changed. +// *

    +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see Control#update() +// */ +//@Override +//public void redraw() { +// super.redraw(); +// int itemCount = getPartialBottomIndex() - topIndex + 1; +// renderer.reset(topIndex, itemCount); +// renderer.calculate(topIndex, itemCount); +// setScrollBars(false); +// doMouseLinkCursor(); +//} +///** +// * Causes the rectangular area of the receiver specified by +// * the arguments to be marked as needing to be redrawn. +// * The next time a paint request is processed, that area of +// * the receiver will be painted. If the all flag +// * is true, any children of the receiver which +// * intersect with the specified area will also paint their +// * intersecting areas. If the all flag is +// * false, the children will not be painted. +// *

    +// * Marks the content width of all lines in the specified rectangle +// * as unknown. Recalculates the content width of all visible lines. +// * When a LineStyleListener is used a redraw call +// * is the only notification to the widget that styles have changed +// * and that the content width may have changed. +// *

    +// * +// * @param x the x coordinate of the area to draw +// * @param y the y coordinate of the area to draw +// * @param width the width of the area to draw +// * @param height the height of the area to draw +// * @param all true if children should redraw, and false otherwise +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see Control#update() +// */ +//@Override +//public void redraw(int x, int y, int width, int height, boolean all) { +// super.redraw(x, y, width, height, all); +// if (height > 0) { +// int firstLine = getLineIndex(y); +// int lastLine = getLineIndex(y + height); +// resetCache(firstLine, lastLine - firstLine + 1); +// doMouseLinkCursor(); +// } +//} +//void redrawLines(int startLine, int lineCount, boolean bottomChanged) { +// // do nothing if redraw range is completely invisible +// int endLine = startLine + lineCount - 1; +// int partialBottomIndex = getPartialBottomIndex(); +// int partialTopIndex = getPartialTopIndex(); +// if (startLine > partialBottomIndex || endLine < partialTopIndex) { +// return; +// } +// // only redraw visible lines +// if (startLine < partialTopIndex) { +// startLine = partialTopIndex; +// } +// if (endLine > partialBottomIndex) { +// endLine = partialBottomIndex; +// } +// int redrawTop = getLinePixel(startLine); +// int redrawBottom = getLinePixel(endLine + 1); +// if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin; +// int redrawWidth = clientAreaWidth - leftMargin - rightMargin; +// super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); +//} +//void redrawLinesBullet (int[] redrawLines) { +// if (redrawLines == null) return; +// int topIndex = getPartialTopIndex(); +// int bottomIndex = getPartialBottomIndex(); +// for (int redrawLine : redrawLines) { +// int lineIndex = redrawLine; +// if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue; +// int width = -1; +// Bullet bullet = renderer.getLineBullet(lineIndex, null); +// if (bullet != null) { +// StyleRange style = bullet.style; +// GlyphMetrics metrics = style.metrics; +// width = metrics.width; +// } +// if (width == -1) width = getClientArea().width; +// int height = renderer.getLineHeight(lineIndex); +// int y = getLinePixel(lineIndex); +// super.redraw(0, y, width, height, false); +// } +//} +//void redrawMargins(int oldHeight, int oldWidth) { +// /* Redraw the old or new right/bottom margin if needed */ +// if (oldWidth != clientAreaWidth) { +// if (rightMargin > 0) { +// int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; +// super.redraw(x, 0, rightMargin, oldHeight, false); +// } +// } +// if (oldHeight != clientAreaHeight) { +// if (bottomMargin > 0) { +// int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; +// super.redraw(0, y, oldWidth, bottomMargin, false); +// } +// } +//} +///** +// * Redraws the specified text range. +// * +// * @param start offset of the first character to redraw +// * @param length number of characters to redraw +// * @param clearBackground true if the background should be cleared as +// * part of the redraw operation. If true, the entire redraw range will +// * be cleared before anything is redrawn. If the redraw range includes +// * the last character of a line (i.e., the entire line is redrawn) the +// * line is cleared all the way to the right border of the widget. +// * The redraw operation will be faster and smoother if clearBackground +// * is set to false. Whether or not the flag can be set to false depends +// * on the type of change that has taken place. If font styles or +// * background colors for the redraw range have changed, clearBackground +// * should be set to true. If only foreground colors have changed for +// * the redraw range, clearBackground can be set to false. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • +// *
    +// */ +//public void redrawRange(int start, int length, boolean clearBackground) { +// checkWidget(); +// int end = start + length; +// int contentLength = content.getCharCount(); +// if (start > end || start < 0 || end > contentLength) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// int firstLine = content.getLineAtOffset(start); +// int lastLine = content.getLineAtOffset(end); +// resetCache(firstLine, lastLine - firstLine + 1); +// internalRedrawRange(start, length); +// doMouseLinkCursor(); +//} +///** +// * Removes the specified bidirectional segment listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @since 2.0 +// */ +//public void removeBidiSegmentListener(BidiSegmentListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.LineGetSegments, listener); +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Removes the specified caret listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @since 3.5 +// */ +//public void removeCaretListener(CaretListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.CaretMoved, listener); +//} +///** +// * Removes the specified extended modify listener. +// * +// * @param extendedModifyListener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { +// checkWidget(); +// if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.ExtendedModify, extendedModifyListener); +//} +///** +// * Removes the specified line background listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeLineBackgroundListener(LineBackgroundListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.LineGetBackground, listener); +//} +///** +// * Removes the specified line style listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeLineStyleListener(LineStyleListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.LineGetStyle, listener); +// setCaretLocations(); +//} +///** +// * Removes the specified modify listener. +// * +// * @param modifyListener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeModifyListener(ModifyListener modifyListener) { +// checkWidget(); +// if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(SWT.Modify, modifyListener); +//} +///** +// * Removes the specified listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * @since 3.2 +// */ +//public void removePaintObjectListener(PaintObjectListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.PaintObject, listener); +//} +///** +// * Removes the listener from the collection of listeners who will +// * be notified when the user changes the receiver's selection. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see SelectionListener +// * @see #addSelectionListener +// */ +//public void removeSelectionListener(SelectionListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(SWT.Selection, listener); +//} +///** +// * Removes the specified verify listener. +// * +// * @param verifyListener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeVerifyListener(VerifyListener verifyListener) { +// checkWidget(); +// if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(SWT.Verify, verifyListener); +//} +///** +// * Removes the specified key verify listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void removeVerifyKeyListener(VerifyKeyListener listener) { +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.VerifyKey, listener); +//} +///** +// * Removes the specified word movement listener. +// * +// * @param listener the listener which should no longer be notified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// * +// * @see MovementEvent +// * @see MovementListener +// * @see #addWordMovementListener +// * +// * @since 3.3 +// */ +// +//public void removeWordMovementListener(MovementListener listener) { +// checkWidget(); +// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// removeTypedListener(ST.WordNext, listener); +// removeTypedListener(ST.WordPrevious, listener); +//} +///** +// * Replaces the styles in the given range with new styles. This method +// * effectively deletes the styles in the given range and then adds the +// * the new styles. +// *

    +// * Note: Because a StyleRange includes the start and length, the +// * same instance cannot occur multiple times in the array of styles. +// * If the same style attributes, such as font and color, occur in +// * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[]) +// * can be used to share styles and reduce memory usage. +// *

    +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param start offset of first character where styles will be deleted +// * @param length length of the range to delete styles in +// * @param ranges StyleRange objects containing the new style information. +// * The ranges should not overlap and should be within the specified start +// * and length. The style rendering is undefined if the ranges do overlap +// * or are ill-defined. Must not be null. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • +// *
    • ERROR_NULL_ARGUMENT when ranges is null
    • +// *
    +// * +// * @since 2.0 +// * +// * @see #setStyleRanges(int, int, int[], StyleRange[]) +// */ +//public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// setStyleRanges(start, length, null, ranges, false); +//} +///** +// * Replaces the given text range with new text. +// * If the widget has the SWT.SINGLE style and "text" contains more than +// * one line, only the first line is rendered but the text is stored +// * unchanged. A subsequent call to getText will return the same text +// * that was set. Note that only a single line of text should be set when +// * the SWT.SINGLE style is used. +// *

    +// * NOTE: During the replace operation the current selection is +// * changed as follows: +// *

    +// *
      +// *
    • selection before replaced text: selection unchanged +// *
    • selection after replaced text: adjust the selection so that same text +// * remains selected +// *
    • selection intersects replaced text: selection is cleared and caret +// * is placed after inserted text +// *
    +// * +// * @param start offset of first character to replace +// * @param length number of characters to replace. Use 0 to insert text +// * @param text new text. May be empty to delete text. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • +// *
    • ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. +// * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
    • +// *
    • ERROR_NULL_ARGUMENT when string is null
    • +// *
    +// */ +//public void replaceTextRange(int start, int length, String text) { +// checkWidget(); +// if (text == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// int contentLength = getCharCount(); +// int end = start + length; +// if (start > end || start < 0 || end > contentLength) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// Event event = new Event(); +// event.start = start; +// event.end = end; +// event.text = text; +// modifyContent(event, false); +//} +///** +// * Resets the caret position, selection and scroll offsets. Recalculate +// * the content width and scroll bars. Redraw the widget. +// */ +//void reset() { +// ScrollBar verticalBar = getVerticalBar(); +// ScrollBar horizontalBar = getHorizontalBar(); +// setCaretOffsets(new int[] {0}, SWT.DEFAULT); +// topIndex = 0; +// topIndexY = 0; +// verticalScrollOffset = 0; +// horizontalScrollOffset = 0; +// resetSelection(); +// renderer.setContent(content); +// if (verticalBar != null) { +// verticalBar.setSelection(0); +// } +// if (horizontalBar != null) { +// horizontalBar.setSelection(0); +// } +// resetCache(0, 0); +// setCaretLocations(); +// super.redraw(); +//} +//void resetBidiData() { +// caretDirection = SWT.NULL; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// keyActionMap.clear(); +// createKeyBindings(); +// super.redraw(); +//} +//void resetCache(SortedSet lines) { +// if (lines == null || lines.isEmpty()) return; +// int maxLineIndex = renderer.maxWidthLineIndex; +// renderer.reset(lines); +// renderer.calculateClientArea(); +// if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) { +// renderer.calculate(maxLineIndex, 1); +// } +// setScrollBars(true); +// if (!isFixedLineHeight()) { +// if (topIndex > lines.iterator().next()) { +// verticalScrollOffset = -1; +// } +// renderer.calculateIdle(); +// } +//} +//void resetCache(int firstLine, int count) { +// int maxLineIndex = renderer.maxWidthLineIndex; +// renderer.reset(firstLine, count); +// renderer.calculateClientArea(); +// if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) { +// renderer.calculate(maxLineIndex, 1); +// } +// setScrollBars(true); +// if (!isFixedLineHeight()) { +// if (topIndex > firstLine) { +// verticalScrollOffset = -1; +// } +// renderer.calculateIdle(); +// } +//} +///** +// * Resets the selection. +// */ +//void resetSelection() { +// selection = Arrays.stream(caretOffsets).mapToObj(offset -> new Point(offset, offset)).toArray(Point[]::new); +// selectionAnchors = Arrays.copyOf(caretOffsets, caretOffsets.length); +// sendAccessibleTextCaretMoved(); +//} +// +//@Override +//public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) { +// super.scroll(destX, destY, x, y, width, height, false); +// if (all) { +// int deltaX = destX - x, deltaY = destY - y; +// for (Control child : getChildren()) { +// Rectangle rect = child.getBounds(); +// child.setLocation(rect.x + deltaX, rect.y + deltaY); +// } +// } +//} +// +///** +// * Scrolls the widget horizontally. +// * +// * @param pixels number of SWT logical points to scroll, > 0 = scroll left, +// * < 0 scroll right +// * @param adjustScrollBar +// * true= the scroll thumb will be moved to reflect the new scroll offset. +// * false = the scroll thumb will not be moved +// * @return +// * true=the widget was scrolled +// * false=the widget was not scrolled, the given offset is not valid. +// */ +//boolean scrollHorizontal(int pixels, boolean adjustScrollBar) { +// if (pixels == 0) return false; +// if (wordWrap) return false; +// ScrollBar horizontalBar = getHorizontalBar(); +// if (horizontalBar != null && adjustScrollBar) { +// horizontalBar.setSelection(horizontalScrollOffset + pixels); +// } +// int scrollHeight = clientAreaHeight - topMargin - bottomMargin; +// if (pixels > 0) { +// int sourceX = leftMargin + pixels; +// int scrollWidth = clientAreaWidth - sourceX - rightMargin; +// if (scrollWidth > 0) { +// scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true); +// } +// if (sourceX > scrollWidth) { +// super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true); +// } +// } else { +// int destinationX = leftMargin - pixels; +// int scrollWidth = clientAreaWidth - destinationX - rightMargin; +// if (scrollWidth > 0) { +// scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true); +// } +// if (destinationX > scrollWidth) { +// super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true); +// } +// } +// horizontalScrollOffset += pixels; +// setCaretLocations(); +// return true; +//} +///** +// * Scrolls the widget vertically. +// * +// * @param pixel the new vertical scroll offset +// * @param adjustScrollBar +// * true= the scroll thumb will be moved to reflect the new scroll offset. +// * false = the scroll thumb will not be moved +// * @return +// * true=the widget was scrolled +// * false=the widget was not scrolled +// */ +//boolean scrollVertical(int pixels, boolean adjustScrollBar) { +// if (pixels == 0) { +// return false; +// } +// if (verticalScrollOffset != -1) { +// ScrollBar verticalBar = getVerticalBar(); +// if (verticalBar != null && adjustScrollBar) { +// verticalBar.setSelection(verticalScrollOffset + pixels); +// } +// int deltaY = 0; +// if (pixels > 0) { +// int sourceY = topMargin + pixels; +// int scrollHeight = clientAreaHeight - sourceY - bottomMargin; +// if (scrollHeight > 0) { +// deltaY = -pixels; +// } +// } else { +// int destinationY = topMargin - pixels; +// int scrollHeight = clientAreaHeight - destinationY - bottomMargin; +// if (scrollHeight > 0) { +// deltaY = -pixels; +// } +// } +// Control[] children = getChildren(); +// for (Control child : children) { +// Rectangle rect = child.getBounds(); +// child.setLocation(rect.x, rect.y + deltaY); +// } +// verticalScrollOffset += pixels; +// calculateTopIndex(pixels); +// super.redraw(); +// } else { +// calculateTopIndex(pixels); +// super.redraw(); +// } +// setCaretLocations(); +// return true; +//} +//void scrollText(int srcY, int destY) { +// if (srcY == destY) return; +// int deltaY = destY - srcY; +// int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight; +// if (deltaY > 0) { +// scrollHeight = clientAreaHeight - srcY - bottomMargin; +// } else { +// scrollHeight = clientAreaHeight - destY - bottomMargin; +// } +// scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true); +// if ((0 < srcY + scrollHeight) && (topMargin > srcY)) { +// super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false); +// } +// if ((0 < destY + scrollHeight) && (topMargin > destY)) { +// super.redraw(leftMargin, 0, scrollWidth, topMargin, false); +// } +// if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) { +// super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false); +// } +// if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) { +// super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); +// } +//} +//void sendAccessibleTextCaretMoved() { +// if (Arrays.stream(caretOffsets).noneMatch(caretOffset -> caretOffset == accCaretOffset)) { +// accCaretOffset = caretOffsets[0]; +// getAccessible().textCaretMoved(caretOffsets[0]); +// } +//} +//void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) { +// Accessible accessible = getAccessible(); +// if (replaceCharCount != 0) { +// accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount); +// } +// if (newCharCount != 0) { +// accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount); +// } +//} +///** +// * Selects all the text. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void selectAll() { +// checkWidget(); +// if (blockSelection) { +// renderer.calculate(0, content.getLineCount()); +// setScrollBars(false); +// int verticalScrollOffset = getVerticalScrollOffset(); +// int left = leftMargin - horizontalScrollOffset; +// int top = topMargin - verticalScrollOffset; +// int right = renderer.getWidth() - rightMargin - horizontalScrollOffset; +// int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset; +// setBlockSelectionLocation(left, top, right, bottom, false); +// return; +// } +// setSelection(0, Math.max(getCharCount(),0)); +//} +///** +// * Replaces/inserts text as defined by the event. +// * +// * @param event the text change event. +// *
      +// *
    • event.start - the replace start offset
    • +// *
    • event.end - the replace end offset
    • +// *
    • event.text - the new text
    • +// *
    +// */ +//void sendKeyEvent(Event event) { +// if (editable) { +// modifyContent(event, true); +// } +//} +///** +// * Returns a StyledTextEvent that can be used to request data such +// * as styles and background color for a line. +// *

    +// * The specified line may be a visual (wrapped) line if in word +// * wrap mode. The returned object will always be for a logical +// * (unwrapped) line. +// *

    +// * +// * @param lineOffset offset of the line. This may be the offset of +// * a visual line if the widget is in word wrap mode. +// * @param line line text. This may be the text of a visual line if +// * the widget is in word wrap mode. +// * @return StyledTextEvent that can be used to request line data +// * for the given line. +// */ +//StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { +// StyledTextEvent event = null; +// if (isListening(eventType)) { +// event = new StyledTextEvent(content); +// event.detail = lineOffset; +// event.text = line; +// event.alignment = alignment; +// event.indent = indent; +// event.wrapIndent = wrapIndent; +// event.justify = justify; +// notifyListeners(eventType, event); +// } +// return event; +//} +///** +// * Sends the specified selection event. +// */ +//void sendSelectionEvent() { +// getAccessible().textSelectionChanged(); +// Event event = new Event(); +// event.x = selection[0].x; +// event.y = selection[selection.length - 1].y; +// notifyListeners(SWT.Selection, event); +//} +//int sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) { +// int lineWidth = 0, start, end; +// StringBuilder buffer = new StringBuilder(); +// if (lineIndex < content.getLineCount()) { +// int[] trailing = new int[1]; +// start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true); +// if (start == -1) { +// int lineOffset = content.getOffsetAtLine(lineIndex); +// int lineLegth = content.getLine(lineIndex).length(); +// start = end = lineOffset + lineLegth; +// if (fillWithSpaces) { +// TextLayout layout = renderer.getTextLayout(lineIndex); +// lineWidth = layout.getBounds().width; +// renderer.disposeTextLayout(layout); +// } +// } else { +// start += trailing[0]; +// end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null); +// fillWithSpaces = false; +// } +// } else { +// start = end = content.getCharCount(); +// buffer.append(content.getLineDelimiter()); +// } +// if (start > end) { +// int temp = start; +// start = end; +// end = temp; +// } +// if (fillWithSpaces) { +// int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin; +// int spacesCount = spacesWidth / renderer.averageCharWidth; +// for (int i = 0; i < spacesCount; i++) { +// buffer.append(' '); +// } +// } +// buffer.append(text); +// Event event = new Event(); +// event.start = start; +// event.end = end; +// event.text = buffer.toString(); +// sendKeyEvent(event); +// return event.start + event.text.length(); +//} +//int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) { +// if (isListening(eventType)) { +// StyledTextEvent event = new StyledTextEvent(content); +// event.detail = lineOffset; +// event.text = lineText; +// event.count = movement; +// event.start = offset; +// event.end = newOffset; +// notifyListeners(eventType, event); +// offset = event.end; +// if (offset != newOffset) { +// int length = getCharCount(); +// if (offset < 0) { +// offset = 0; +// } else if (offset > length) { +// offset = length; +// } else { +// if (isLineDelimiter(offset)) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// } +// } +// return offset; +// } +// return newOffset; +//} +//void setAlignment() { +// if ((getStyle() & SWT.SINGLE) == 0) return; +// int alignment = renderer.getLineAlignment(0, this.alignment); +// int newAlignmentMargin = 0; +// if (alignment != SWT.LEFT) { +// renderer.calculate(0, 1); +// int width = renderer.getWidth() - alignmentMargin; +// newAlignmentMargin = clientAreaWidth - width; +// if (newAlignmentMargin < 0) newAlignmentMargin = 0; +// if (alignment == SWT.CENTER) newAlignmentMargin /= 2; +// } +// if (alignmentMargin != newAlignmentMargin) { +// leftMargin -= alignmentMargin; +// leftMargin += newAlignmentMargin; +// alignmentMargin = newAlignmentMargin; +// resetCache(0, 1); +// setCaretLocations(); +// super.redraw(); +// } +//} +///** +// * Sets the alignment of the widget. The argument should be one of SWT.LEFT, +// * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines. +// *

    +// * Note that if SWT.MULTI is set, then SWT.WRAP must also be set +// * in order to stabilize the right edge before setting alignment. +// *

    +// * +// * @param alignment the new alignment +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #setLineAlignment(int, int, int) +// * +// * @since 3.2 +// */ +//public void setAlignment(int alignment) { +// checkWidget(); +// alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER); +// if (alignment == 0 || this.alignment == alignment) return; +// this.alignment = alignment; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// setAlignment(); +// super.redraw(); +//} +///** +// * Set the Always Show Scrollbars flag. True if the scrollbars are +// * always shown even if they are not required (default value). False if the scrollbars are only +// * visible when some part of the content needs to be scrolled to be seen. +// * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the +// * horizontal and vertical directions. +// * +// * @param show true to show the scrollbars even when not required, false to show scrollbars only when required +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.8 +// */ +//public void setAlwaysShowScrollBars(boolean show) { +// checkWidget(); +// if (show == alwaysShowScroll) return; +// alwaysShowScroll = show; +// setScrollBars(true); +//} +///** +// * @see Control#setBackground(Color) +// */ +//@Override +//public void setBackground(Color color) { +// checkWidget(); +// boolean backgroundDisabled = false; +// if (!this.enabled && color == null) { +// if (background != null) { +// Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND); +// if (background.equals(disabledBg)) { +// return; +// } else { +// color = new Color (disabledBg.getRGBA()); +// backgroundDisabled = true; +// } +// } +// } +// customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled; +// background = color; +// super.setBackground(color); +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the block selection mode. +// * +// * @param blockSelection true=enable block selection, false=disable block selection +// * +// * @since 3.5 +// */ +//public void setBlockSelection(boolean blockSelection) { +// checkWidget(); +// if ((getStyle() & SWT.SINGLE) != 0) return; +// if (blockSelection == this.blockSelection) return; +// if (wordWrap) return; +// this.blockSelection = blockSelection; +// if (cursor == null) { +// Display display = getDisplay(); +// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; +// super.setCursor(display.getSystemCursor(type)); +// } +// if (blockSelection) { +// int start = selection[0].x; +// int end = selection[0].y; +// if (start != end) { +// setBlockSelectionOffset(start, end, false); +// } +// } else { +// clearBlockSelection(false, false); +// } +//} +///** +// * Sets the block selection bounds. The bounds is +// * relative to the upper left corner of the document. +// * +// * @param rect the new bounds for the block selection +// * +// * @see #setBlockSelectionBounds(int, int, int, int) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when point is null
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setBlockSelectionBounds(Rectangle rect) { +// checkWidget(); +// if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height); +//} +///** +// * Sets the block selection bounds. The bounds is +// * relative to the upper left corner of the document. +// * +// * @param x the new x coordinate for the block selection +// * @param y the new y coordinate for the block selection +// * @param width the new width for the block selection +// * @param height the new height for the block selection +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setBlockSelectionBounds(int x, int y, int width, int height) { +// checkWidget(); +// int verticalScrollOffset = getVerticalScrollOffset(); +// if (!blockSelection) { +// x -= horizontalScrollOffset; +// y -= verticalScrollOffset; +// int start = getOffsetAtPoint(x, y, null); +// int end = getOffsetAtPoint(x+width-1, y+height-1, null); +// setSelection(new int[] {start, end - start}, false, false); +// setCaretLocations(); +// return; +// } +// int minY = topMargin; +// int minX = leftMargin; +// int maxY = renderer.getHeight() - bottomMargin; +// int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin; +// int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset; +// int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset; +// int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset; +// int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset; +// if (isFixedLineHeight() && renderer.fixedPitch) { +// int avg = renderer.averageCharWidth; +// anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; +// locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset; +// } +// setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false); +//} +//void setBlockSelectionLocation (int x, int y, boolean sendEvent) { +// int verticalScrollOffset = getVerticalScrollOffset(); +// blockXLocation = x + horizontalScrollOffset; +// blockYLocation = y + verticalScrollOffset; +// int[] alignment = new int[1]; +// int offset = getOffsetAtPoint(x, y, alignment); +// setCaretOffsets(new int[] {offset}, alignment[0]); +// if (blockXAnchor == -1) { +// blockXAnchor = blockXLocation; +// blockYAnchor = blockYLocation; +// selectionAnchors[0] = caretOffsets[0]; +// } +// doBlockSelection(sendEvent); +//} +//void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) { +// int verticalScrollOffset = getVerticalScrollOffset(); +// blockXAnchor = anchorX + horizontalScrollOffset; +// blockYAnchor = anchorY + verticalScrollOffset; +// selectionAnchors[0] = getOffsetAtPoint(anchorX, anchorY, null); +// setBlockSelectionLocation(x, y, sendEvent); +//} +//void setBlockSelectionOffset (int offset, boolean sendEvent) { +// Point point = getPointAtOffset(offset); +// int verticalScrollOffset = getVerticalScrollOffset(); +// blockXLocation = point.x + horizontalScrollOffset; +// blockYLocation = point.y + verticalScrollOffset; +// setCaretOffsets(new int[] {offset}, SWT.DEFAULT); +// if (blockXAnchor == -1) { +// blockXAnchor = blockXLocation; +// blockYAnchor = blockYLocation; +// selectionAnchors[0] = caretOffsets[0]; +// } +// doBlockSelection(sendEvent); +//} +//void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) { +// int verticalScrollOffset = getVerticalScrollOffset(); +// Point anchorPoint = getPointAtOffset(anchorOffset); +// blockXAnchor = anchorPoint.x + horizontalScrollOffset; +// blockYAnchor = anchorPoint.y + verticalScrollOffset; +// selectionAnchors[0] = anchorOffset; +// setBlockSelectionOffset(offset, sendEvent); +//} +// +///** +// * Sets the receiver's caret. Set the caret's height and location. +// * +// * @param caret the new caret for the receiver +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//@Override +//public void setCaret(Caret caret) { +// checkWidget (); +// super.setCaret(caret); +// caretDirection = SWT.NULL; +// if (caret != null) { +// setCaretLocations(); +// if(carets != null) { +// for (int i = 1; i < carets.length; i++) { +// carets[i].dispose(); +// } +// } +// carets = new Caret[] {caret}; +// } else { +// carets = null; +// } +//} +///** +// * Sets the BIDI coloring mode. When true the BIDI text display +// * algorithm is applied to segments of text that are the same +// * color. +// * +// * @param mode the new coloring mode +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @deprecated use BidiSegmentListener instead. +// */ +//@Deprecated +//public void setBidiColoring(boolean mode) { +// checkWidget(); +// bidiColoring = mode; +//} +///** +// * Sets the bottom margin. +// * +// * @param bottomMargin the bottom margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setBottomMargin (int bottomMargin) { +// checkWidget(); +// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); +//} +///** +// * Moves the Caret to the current caret offset. +// */ +//void setCaretLocations() { +// Point[] newCaretPos = Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new); +// setCaretLocations(newCaretPos, getCaretDirection()); +//} +//void setCaretLocations(final Point[] locations, int direction) { +// Caret firstCaret = getCaret(); +// if (firstCaret != null) { +// if (carets == null || carets.length == 0) { +// carets = new Caret[] { firstCaret }; +// } +// final boolean isDefaultCaret = firstCaret == defaultCaret; +// if (locations.length > carets.length) { +// int formerCaretCount = carets.length; +// carets = Arrays.copyOf(carets, locations.length); +// for (int i = formerCaretCount; i < carets.length; i++) { +// carets[i] = new Caret(this, firstCaret.getStyle()); +// carets[i].setImage(firstCaret.getImage()); +// carets[i].setFont(firstCaret.getFont()); +// carets[i].setSize(firstCaret.getSize()); +// } +// } else if (locations.length < carets.length) { +// for (int i = locations.length; i < carets.length; i++) { +// carets[i].dispose(); +// } +// carets = Arrays.copyOf(carets, locations.length); +// } +// for (int i = Math.min(caretOffsets.length, locations.length)-1; i>=0; i--) { // reverse order, seee bug 579028#c7 +// final Caret caret = carets[i]; +// final int caretOffset = caretOffsets[i]; +// final Point location = locations[i]; +// final StyleRange styleAtOffset = content.getCharCount() > 0 ? +// (caretOffset < content.getCharCount() ? +// getStyleRangeAtOffset(caretOffset) : +// getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style +// null; +// final int caretLine = content.getLineAtOffset(caretOffset); +// +// int graphicalLineHeight = getLineHeight(); +// final int lineStartOffset = getOffsetAtLine(caretLine); +// int graphicalLineFirstOffset = lineStartOffset; +// final int lineEndOffset = lineStartOffset + getLine(caretLine).length(); +// int graphicalLineLastOffset = lineEndOffset; +// if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles... +// graphicalLineHeight = getLineHeight(caretOffset); +// final Rectangle characterBounds = getBoundsAtOffset(caretOffset); +// graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y)); +// graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1; +// if (graphicalLineLastOffset < graphicalLineFirstOffset) { +// graphicalLineLastOffset = getCharCount(); +// } +// } +// +// int caretHeight = getLineHeight(); +// boolean isTextAlignedAtBottom = true; +// if (graphicalLineFirstOffset >= 0) { +// for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) { +// isTextAlignedAtBottom &= ( +// (style.font == null || Objects.equals(style.font, getFont())) && +// style.rise >= 0 && +// (style.metrics == null || style.metrics.descent <= 0) +// ); +// } +// } +// if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) { +// if (isDefaultCaret) { +// direction = SWT.DEFAULT; +// caretHeight = graphicalLineHeight; +// } else { +// caretHeight = caret.getSize().y; +// } +// } +// if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) { +// location.y += (graphicalLineHeight - caretHeight); +// } +// +// int imageDirection = direction; +// if (isMirrored()) { +// if (imageDirection == SWT.LEFT) { +// imageDirection = SWT.RIGHT; +// } else if (imageDirection == SWT.RIGHT) { +// imageDirection = SWT.LEFT; +// } +// } +// if (isDefaultCaret && imageDirection == SWT.RIGHT) { +// location.x -= (caret.getSize().x - 1); +// } +// if (isDefaultCaret) { +// caret.setBounds(location.x, location.y, caretWidth, caretHeight); +// } else { +// caret.setLocation(location); +// } +// if (direction != caretDirection) { +// caretDirection = direction; +// if (isDefaultCaret) { +// if (imageDirection == SWT.DEFAULT) { +// defaultCaret.setImage(null); +// } else if (imageDirection == SWT.LEFT) { +// defaultCaret.setImage(leftCaretBitmap); +// } else if (imageDirection == SWT.RIGHT) { +// defaultCaret.setImage(rightCaretBitmap); +// } +// } +// if (caretDirection == SWT.LEFT) { +// BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI); +// } else if (caretDirection == SWT.RIGHT) { +// BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI); +// } +// } +// } +// updateCaretVisibility(); +// super.redraw(); +// } +// columnX = locations[0].x; +//} +///** +// * Sets the caret offset. +// * +// * @param offset caret offset, relative to the first character in the text. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the offset is inside a multi byte line +// * delimiter (and thus neither clearly in front of or after the line delimiter) +// *
    +// */ +//public void setCaretOffset(int offset) { +// checkWidget(); +// int length = getCharCount(); +// if (length > 0 && !Arrays.equals(caretOffsets, new int[] {offset})) { +// if (offset < 0) { +// offset = 0; +// } else if (offset > length) { +// offset = length; +// } else { +// if (isLineDelimiter(offset)) { +// // offset is inside a multi byte line delimiter. This is an +// // illegal operation and an exception is thrown. Fixes 1GDKK3R +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// } +// setCaretOffsets(new int[] {offset}, PREVIOUS_OFFSET_TRAILING); +// // clear the selection if the caret is moved. +// // don't notify listeners about the selection change. +// if (blockSelection) { +// clearBlockSelection(true, false); +// } else { +// clearSelection(false); +// } +// } +// setCaretLocations(); +//} +//void setCaretOffsets(int[] newOffsets, int alignment) { +// if (newOffsets.length > 1) { +// newOffsets = Arrays.stream(newOffsets).distinct().sorted().toArray(); +// } +// if (!Arrays.equals(caretOffsets, newOffsets)) { +// caretOffsets = newOffsets; +// if (isListening(ST.CaretMoved)) { +// StyledTextEvent event = new StyledTextEvent(content); +// event.end = caretOffsets[caretOffsets.length - 1]; +// notifyListeners(ST.CaretMoved, event); +// } +// } +// if (alignment != SWT.DEFAULT) { +// caretAlignment = alignment; +// } +//} +///** +// * Copies the specified text range to the clipboard. The text will be placed +// * in the clipboard in plain text, HTML, and RTF formats. +// * +// * @param start start index of the text +// * @param length length of text to place in clipboard +// * +// * @exception SWTError +// * @see org.eclipse.swt.dnd.Clipboard#setContents +// */ +//void setClipboardContent(int start, int length, int clipboardType) throws SWTError { +// if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return; +// TextTransfer plainTextTransfer = TextTransfer.getInstance(); +// TextWriter plainTextWriter = new TextWriter(start, length); +// String plainText = getPlatformDelimitedText(plainTextWriter); +// Object[] data; +// Transfer[] types; +// if (clipboardType == DND.SELECTION_CLIPBOARD) { +// data = new Object[]{plainText}; +// types = new Transfer[]{plainTextTransfer}; +// } else { +// try { +// RTFTransfer rtfTransfer = RTFTransfer.getInstance(); +// RTFWriter rtfWriter = new RTFWriter(this, start, length); +// String rtfText = getPlatformDelimitedText(rtfWriter); +// +// HTMLTransfer htmlTransfer = HTMLTransfer.getInstance(); +// HTMLWriter htmlWriter = new HTMLWriter(this, start, length, content); +// String htmlText = getPlatformDelimitedText(htmlWriter); +// htmlText = "" +htmlText; //cause extra memory pressure to fail fast instead of failing in HTMLTransfer.javaToNative() +// data = new Object[]{rtfText, htmlText, plainText}; +// types = new Transfer[]{rtfTransfer, htmlTransfer, plainTextTransfer}; +// } catch (OutOfMemoryError oome) { +// // Adding RTF and HTML text may increase size by factor > 15 +// // fall back: copy plain text +// data = new Object[] { plainText }; +// types = new Transfer[] { plainTextTransfer }; +// clipboard.setContents(data, types, clipboardType); +// OutOfMemoryError customOome = new OutOfMemoryError( +// "Out of Memory: Copied only plain text (" + plainText.lines().count() + " lines)."); +// customOome.initCause(oome); +// // Still throw as it is likely that other threads silently failed too, but at least copied text is not lost +// throw customOome; +// } +// } +// clipboard.setContents(data, types, clipboardType); +//} +///** +// * Sets the content implementation to use for text storage. +// * +// * @param newContent StyledTextContent implementation to use for text storage. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when listener is null
    • +// *
    +// */ +//public void setContent(StyledTextContent newContent) { +// checkWidget(); +// if (newContent == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// if (content != null) { +// content.removeTextChangeListener(textChangeListener); +// } +// content = newContent; +// content.addTextChangeListener(textChangeListener); +// reset(); +//} +///** +// * Sets the receiver's cursor to the cursor specified by the +// * argument. Overridden to handle the null case since the +// * StyledText widget uses an ibeam as its default cursor. +// * +// * @see Control#setCursor(Cursor) +// */ +//@Override +//public void setCursor (Cursor cursor) { +// checkWidget(); +// if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// this.cursor = cursor; +// if (cursor == null) { +// Display display = getDisplay(); +// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; +// super.setCursor(display.getSystemCursor(type)); +// } else { +// super.setCursor(cursor); +// } +//} +///** +// * Sets whether the widget implements double click mouse behavior. +// * +// * @param enable if true double clicking a word selects the word, if false +// * double clicks have the same effect as regular mouse clicks. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void setDoubleClickEnabled(boolean enable) { +// checkWidget(); +// doubleClickEnabled = enable; +//} +//@Override +//public void setDragDetect (boolean dragDetect) { +// checkWidget (); +// this.dragDetect = dragDetect; +//} +///** +// * Sets whether the widget content can be edited. +// * +// * @param editable if true content can be edited, if false content can not be +// * edited +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void setEditable(boolean editable) { +// checkWidget(); +// this.editable = editable; +//} +//@Override +//public void setEnabled(boolean enabled) { +// super.setEnabled(enabled); +// Display display = getDisplay(); +// this.enabled = enabled; +// this.insideSetEnableCall = true; +// try { +// if (enabled && editable) { +// if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); +// if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); +// } else if(!enabled) { +// if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND)); +// if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND)); +// } else if(!editable) { +// if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND)); +// if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); +// } +// } +// finally { +// this.insideSetEnableCall = false; +// } +//} +// +//@Override +//public boolean setFocus() { +// boolean focusGained = super.setFocus(); +// if (focusGained && hasMultipleCarets()) { +// // Multiple carets need to update their drawing. See bug 579179 +// setCaretLocations(); +// } +// return focusGained; +//} +// +//private boolean hasMultipleCarets() { +// return carets != null && carets.length > 1; +//} +// +///** +// * See {@link TextLayout#setFixedLineMetrics} +// * +// * @since 3.125 +// */ +//public void setFixedLineMetrics(FontMetrics metrics) { +// renderer.setFixedLineMetrics (metrics); +//} +// +///** +// * Sets a new font to render text with. +// *

    +// * NOTE: Italic fonts are not supported unless they have no overhang +// * and the same baseline as regular fonts. +// *

    +// * +// * @param font new font +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//@Override +//public void setFont(Font font) { +// checkWidget(); +// int oldLineHeight = renderer.getLineHeight(); +// super.setFont(font); +// renderer.setFont(getFont(), tabLength); +// // keep the same top line visible. fixes 5815 +// if (isFixedLineHeight()) { +// int lineHeight = renderer.getLineHeight(); +// if (lineHeight != oldLineHeight) { +// int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset(); +// scrollVertical(vscroll, true); +// } +// } +// resetCache(0, content.getLineCount()); +// claimBottomFreeSpace(); +// calculateScrollBars(); +// if (isBidiCaret()) createCaretBitmaps(); +// caretDirection = SWT.NULL; +// setCaretLocations(); +// super.redraw(); +//} +//@Override +//public void setForeground(Color color) { +// checkWidget(); +// boolean foregroundDisabled = false; +// if (!this.enabled && color == null) { +// if (foreground != null) { +// Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND); +// if (foreground.equals(disabledFg)) { +// return; +// } else { +// color = new Color (disabledFg.getRGBA()); +// foregroundDisabled = true; +// } +// } +// } +// customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled; +// foreground = color; +// super.setForeground(color); +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the horizontal scroll offset relative to the start of the line. +// * Do nothing if there is no text set. +// *

    +// * NOTE: The horizontal index is reset to 0 when new text is set in the +// * widget. +// *

    +// * +// * @param offset horizontal scroll offset relative to the start +// * of the line, measured in character increments starting at 0, if +// * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void setHorizontalIndex(int offset) { +// checkWidget(); +// if (getCharCount() == 0) { +// return; +// } +// if (offset < 0) { +// offset = 0; +// } +// offset *= getHorizontalIncrement(); +// // allow any value if client area width is unknown or 0. +// // offset will be checked in resize handler. +// // don't use isVisible since width is known even if widget +// // is temporarily invisible +// if (clientAreaWidth > 0) { +// int width = renderer.getWidth(); +// // prevent scrolling if the content fits in the client area. +// // align end of longest line with right border of client area +// // if offset is out of range. +// if (offset > width - clientAreaWidth) { +// offset = Math.max(0, width - clientAreaWidth); +// } +// } +// scrollHorizontal(offset - horizontalScrollOffset, true); +//} +///** +// * Sets the horizontal SWT logical point offset relative to the start of the line. +// * Do nothing if there is no text set. +// *

    +// * NOTE: The horizontal SWT logical point offset is reset to 0 when new text +// * is set in the widget. +// *

    +// * +// * @param pixel horizontal SWT logical point offset relative to the start +// * of the line. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.0 +// */ +//public void setHorizontalPixel(int pixel) { +// checkWidget(); +// if (getCharCount() == 0) { +// return; +// } +// if (pixel < 0) { +// pixel = 0; +// } +// // allow any value if client area width is unknown or 0. +// // offset will be checked in resize handler. +// // don't use isVisible since width is known even if widget +// // is temporarily invisible +// if (clientAreaWidth > 0) { +// int width = renderer.getWidth(); +// // prevent scrolling if the content fits in the client area. +// // align end of longest line with right border of client area +// // if offset is out of range. +// if (pixel > width - clientAreaWidth) { +// pixel = Math.max(0, width - clientAreaWidth); +// } +// } +// scrollHorizontal(pixel - horizontalScrollOffset, true); +//} +///** +// * Sets the line indentation of the widget. +// *

    +// * It is the amount of blank space, in points, at the beginning of each line. +// * When a line wraps in several lines only the first one is indented. +// *

    +// * +// * @param indent the new indent +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #setLineIndent(int, int, int) +// * +// * @since 3.2 +// */ +//public void setIndent(int indent) { +// checkWidget(); +// if (this.indent == indent || indent < 0) return; +// this.indent = indent; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets whether the widget should justify lines. +// * +// * @param justify whether lines should be justified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #setLineJustify(int, int, boolean) +// * +// * @since 3.2 +// */ +//public void setJustify(boolean justify) { +// checkWidget(); +// if (this.justify == justify) return; +// this.justify = justify; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Maps a key to an action. +// *

    +// * One action can be associated with N keys. However, each key can only +// * have one action (key:action is N:1 relation). +// *

    +// * +// * @param key a key code defined in SWT.java or a character. +// * Optionally ORd with a state mask. Preferred state masks are one or more of +// * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform +// * differences. However, there may be cases where using the specific state masks +// * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. +// * @param action one of the predefined actions defined in ST.java. +// * Use SWT.NULL to remove a key binding. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void setKeyBinding(int key, int action) { +// checkWidget(); +// int modifierValue = key & SWT.MODIFIER_MASK; +// int keyInt = key & SWT.KEY_MASK; +// char keyChar = (char)keyInt; +// /** +// * Bug 440535: Make sure the key getting mapped to letter is in defiened +// * character range and filter out incorrect int to char typecasting. For +// * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p' +// */ +// if (Character.isDefined(keyInt) && Character.isLetter(keyChar)) { +// // make the keybinding case insensitive by adding it +// // in its upper and lower case form +// char ch = Character.toUpperCase(keyChar); +// int newKey = ch | modifierValue; +// if (action == SWT.NULL) { +// keyActionMap.remove(newKey); +// } else { +// keyActionMap.put(newKey, action); +// } +// ch = Character.toLowerCase(keyChar); +// newKey = ch | modifierValue; +// if (action == SWT.NULL) { +// keyActionMap.remove(newKey); +// } else { +// keyActionMap.put(newKey, action); +// } +// } else { +// if (action == SWT.NULL) { +// keyActionMap.remove(key); +// } else { +// keyActionMap.put(key, action); +// } +// } +//} +///** +// * Sets the left margin. +// * +// * @param leftMargin the left margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setLeftMargin (int leftMargin) { +// checkWidget(); +// setMargins(leftMargin, topMargin, rightMargin, bottomMargin); +//} +///** +// * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT, +// * SWT.CENTER or SWT.RIGHT. +// *

    +// * Note that if SWT.MULTI is set, then SWT.WRAP must also be set +// * in order to stabilize the right edge before setting alignment. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// * +// * @param startLine first line the alignment is applied to, 0 based +// * @param lineCount number of lines the alignment applies to. +// * @param alignment line alignment +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @see #setAlignment(int) +// * @since 3.2 +// */ +//public void setLineAlignment(int startLine, int lineCount, int alignment) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// +// renderer.setLineAlignment(startLine, lineCount, alignment); +// resetCache(startLine, lineCount); +// redrawLines(startLine, lineCount, false); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +// setAlignment(); +//} +///** +// * Sets the background color of the specified lines. +// *

    +// * The background color is drawn for the width of the widget. All +// * line background colors are discarded when setText is called. +// * The text background color if defined in a StyleRange overlays the +// * line background color. +// *

    +// * Should not be called if a LineBackgroundListener has been set since the +// * listener maintains the line backgrounds. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the color is applied to, 0 based +// * @param lineCount number of lines the color applies to. +// * @param background line background color +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// */ +//public void setLineBackground(int startLine, int lineCount, Color background) { +// checkWidget(); +// if (isListening(ST.LineGetBackground)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// if (background != null) { +// renderer.setLineBackground(startLine, lineCount, background); +// } else { +// renderer.clearLineBackground(startLine, lineCount); +// } +// redrawLines(startLine, lineCount, false); +//} +///** +// * Sets the bullet of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the bullet is applied to, 0 based +// * @param lineCount number of lines the bullet applies to. +// * @param bullet line bullet +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @since 3.2 +// */ +//public void setLineBullet(int startLine, int lineCount, Bullet bullet) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int oldBottom = getLinePixel(startLine + lineCount); +// renderer.setLineBullet(startLine, lineCount, bullet); +// resetCache(startLine, lineCount); +// int newBottom = getLinePixel(startLine + lineCount); +// redrawLines(startLine, lineCount, oldBottom != newBottom); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +//} +///** +// * Returns true if StyledText is in word wrap mode and false otherwise. +// * +// * @return true if StyledText is in word wrap mode and false otherwise. +// */ +//boolean isWordWrap() { +// return wordWrap || visualWrap; +//} +///** +// * Sets the indent of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the indent is applied to, 0 based +// * @param lineCount number of lines the indent applies to. +// * @param indent line indent +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @see #setIndent(int) +// * @since 3.2 +// */ +//public void setLineIndent(int startLine, int lineCount, int indent) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int oldBottom = getLinePixel(startLine + lineCount); +// renderer.setLineIndent(startLine, lineCount, indent); +// resetCache(startLine, lineCount); +// int newBottom = getLinePixel(startLine + lineCount); +// redrawLines(startLine, lineCount, oldBottom != newBottom); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +//} +// +///** +// * Sets the vertical indent of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * Setting both line spacing and vertical indent on a line would result in the +// * spacing and indent add up for the line. +// *

    +// * +// * @param lineIndex line index the vertical indent is applied to, 0 based +// * @param verticalLineIndent vertical line indent +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line index is invalid
    • +// *
    +// * @since 3.109 +// */ +//public void setLineVerticalIndent(int lineIndex, int verticalLineIndent) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (lineIndex < 0 || lineIndex >= content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int previousVerticalIndent = renderer.getLineVerticalIndent(lineIndex); +// if (verticalLineIndent == previousVerticalIndent) { +// return; +// } +// int initialTopPixel = getTopPixel(); +// int initialTopIndex = getPartialTopIndex(); +// int initialBottomIndex = getPartialBottomIndex(); +// int verticalIndentDiff = verticalLineIndent - previousVerticalIndent; +// renderer.setLineVerticalIndent(lineIndex, verticalLineIndent); +// this.hasVerticalIndent = verticalLineIndent != 0 || renderer.hasVerticalIndent(); +// ScrollBar verticalScrollbar = getVerticalBar(); +// if (lineIndex < initialTopIndex) { +// verticalScrollOffset += verticalIndentDiff; // just change value, don't actually scroll/redraw +// if (verticalScrollbar != null) { +// verticalScrollbar.setSelection(verticalScrollOffset); +// verticalScrollbar.setMaximum(verticalScrollbar.getMaximum() + verticalIndentDiff); +// } +// } else if (lineIndex > initialBottomIndex) { +// if (verticalScrollbar != null) { +// verticalScrollbar.setMaximum(verticalScrollbar.getMaximum() + verticalIndentDiff); +// } +// } else { +// resetCache(lineIndex, 1); +// if((initialTopIndex == 0) && (initialBottomIndex == (content.getLineCount() - 1))) { // not scrollable editor +// setCaretLocations(); +// redrawLines(lineIndex, getBottomIndex() - lineIndex + 1, true); +// } else if (getFirstCaretLine() >= initialTopIndex && getFirstCaretLine() <= initialBottomIndex) { // caret line with caret mustn't move +// if (getFirstCaretLine() < lineIndex) { +// redrawLines(lineIndex, getPartialBottomIndex() - lineIndex + 1, true); +// } else { +// setTopPixel(initialTopPixel + verticalIndentDiff); +// } +// } else { // move as few lines as possible +// if (lineIndex - getTopIndex() < getBottomIndex() - lineIndex) { +// setTopPixel(initialTopPixel + verticalIndentDiff); +// } else { +// // redraw below +// redrawLines(lineIndex, getPartialBottomIndex() - lineIndex + 1, true); +// } +// } +// setScrollBars(true); +// } +//} +// +///** +// * Sets the justify of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the justify is applied to, 0 based +// * @param lineCount number of lines the justify applies to. +// * @param justify true if lines should be justified +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @see #setJustify(boolean) +// * @since 3.2 +// */ +//public void setLineJustify(int startLine, int lineCount, boolean justify) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// +// renderer.setLineJustify(startLine, lineCount, justify); +// resetCache(startLine, lineCount); +// redrawLines(startLine, lineCount, false); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +//} +///** +// * Sets the line spacing of the widget. The line spacing applies for all lines. +// * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized, +// * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}. +// * +// * @param lineSpacing the line spacing +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @see #setLineSpacingProvider(StyledTextLineSpacingProvider) +// * @since 3.2 +// */ +//public void setLineSpacing(int lineSpacing) { +// checkWidget(); +// if (this.lineSpacing == lineSpacing || lineSpacing < 0) return; +// this.lineSpacing = lineSpacing; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing +// * or reset the customized spacing if the argument is null. +// * +// * @param lineSpacingProvider the line spacing provider (or null) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @see #setLineSpacingProvider(StyledTextLineSpacingProvider) +// * @since 3.107 +// */ +//public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) { +// checkWidget(); +// boolean wasFixedLineHeight = isFixedLineHeight(); +// if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null +// || (renderer.getLineSpacingProvider() != null +// && renderer.getLineSpacingProvider().equals(lineSpacingProvider))) +// return; +// renderer.setLineSpacingProvider(lineSpacingProvider); +// // reset lines cache if needed +// if (lineSpacingProvider == null) { +// if (!wasFixedLineHeight) { +// resetCache(0, content.getLineCount()); +// } +// } else { +// if (wasFixedLineHeight) { +// int firstLine = -1; +// for (int i = 0; i < content.getLineCount(); i++) { +// Integer lineSpacing = lineSpacingProvider.getLineSpacing(i); +// if (lineSpacing != null && lineSpacing > 0) { +// // there is a custom line spacing, set StyledText as variable line height mode +// // reset only the line size +// renderer.reset(i, 1); +// if (firstLine == -1) { +// firstLine = i; +// } +// } +// } +// if (firstLine != -1) { +// // call reset cache for the first line which have changed to recompute scrollbars +// resetCache(firstLine, 0); +// } +// } +// } +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the tab stops of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the justify is applied to, 0 based +// * @param lineCount number of lines the justify applies to. +// * @param tabStops tab stops +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @see #setTabStops(int[]) +// * @since 3.6 +// */ +//public void setLineTabStops(int startLine, int lineCount, int[] tabStops) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// if (tabStops != null) { +// int pos = 0; +// int[] newTabs = new int[tabStops.length]; +// for (int i = 0; i < tabStops.length; i++) { +// if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// newTabs[i] = pos = tabStops[i]; +// } +// renderer.setLineTabStops(startLine, lineCount, newTabs); +// } else { +// renderer.setLineTabStops(startLine, lineCount, null); +// } +// resetCache(startLine, lineCount); +// redrawLines(startLine, lineCount, false); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +//} +///** +// * Sets the wrap indent of the specified lines. +// *

    +// * Should not be called if a LineStyleListener has been set since the listener +// * maintains the line attributes. +// *

    +// * All line attributes are maintained relative to the line text, not the +// * line index that is specified in this method call. +// * During text changes, when entire lines are inserted or removed, the line +// * attributes that are associated with the lines after the change +// * will "move" with their respective text. An entire line is defined as +// * extending from the first character on a line to the last and including the +// * line delimiter. +// *

    +// * When two lines are joined by deleting a line delimiter, the top line +// * attributes take precedence and the attributes of the bottom line are deleted. +// * For all other text changes line attributes will remain unchanged. +// *

    +// * +// * @param startLine first line the wrap indent is applied to, 0 based +// * @param lineCount number of lines the wrap indent applies to. +// * @param wrapIndent line wrap indent +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • +// *
    +// * @see #setWrapIndent(int) +// * @since 3.6 +// */ +//public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (startLine < 0 || startLine + lineCount > content.getLineCount()) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int oldBottom = getLinePixel(startLine + lineCount); +// renderer.setLineWrapIndent(startLine, lineCount, wrapIndent); +// resetCache(startLine, lineCount); +// int newBottom = getLinePixel(startLine + lineCount); +// redrawLines(startLine, lineCount, oldBottom != newBottom); +// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) { +// setCaretLocations(); +// } +//} +// +///** +// * Sets the color of the margins. +// * +// * @param color the new color (or null) +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setMarginColor(Color color) { +// checkWidget(); +// if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// marginColor = color; +// super.redraw(); +//} +///** +// * Sets the margins. +// * +// * @param leftMargin the left margin. +// * @param topMargin the top margin. +// * @param rightMargin the right margin. +// * @param bottomMargin the bottom margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) { +// checkWidget(); +// this.leftMargin = Math.max(0, leftMargin) + alignmentMargin; +// this.topMargin = Math.max(0, topMargin); +// this.rightMargin = Math.max(0, rightMargin); +// this.bottomMargin = Math.max(0, bottomMargin); +// resetCache(0, content.getLineCount()); +// setScrollBars(true); +// setCaretLocations(); +// setAlignment(); +// super.redraw(); +//} +///** +// * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget +// * by pressing the middle button and moving the cursor. +// * +// * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 3.110 +// */ +//public void setMouseNavigatorEnabled(boolean enabled) { +// checkWidget(); +// if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) { +// return; +// } +// if (enabled) { +// mouseNavigator = new MouseNavigator(this); +// } else { +// mouseNavigator.dispose(); +// mouseNavigator = null; +// } +//} +///** +// * Flips selection anchor based on word selection direction. +// */ +//void setMouseWordSelectionAnchor() { +// if (doubleClickEnabled && clickCount > 1) { +// if (caretOffsets[0] < doubleClickSelection.x) { +// selectionAnchors[0] = doubleClickSelection.y; +// } else if (caretOffsets[0] > doubleClickSelection.y) { +// selectionAnchors[0] = doubleClickSelection.x; +// } +// } +//} +///** +// * Sets the orientation of the receiver, which must be one +// * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. +// * +// * @param orientation new orientation style +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 2.1.2 +// */ +//@Override +//public void setOrientation(int orientation) { +// int oldOrientation = getOrientation(); +// super.setOrientation(orientation); +// int newOrientation = getOrientation(); +// if (oldOrientation != newOrientation) { +// resetBidiData(); +// } +//} +///** +// * Sets the right margin. +// * +// * @param rightMargin the right margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setRightMargin (int rightMargin) { +// checkWidget(); +// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); +//} +//void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) { +// int inactive = 1; +// if (clientArea < maximum) { +// bar.setMaximum(maximum - margin); +// bar.setThumb(clientArea - margin); +// bar.setPageIncrement(clientArea - margin); +// if (!alwaysShowScroll) bar.setVisible(true); +// } else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) { +// bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive); +// } +//} +///** +// * Adjusts the maximum and the page size of the scroll bars to +// * reflect content width/length changes. +// * +// * @param vertical indicates if the vertical scrollbar also needs to be set +// */ +//void setScrollBars(boolean vertical) { +// ignoreResize++; +// if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true; +// ScrollBar verticalBar = vertical ? getVerticalBar() : null; +// ScrollBar horizontalBar = getHorizontalBar(); +// int oldHeight = clientAreaHeight; +// int oldWidth = clientAreaWidth; +// if (!alwaysShowScroll) { +// if (verticalBar != null) verticalBar.setVisible(false); +// if (horizontalBar != null) horizontalBar.setVisible(false); +// } +// if (verticalBar != null) { +// setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin); +// } +// if (horizontalBar != null && !wordWrap) { +// setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin); +// if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) { +// setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin); +// if (verticalBar.getVisible()) { +// setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin); +// } +// } +// } +// if (!alwaysShowScroll) { +// redrawMargins(oldHeight, oldWidth); +// } +// ignoreResize--; +//} +///** +// * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). +// * +// * @param start new caret position +// * @see #setSelection(int,int) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a +// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) +// *
    +// */ +//public void setSelection(int start) { +// // checkWidget test done in setSelectionRange +// setSelection(start, start); +//} +///** +// * Sets the selection and scrolls it into view. +// *

    +// * Indexing is zero based. Text selections are specified in terms of +// * caret positions. In a text widget that contains N characters, there are +// * N+1 caret positions, ranging from 0..N +// *

    +// * +// * @param point x=selection start offset, y=selection end offset +// * The caret will be placed at the selection start when x > y. +// * @see #setSelection(int,int) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when point is null
    • +// *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a +// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) +// *
    +// */ +//public void setSelection(Point point) { +// checkWidget(); +// if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); +// setSelection(point.x, point.y); +//} +///** +// * Sets the receiver's selection background color to the color specified +// * by the argument, or to the default system color for the control +// * if the argument is null. +// * +// * @param color the new color (or null) +// * +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.1 +// */ +//public void setSelectionBackground (Color color) { +// checkWidget (); +// if (color != null) { +// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// selectionBackground = color; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the receiver's selection foreground color to the color specified +// * by the argument, or to the default system color for the control +// * if the argument is null. +// *

    +// * Note that this is a HINT. Some platforms do not allow the application +// * to change the selection foreground color. +// *

    +// * @param color the new color (or null) +// * +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.1 +// */ +//public void setSelectionForeground (Color color) { +// checkWidget (); +// if (color != null) { +// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// selectionForeground = color; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the selection and scrolls it into view. +// *

    +// * Indexing is zero based. Text selections are specified in terms of +// * caret positions. In a text widget that contains N characters, there are +// * N+1 caret positions, ranging from 0..N +// *

    +// * +// * @param start selection start offset. The caret will be placed at the +// * selection start when start > end. +// * @param end selection end offset +// * @see #setSelectionRange(int,int) +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a +// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) +// *
    +// */ +//public void setSelection(int start, int end) { +// setSelectionRange(start, end - start); +// showSelection(); +//} +///** +// * Sets the selection. +// *

    +// * The new selection may not be visible. Call showSelection to scroll +// * the selection into view. +// *

    +// * +// * @param start offset of the first selected character, start >= 0 must be true. +// * @param length number of characters to select, 0 <= start + length +// * <= getCharCount() must be true. +// * A negative length places the caret at the selection start. +// * @param sendEvent a Selection event is sent when set to true and when +// * the selection is reset. +// */ +//void setSelection(int[] regions, boolean sendEvent, boolean doBlock) { +// if (regions.length == 2 && selection.length == 1) { // single range before/after +// int start = regions[0]; +// int length = regions[1]; +// int end = start + length; +// if (start > end) { +// int temp = end; +// end = start; +// start = temp; +// } +// int selectionAnchor = selectionAnchors[0]; +// // is the selection range different or is the selection direction +// // different? +// if (selection[0].x != start || selection[0].y != end || +// (length > 0 && selectionAnchor != selection[0].x) || +// (length < 0 && selectionAnchor != selection[0].y)) { +// if (blockSelection && doBlock) { +// if (length < 0) { +// setBlockSelectionOffset(end, start, sendEvent); +// } else { +// setBlockSelectionOffset(start, end, sendEvent); +// } +// } else { +// int oldStart = selection[0].x; +// int oldLength = selection[0].y - selection[0].x; +// int charCount = content.getCharCount(); +// // called internally to remove selection after text is removed +// // therefore make sure redraw range is valid. +// int redrawX = Math.min(selection[0].x, charCount); +// int redrawY = Math.min(selection[0].y, charCount); +// if (length < 0) { +// selectionAnchors[0] = selectionAnchor = selection[0].y = end; +// selection[0].x = start; +// setCaretOffsets(new int[] {start}, PREVIOUS_OFFSET_TRAILING); +// } else { +// selectionAnchors[0] = selectionAnchor = selection[0].x = start; +// selection[0].y = end; +// setCaretOffsets(new int[] {end}, PREVIOUS_OFFSET_TRAILING); +// } +// redrawX = Math.min(redrawX, selection[0].x); +// redrawY = Math.max(redrawY, selection[0].y); +// if (redrawY - redrawX > 0) { +// internalRedrawRange(redrawX, redrawY - redrawX); +// } +// if (sendEvent && (oldLength != end - start || (oldLength != 0 && oldStart != start))) { +// sendSelectionEvent(); +// } +// sendAccessibleTextCaretMoved(); +// } +// } +// } else if (!blockSelection || !doBlock) { +// boolean caretAtEndOfSelection = regions[1] > 0; +// int charCount = content.getCharCount(); +// Point[] newRanges = new Point[regions.length / 2]; +// for (int i = 0; i < regions.length; i += 2) { +// int start = regions[i]; +// int length = regions[i + 1]; +// int end = start + length; +// if (start > end) { +// int temp = end; +// end = start; +// start = temp; +// } +// newRanges[i / 2] = new Point(start, end); +// } +// Arrays.sort(newRanges, SELECTION_COMPARATOR); +// // merge contiguous ranges +// int newRangeIndex = 0; +// for (Point range : newRanges) { +// if (newRangeIndex > 0) { +// Point previousRange = newRanges[newRangeIndex - 1]; +// if (previousRange.y >= range.x) { +// previousRange.y = Math.max(previousRange.y, range.y); +// } else { +// newRanges[newRangeIndex] = range; +// newRangeIndex++; +// } +// } else { +// newRanges[newRangeIndex] = range; +// newRangeIndex++; +// } +// } +// Point[] toRedraw = new Point[newRangeIndex + selection.length]; +// System.arraycopy(newRanges, 0, toRedraw, 0, newRangeIndex); +// System.arraycopy(selection, 0, toRedraw, newRangeIndex, selection.length); +// Arrays.sort(toRedraw, SELECTION_COMPARATOR); +// Point[] formerSelection = selection; +// selection = Arrays.copyOf(newRanges, newRangeIndex); +// Point currentToRedraw = null; +// for (Point p : toRedraw) { +// if (currentToRedraw == null) { +// currentToRedraw = new Point(p.x, p.y); +// } else if (currentToRedraw.y >= p.x - 1) { +// // expand if necessary +// currentToRedraw = new Point(currentToRedraw.x, Math.max(p.y, currentToRedraw.y)); +// } else { +// currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y)); +// internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x); +// currentToRedraw = null; +// } +// } +// if (currentToRedraw != null) { +// currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y)); +// internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x); +// } +// if (!caretAtEndOfSelection) { +// selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.y).toArray(); +// setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.x).toArray(), PREVIOUS_OFFSET_TRAILING); +// } else { +// selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.x).toArray(); +// setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.y).toArray(), PREVIOUS_OFFSET_TRAILING); +// } +// setCaretLocations(); +// if (sendEvent && !Arrays.equals(formerSelection, selection)) { +// sendSelectionEvent(); +// } +// sendAccessibleTextCaretMoved(); +// } +//} +///** +// * Sets the selection. +// *

    +// * The new selection may not be visible. Call showSelection to scroll the selection +// * into view. A negative length places the caret at the visual start of the selection. +// *

    +// * +// * @param start offset of the first selected character +// * @param length number of characters to select +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a +// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) +// *
    +// */ +//public void setSelectionRange(int start, int length) { +// setSelectionRanges(new int[] { start, length }); +//} +// +///** +// * Sets the selected locations/ranges. +// *

    +// * The new selection may not be visible. Call showSelection to scroll the selection +// * into view. A negative length places the caret at the visual start of the selection. +// *

    +// * +// * @param ranges an array of offset/length pairs. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT when either the start or the end of one selection range is inside a +// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
    • +// *
    • ERROR_INVALID_ARGUMENT when ranges are null or size isn't valid (not pair)
    • +// *
    +// * @see #getSelectionRanges() +// * @since 3.117 +// */ +//public void setSelectionRanges(int[] ranges) { +// checkWidget(); +// int contentLength = getCharCount(); +// if (ranges.length % 2 != 0) { +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int[] fixedRanges = Arrays.copyOf(ranges, ranges.length); +// for (int i = 0; i < ranges.length; i+=2) { +// int start = ranges[i]; +// start = Math.max(0, Math.min(start, contentLength)); +// int length = ranges[i + 1]; +// int end = start + length; +// if (end < 0) { +// length = -start; +// } else if (end > contentLength) { +// length = contentLength - start; +// } +// if (isLineDelimiter(start) || isLineDelimiter(start + length)) { +// // the start offset or end offset of the selection range is inside a +// // multi byte line delimiter. This is an illegal operation and an exception +// // is thrown. Fixes 1GDKK3R +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// fixedRanges[i] = start; +// fixedRanges[i + 1] = length; +// } +// setSelection(fixedRanges, false, true); +// setCaretLocations(); +//} +// +///** +// * Adds the specified style. +// *

    +// * The new style overwrites existing styles for the specified range. +// * Existing style ranges are adjusted if they partially overlap with +// * the new style. To clear an individual style, call setStyleRange +// * with a StyleRange that has null attributes. +// *

    +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param range StyleRange object containing the style information. +// * Overwrites the old style in the given range. May be null to delete +// * all styles. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
    • +// *
    +// */ +//public void setStyleRange(StyleRange range) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (range != null) { +// if (range.isUnstyled()) { +// setStyleRanges(range.start, range.length, null, null, false); +// } else { +// setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); +// } +// } else { +// setStyleRanges(0, 0, null, null, true); +// } +//} +///** +// * Clears the styles in the range specified by start and +// * length and adds the new styles. +// *

    +// * The ranges array contains start and length pairs. Each pair refers to +// * the corresponding style in the styles array. For example, the pair +// * that starts at ranges[n] with length ranges[n+1] uses the style +// * at styles[n/2]. The range fields within each StyleRange are ignored. +// * If ranges or styles is null, the specified range is cleared. +// *

    +// * Note: It is expected that the same instance of a StyleRange will occur +// * multiple times within the styles array, reducing memory usage. +// *

    +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param start offset of first character where styles will be deleted +// * @param length length of the range to delete styles in +// * @param ranges the array of ranges. The ranges must not overlap and must be in order. +// * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • +// *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • +// *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • +// *
    • ERROR_INVALID_RANGE when a range overlaps
    • +// *
    +// * +// * @since 3.2 +// */ +//public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (ranges == null || styles == null) { +// setStyleRanges(start, length, null, null, false); +// } else { +// setStyleRanges(start, length, ranges, styles, false); +// } +//} +///** +// * Sets styles to be used for rendering the widget content. +// *

    +// * All styles in the widget will be replaced with the given set of ranges and styles. +// * The ranges array contains start and length pairs. Each pair refers to +// * the corresponding style in the styles array. For example, the pair +// * that starts at ranges[n] with length ranges[n+1] uses the style +// * at styles[n/2]. The range fields within each StyleRange are ignored. +// * If either argument is null, the styles are cleared. +// *

    +// * Note: It is expected that the same instance of a StyleRange will occur +// * multiple times within the styles array, reducing memory usage. +// *

    +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param ranges the array of ranges. The ranges must not overlap and must be in order. +// * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • +// *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • +// *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • +// *
    • ERROR_INVALID_RANGE when a range overlaps
    • +// *
    +// * +// * @since 3.2 +// */ +//public void setStyleRanges(int[] ranges, StyleRange[] styles) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (ranges == null || styles == null) { +// setStyleRanges(0, 0, null, null, true); +// } else { +// setStyleRanges(0, 0, ranges, styles, true); +// } +//} +//void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) { +// int charCount = content.getCharCount(); +// if (reset) { +// start = 0; +// length = charCount; +// } +// int[] formerRanges = getRanges(start, length); +// StyleRange[] formerStyles = getStyleRanges(start, length); +// int end = start + length; +// final boolean wasFixedLineHeight = isFixedLineHeight(); +// if (start > end || start < 0) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (styles != null) { +// if (end > charCount) { +// SWT.error(SWT.ERROR_INVALID_RANGE); +// } +// if (ranges != null) { +// if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// int lastOffset = 0; +// for (int i = 0; i < styles.length; i ++) { +// if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// int rangeStart, rangeLength; +// if (ranges != null) { +// rangeStart = ranges[i << 1]; +// rangeLength = ranges[(i << 1) + 1]; +// } else { +// rangeStart = styles[i].start; +// rangeLength = styles[i].length; +// } +// if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// hasStyleWithVariableHeight |= styles[i].isVariableHeight(); +// lastOffset = rangeStart + rangeLength; +// } +// } +// int rangeStart = start, rangeEnd = end; +// if (styles != null && styles.length > 0) { +// if (ranges != null) { +// rangeStart = ranges[0]; +// rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1]; +// } else { +// rangeStart = styles[0].start; +// rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length; +// } +// } +// +// // This needs to happen before new styles are applied +// int expectedBottom = 0; +// if (!isFixedLineHeight() && !reset) { +// int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); +// int partialTopIndex = getPartialTopIndex(); +// int partialBottomIndex = getPartialBottomIndex(); +// if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { +// expectedBottom = getLinePixel(lineEnd + 1); +// } +// } +// if (reset) { +// renderer.setStyleRanges(null, null); +// } else { +// renderer.updateRanges(start, length, length); +// } +// if (styles != null && styles.length > 0) { +// renderer.setStyleRanges(ranges, styles); +// } +// +// // re-evaluate variable height with all styles (including new ones) +// hasStyleWithVariableHeight = false; +// for (StyleRange style : getStyleRanges(false)) { +// hasStyleWithVariableHeight = style.isVariableHeight(); +// if (hasStyleWithVariableHeight) break; +// } +// +// SortedSet modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles); +// resetCache(modifiedLines); +// if (reset) { +// super.redraw(); +// } else { +// int lineStart = content.getLineAtOffset(Math.min(start, rangeStart)); +// int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); +// int partialTopIndex = getPartialTopIndex(); +// int partialBottomIndex = getPartialBottomIndex(); +// if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) { +// int top = 0; +// int bottom = clientAreaHeight; +// if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) { +// top = Math.max(0, getLinePixel(lineStart)); +// } +// if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { +// bottom = getLinePixel(lineEnd + 1); +// } +// if (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) { +// bottom = clientAreaHeight; +// } +// super.redraw(0, top, clientAreaWidth, bottom - top, false); +// } +// } +// int oldColumnX = columnX; +// setCaretLocations(); +// columnX = oldColumnX; +// doMouseLinkCursor(); +//} +// +///** +// * +// * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)} +// * @param newRanges former ranges, sorted by order and without overlapping +// */ +//private SortedSet computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) { +// if (referenceStyles == null) { +// referenceStyles = new StyleRange[0]; +// } +// if (referenceRanges == null) { +// referenceRanges = createRanges(referenceStyles); +// } +// if (newStyles == null) { +// newStyles = new StyleRange[0]; +// } +// if (newRanges == null) { +// newRanges = createRanges(newStyles); +// } +// if (referenceRanges.length != 2 * referenceStyles.length) { +// throw new IllegalArgumentException(); +// } +// if (newRanges.length != 2 * newStyles.length) { +// throw new IllegalArgumentException(); +// } +// SortedSet res = new TreeSet<>(); +// int referenceRangeIndex = 0; +// int newRangeIndex = 0; +// StyleRange defaultStyle = new StyleRange(); +// defaultStyle.foreground = this.foreground; +// defaultStyle.background = this.background; +// defaultStyle.font = getFont(); +// int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE; +// if (newRanges.length > 0) { +// currentOffset = Math.min(currentOffset, newRanges[0]); +// } +// while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) { +// int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset +// +// while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) { +// referenceRangeIndex++; +// } +// StyleRange referenceStyleAtCurrentOffset = defaultStyle; +// if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling +// referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex]; +// nextMilestoneOffset = endRangeOffset(referenceRanges, referenceRangeIndex); +// } else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling +// nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range +// } +// +// while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) { +// newRangeIndex++; +// } +// StyleRange newStyleAtCurrentOffset = defaultStyle; +// if (isInRange(newRanges, newRangeIndex, currentOffset)) { +// newStyleAtCurrentOffset = newStyles[newRangeIndex]; +// nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex)); +// } else if (newRangeIndex < newStyles.length) { +// nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]); +// } +// +// if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) { +// int fromLine = getLineAtOffset(currentOffset); +// int toLine = getLineAtOffset(nextMilestoneOffset - 1); +// for (int line = fromLine; line <= toLine; line++) { +// res.add(line); +// } +// currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount(); +// } else { +// currentOffset = nextMilestoneOffset; +// } +// } +// return res; +//} +//private int[] createRanges(StyleRange[] referenceStyles) { +// int[] referenceRanges; +// referenceRanges = new int[2 * referenceStyles.length]; +// for (int i = 0; i < referenceStyles.length; i++) { +// referenceRanges[2 * i] = referenceStyles[i].start; +// referenceRanges[2 * i + 1] = referenceStyles[i].length; +// } +// return referenceRanges; +//} +// +//private boolean isInRange(int[] ranges, int styleIndex, int offset) { +// if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) { +// return false; +// } +// int start = ranges[2 * styleIndex]; +// int length = ranges[2 * styleIndex + 1]; +// return offset >= start && offset < start + length; +//} +// +///** +// * The offset on which the range ends (excluded) +// */ +//private int endRangeOffset(int[] ranges, int styleIndex) { +// if (styleIndex < 0 || 2 * styleIndex > ranges.length) { +// throw new IllegalArgumentException(); +// } +// int start = ranges[2 * styleIndex]; +// int length = ranges[2 * styleIndex + 1]; +// return start + length; +//} +// +///** +// * Sets styles to be used for rendering the widget content. All styles +// * in the widget will be replaced with the given set of styles. +// *

    +// * Note: Because a StyleRange includes the start and length, the +// * same instance cannot occur multiple times in the array of styles. +// * If the same style attributes, such as font and color, occur in +// * multiple StyleRanges, setStyleRanges(int[], StyleRange[]) +// * can be used to share styles and reduce memory usage. +// *

    +// * Should not be called if a LineStyleListener has been set since the +// * listener maintains the styles. +// *

    +// * +// * @param ranges StyleRange objects containing the style information. +// * The ranges should not overlap. The style rendering is undefined if +// * the ranges do overlap. Must not be null. The styles need to be in order. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when the list of ranges is null
    • +// *
    • ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
    • +// *
    +// * +// * @see #setStyleRanges(int[], StyleRange[]) +// */ +//public void setStyleRanges(StyleRange[] ranges) { +// checkWidget(); +// if (isListening(ST.LineGetStyle)) return; +// if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// setStyleRanges(0, 0, null, ranges, true); +//} +///** +// * Sets the tab width. +// * +// * @param tabs tab width measured in characters. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #setTabStops(int[]) +// */ +//public void setTabs(int tabs) { +// checkWidget(); +// tabLength = tabs; +// renderer.setFont(null, tabs); +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +// +///** +// * Sets the receiver's tab list. Each value in the tab list specifies +// * the space in points from the origin of the document to the respective +// * tab stop. The last tab stop width is repeated continuously. +// * +// * @param tabs the new tab list (or null) +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_INVALID_ARGUMENT - if a tab stop is negative or less than the previous stop in the list
    • +// *
    +// * +// * @see StyledText#getTabStops() +// * +// * @since 3.6 +// */ +//public void setTabStops(int [] tabs) { +// checkWidget(); +// if (tabs != null) { +// int pos = 0; +// int[] newTabs = new int[tabs.length]; +// for (int i = 0; i < tabs.length; i++) { +// if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// newTabs[i] = pos = tabs[i]; +// } +// this.tabs = newTabs; +// } else { +// this.tabs = null; +// } +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +// +///** +// * Sets the widget content. +// * If the widget has the SWT.SINGLE style and "text" contains more than +// * one line, only the first line is rendered but the text is stored +// * unchanged. A subsequent call to getText will return the same text +// * that was set. +// *

    +// * Note: Only a single line of text should be set when the SWT.SINGLE +// * style is used. +// *

    +// * +// * @param text new widget content. Replaces existing content. Line styles +// * that were set using StyledText API are discarded. The +// * current selection is also discarded. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT when string is null
    • +// *
    +// */ +//public void setText(String text) { +// checkWidget(); +// if (text == null) { +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// } +// Event event = new Event(); +// event.start = 0; +// event.end = getCharCount(); +// event.text = text; +// event.doit = true; +// notifyListeners(SWT.Verify, event); +// if (event.doit) { +// StyledTextEvent styledTextEvent = null; +// if (isListening(ST.ExtendedModify)) { +// styledTextEvent = new StyledTextEvent(content); +// styledTextEvent.start = event.start; +// styledTextEvent.end = event.start + event.text.length(); +// styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); +// } +// content.setText(event.text); +// notifyListeners(SWT.Modify, event); +// if (styledTextEvent != null) { +// notifyListeners(ST.ExtendedModify, styledTextEvent); +// } +// } +//} +// +///** +// * Sets the base text direction (a.k.a. "paragraph direction") of the receiver, +// * which must be one of the constants SWT.LEFT_TO_RIGHT or +// * SWT.RIGHT_TO_LEFT. +// *

    +// * setOrientation would override this value with the text direction +// * that is consistent with the new orientation. +// *

    +// *

    +// * Warning: This API is currently only implemented on Windows. +// * It doesn't set the base text direction on GTK and Cocoa. +// *

    +// * +// * @param textDirection the base text direction style +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see SWT#FLIP_TEXT_DIRECTION +// */ +//@Override +//public void setTextDirection(int textDirection) { +// checkWidget(); +// int oldStyle = getStyle(); +// super.setTextDirection(textDirection); +// if (isAutoDirection () || oldStyle != getStyle()) { +// resetBidiData(); +// } +//} +// +///** +// * Sets the text limit to the specified number of characters. +// *

    +// * The text limit specifies the amount of text that +// * the user can type into the widget. +// *

    +// * +// * @param limit the new text limit. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_CANNOT_BE_ZERO when limit is 0
    • +// *
    +// */ +//public void setTextLimit(int limit) { +// checkWidget(); +// if (limit == 0) { +// SWT.error(SWT.ERROR_CANNOT_BE_ZERO); +// } +// textLimit = limit; +//} +///** +// * Sets the top index. Do nothing if there is no text set. +// *

    +// * The top index is the index of the line that is currently at the top +// * of the widget. The top index changes when the widget is scrolled. +// * Indexing starts from zero. +// * Note: The top index is reset to 0 when new text is set in the widget. +// *

    +// * +// * @param topIndex new top index. Must be between 0 and +// * getLineCount() - fully visible lines per page. If no lines are fully +// * visible the maximum value is getLineCount() - 1. An out of range +// * index will be adjusted accordingly. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void setTopIndex(int topIndex) { +// checkWidget(); +// if (getCharCount() == 0) { +// return; +// } +// int lineCount = content.getLineCount(), pixel; +// if (isFixedLineHeight()) { +// int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); +// if (topIndex < 0) { +// topIndex = 0; +// } else if (topIndex > lineCount - pageSize) { +// topIndex = lineCount - pageSize; +// } +// pixel = getLinePixel(topIndex); +// } else { +// topIndex = Math.max(0, Math.min(lineCount - 1, topIndex)); +// pixel = getLinePixel(topIndex); +// if (pixel > 0) { +// pixel = getAvailableHeightBellow(pixel); +// } else { +// pixel = getAvailableHeightAbove(pixel); +// } +// } +// scrollVertical(pixel, true); +//} +///** +// * Sets the top margin. +// * +// * @param topMargin the top margin. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @since 3.5 +// */ +//public void setTopMargin (int topMargin) { +// checkWidget(); +// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); +//} +///** +// * Sets the top SWT logical point offset. Do nothing if there is no text set. +// *

    +// * The top point offset is the vertical SWT logical point offset of the widget. The +// * widget is scrolled so that the given SWT logical point position is at the top. +// * The top index is adjusted to the corresponding top line. +// * Note: The top point is reset to 0 when new text is set in the widget. +// *

    +// * +// * @param pixel new top point offset. Must be between 0 and +// * (getLineCount() - visible lines per page) / getLineHeight()). An out +// * of range offset will be adjusted accordingly. +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @since 2.0 +// */ +//public void setTopPixel(int pixel) { +// checkWidget(); +// if (getCharCount() == 0) { +// return; +// } +// if (pixel < 0) pixel = 0; +// int lineCount = content.getLineCount(); +// int height = clientAreaHeight - topMargin - bottomMargin; +// int verticalOffset = getVerticalScrollOffset(); +// if (isFixedLineHeight()) { +// int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); +// if (pixel > maxTopPixel) pixel = maxTopPixel; +// pixel -= verticalOffset; +// } else { +// pixel -= verticalOffset; +// if (pixel > 0) { +// pixel = getAvailableHeightBellow(pixel); +// } +// } +// scrollVertical(pixel, true); +//} +///** +// * Sets whether the widget wraps lines. +// *

    +// * This overrides the creation style bit SWT.WRAP. +// *

    +// * +// * @param wrap true=widget wraps lines, false=widget does not wrap lines +// * @since 2.0 +// */ +//public void setWordWrap(boolean wrap) { +// checkWidget(); +// if ((getStyle() & SWT.SINGLE) != 0) return; +// if (wordWrap == wrap) return; +// if (wordWrap && blockSelection) setBlockSelection(false); +// wordWrap = wrap; +// resetCache(0, content.getLineCount()); +// horizontalScrollOffset = 0; +// ScrollBar horizontalBar = getHorizontalBar(); +// if (horizontalBar != null) { +// horizontalBar.setVisible(!wordWrap); +// } +// setScrollBars(true); +// setCaretLocations(); +// super.redraw(); +//} +///** +// * Sets the wrap line indentation of the widget. +// *

    +// * It is the amount of blank space, in points, at the beginning of each wrapped line. +// * When a line wraps in several lines all the lines but the first one is indented +// * by this amount. +// *

    +// * +// * @param wrapIndent the new wrap indent +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * +// * @see #setLineWrapIndent(int, int, int) +// * +// * @since 3.6 +// */ +//public void setWrapIndent(int wrapIndent) { +// checkWidget(); +// if (this.wrapIndent == wrapIndent || wrapIndent < 0) return; +// this.wrapIndent = wrapIndent; +// resetCache(0, content.getLineCount()); +// setCaretLocations(); +// super.redraw(); +//} +//boolean showLocation(Rectangle rect, boolean scrollPage) { +// boolean scrolled = false; +// if (rect.y < topMargin) { +// scrolled = scrollVertical(rect.y - topMargin, true); +// } else if (rect.y + rect.height > clientAreaHeight - bottomMargin) { +// if (clientAreaHeight - topMargin - bottomMargin <= 0) { +// scrolled = scrollVertical(rect.y - topMargin, true); +// } else { +// scrolled = scrollVertical(rect.y + rect.height - (clientAreaHeight - bottomMargin), true); +// } +// } +// int width = clientAreaWidth - rightMargin - leftMargin; +// if (width > 0) { +// int minScroll = scrollPage ? width / 4 : 0; +// if (rect.x < leftMargin) { +// int scrollWidth = Math.max(leftMargin - rect.x, minScroll); +// int maxScroll = horizontalScrollOffset; +// scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true); +// } else if (rect.x + rect.width > (clientAreaWidth - rightMargin)) { +// int scrollWidth = Math.max(rect.x + rect.width - (clientAreaWidth - rightMargin), minScroll); +// int maxScroll = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth; +// scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true); +// } +// } +// return scrolled; +//} +///** +// * Sets the caret location and scrolls the caret offset into view. +// */ +//void showCaret() { +// Rectangle bounds = getBoundsAtOffset(caretOffsets[0]); +// if (!showLocation(bounds, true) || (carets != null && caretOffsets.length != carets.length)) { +// setCaretLocations(); +// } +//} +///** +// * Scrolls the selection into view. +// *

    +// * The end of the selection will be scrolled into view. +// * Note that if a right-to-left selection exists, the end of the selection is +// * the visual beginning of the selection (i.e., where the caret is located). +// *

    +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//public void showSelection() { +// checkWidget(); +// // is selection from right-to-left? +// boolean rightToLeft = caretOffsets[0] == selection[0].x; +// int startOffset, endOffset; +// if (rightToLeft) { +// startOffset = selection[0].y; +// endOffset = selection[0].x; +// } else { +// startOffset = selection[0].x; +// endOffset = selection[0].y; +// } +// +// Rectangle startBounds = getBoundsAtOffset(startOffset); +// Rectangle endBounds = getBoundsAtOffset(endOffset); +// +// // can the selection be fully displayed within the widget's visible width? +// int w = clientAreaWidth - leftMargin - rightMargin; +// boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; +// if (selectionFits) { +// // show as much of the selection as possible by first showing +// // the start of the selection +// if (showLocation(startBounds, false)) { +// // endX value could change if showing startX caused a scroll to occur +// endBounds = getBoundsAtOffset(endOffset); +// } +// // the character at endOffset is not part of the selection +// endBounds.width = endOffset == caretOffsets[0] ? getCaretWidth() : 0; +// showLocation(endBounds, false); +// } else { +// // just show the end of the selection since the selection start +// // will not be visible +// showLocation(endBounds, true); +// } +//} +//void updateCaretVisibility() { +// Caret caret = getCaret(); +// if (caret != null) { +// if (carets == null || carets.length == 0) { +// carets = new Caret[] { caret }; +// } +// if (blockSelection && blockXLocation != -1) { +// Arrays.stream(carets).forEach(c -> c.setVisible(false)); +// } else { +// Arrays.stream(carets).forEach(c -> { +// Point location = c.getLocation(); +// Point size = c.getSize(); +// boolean visible = +// topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin && +// leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin; +// c.setVisible(visible); +// }); +// } +// } +//} +///** +// * Updates the selection and caret position depending on the text change. +// *

    +// * If the selection intersects with the replaced text, the selection is +// * reset and the caret moved to the end of the new text. +// * If the selection is behind the replaced text it is moved so that the +// * same text remains selected. If the selection is before the replaced text +// * it is left unchanged. +// *

    +// * +// * @param startOffset offset of the text change +// * @param replacedLength length of text being replaced +// * @param newLength length of new text +// */ +//void updateSelection(int startOffset, int replacedLength, int newLength) { +// if (selection[selection.length - 1].y <= startOffset) { +// // selection ends before text change +// if (isWordWrap()) setCaretLocations(); +// return; +// } +// // clear selection fragment before text change +// Arrays.stream(selection) +// .filter(sel -> sel.y > startOffset) +// .filter(sel -> sel.x < startOffset) +// .forEach(sel -> internalRedrawRange(sel.x, startOffset - sel.x)); +// Arrays.stream(selection) +// .filter(sel -> sel.y > startOffset) +// .filter(sel -> sel.y > startOffset + replacedLength && sel.x < startOffset + replacedLength) +// .forEach(sel -> { +// // clear selection fragment after text change. +// // do this only when the selection is actually affected by the +// // change. Selection is only affected if it intersects the change (1GDY217). +// int netNewLength = newLength - replacedLength; +// int redrawStart = startOffset + newLength; +// internalRedrawRange(redrawStart, sel.y + netNewLength - redrawStart); +// }); +// setSelection(Arrays.stream(selection).map(sel -> { +// if (sel.y <= startOffset) { +// return sel; +// } else if (sel.x == startOffset && sel.y == startOffset + replacedLength) { +// return new Point(startOffset + newLength, startOffset + newLength); +// } else if (sel.y > startOffset && sel.x < startOffset + replacedLength) { +// // selection intersects replaced text. set caret behind text change +// return new Point(startOffset + newLength, startOffset + newLength); +// } else { +// // move selection to keep same text selected +// int x = sel.x + newLength - replacedLength; +// int y = sel.x + newLength - replacedLength + (sel.y - sel.x); +// +// return new Point(x < 0 ? 0 : x, y < 0 ? 0 : y); +// } +// }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)) +// .toArray(), true, false); +// setCaretLocations(); +//} +// +///** +// * The method accepts a StyledText and a callback which takes +// * all the carets of the StyledText as the argument and executes it. +// * The caret is refreshed after the execution of the callback. +// * +// * @param styledText the StyledText to get the carets from +// * @param caretUpdater the callback which works with the carets +// * +// * @noreference This method is not intended to be referenced by clients. +// */ +//public static void updateAndRefreshCarets(StyledText styledText, Consumer caretUpdater) { +// caretUpdater.accept(styledText.getCaret()); +// caretUpdater.accept(styledText.defaultCaret); +// for (Caret caret : styledText.carets) { +// caretUpdater.accept(caret); +// } +// styledText.updateCaretVisibility(); +// styledText.setCaretLocations(); +// +//} +// +//} - // This needs to happen before new styles are applied - int expectedBottom = 0; - if (!isFixedLineHeight() && !reset) { - int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); - int partialTopIndex = getPartialTopIndex(); - int partialBottomIndex = getPartialBottomIndex(); - if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { - expectedBottom = getLinePixel(lineEnd + 1); - } - } - if (reset) { - renderer.setStyleRanges(null, null); - } else { - renderer.updateRanges(start, length, length); - } - if (styles != null && styles.length > 0) { - renderer.setStyleRanges(ranges, styles); - } +import org.eclipse.swt.widgets.*; - // re-evaluate variable height with all styles (including new ones) - hasStyleWithVariableHeight = false; - for (StyleRange style : getStyleRanges(false)) { - hasStyleWithVariableHeight = style.isVariableHeight(); - if (hasStyleWithVariableHeight) break; - } +// TODO (visjee) SWING +public class StyledText extends Canvas { - SortedSet modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles); - resetCache(modifiedLines); - if (reset) { - super.redraw(); - } else { - int lineStart = content.getLineAtOffset(Math.min(start, rangeStart)); - int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); - int partialTopIndex = getPartialTopIndex(); - int partialBottomIndex = getPartialBottomIndex(); - if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) { - int top = 0; - int bottom = clientAreaHeight; - if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) { - top = Math.max(0, getLinePixel(lineStart)); - } - if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { - bottom = getLinePixel(lineEnd + 1); - } - if (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) { - bottom = clientAreaHeight; - } - super.redraw(0, top, clientAreaWidth, bottom - top, false); - } + public StyledText(Composite parent, int style) { + super(parent, style); } - int oldColumnX = columnX; - setCaretLocations(); - columnX = oldColumnX; - doMouseLinkCursor(); -} -/** - * - * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)} - * @param newRanges former ranges, sorted by order and without overlapping - */ -private SortedSet computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) { - if (referenceStyles == null) { - referenceStyles = new StyleRange[0]; - } - if (referenceRanges == null) { - referenceRanges = createRanges(referenceStyles); - } - if (newStyles == null) { - newStyles = new StyleRange[0]; - } - if (newRanges == null) { - newRanges = createRanges(newStyles); - } - if (referenceRanges.length != 2 * referenceStyles.length) { - throw new IllegalArgumentException(); + public String getMarginColor() { + throw new UnsupportedOperationException("Not implemented yet"); } - if (newRanges.length != 2 * newStyles.length) { - throw new IllegalArgumentException(); - } - SortedSet res = new TreeSet<>(); - int referenceRangeIndex = 0; - int newRangeIndex = 0; - StyleRange defaultStyle = new StyleRange(); - defaultStyle.foreground = this.foreground; - defaultStyle.background = this.background; - defaultStyle.font = getFont(); - int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE; - if (newRanges.length > 0) { - currentOffset = Math.min(currentOffset, newRanges[0]); - } - while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) { - int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset - - while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) { - referenceRangeIndex++; - } - StyleRange referenceStyleAtCurrentOffset = defaultStyle; - if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling - referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex]; - nextMilestoneOffset = endRangeOffset(referenceRanges, referenceRangeIndex); - } else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling - nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range - } - - while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) { - newRangeIndex++; - } - StyleRange newStyleAtCurrentOffset = defaultStyle; - if (isInRange(newRanges, newRangeIndex, currentOffset)) { - newStyleAtCurrentOffset = newStyles[newRangeIndex]; - nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex)); - } else if (newRangeIndex < newStyles.length) { - nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]); - } - if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) { - int fromLine = getLineAtOffset(currentOffset); - int toLine = getLineAtOffset(nextMilestoneOffset - 1); - for (int line = fromLine; line <= toLine; line++) { - res.add(line); - } - currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount(); - } else { - currentOffset = nextMilestoneOffset; - } + public String getTopMargin() { + throw new UnsupportedOperationException("Not implemented yet"); } - return res; -} -private int[] createRanges(StyleRange[] referenceStyles) { - int[] referenceRanges; - referenceRanges = new int[2 * referenceStyles.length]; - for (int i = 0; i < referenceStyles.length; i++) { - referenceRanges[2 * i] = referenceStyles[i].start; - referenceRanges[2 * i + 1] = referenceStyles[i].length; - } - return referenceRanges; -} -private boolean isInRange(int[] ranges, int styleIndex, int offset) { - if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) { - return false; + public String getRightMargin() { + throw new UnsupportedOperationException("Not implemented yet"); } - int start = ranges[2 * styleIndex]; - int length = ranges[2 * styleIndex + 1]; - return offset >= start && offset < start + length; -} -/** - * The offset on which the range ends (excluded) - */ -private int endRangeOffset(int[] ranges, int styleIndex) { - if (styleIndex < 0 || 2 * styleIndex > ranges.length) { - throw new IllegalArgumentException(); + public String getBottomMargin() { + throw new UnsupportedOperationException("Not implemented yet"); } - int start = ranges[2 * styleIndex]; - int length = ranges[2 * styleIndex + 1]; - return start + length; -} - -/** - * Sets styles to be used for rendering the widget content. All styles - * in the widget will be replaced with the given set of styles. - *

    - * Note: Because a StyleRange includes the start and length, the - * same instance cannot occur multiple times in the array of styles. - * If the same style attributes, such as font and color, occur in - * multiple StyleRanges, setStyleRanges(int[], StyleRange[]) - * can be used to share styles and reduce memory usage. - *

    - * Should not be called if a LineStyleListener has been set since the - * listener maintains the styles. - *

    - * - * @param ranges StyleRange objects containing the style information. - * The ranges should not overlap. The style rendering is undefined if - * the ranges do overlap. Must not be null. The styles need to be in order. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when the list of ranges is null
    • - *
    • ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
    • - *
    - * - * @see #setStyleRanges(int[], StyleRange[]) - */ -public void setStyleRanges(StyleRange[] ranges) { - checkWidget(); - if (isListening(ST.LineGetStyle)) return; - if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - setStyleRanges(0, 0, null, ranges, true); -} -/** - * Sets the tab width. - * - * @param tabs tab width measured in characters. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #setTabStops(int[]) - */ -public void setTabs(int tabs) { - checkWidget(); - tabLength = tabs; - renderer.setFont(null, tabs); - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the receiver's tab list. Each value in the tab list specifies - * the space in points from the origin of the document to the respective - * tab stop. The last tab stop width is repeated continuously. - * - * @param tabs the new tab list (or null) - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if a tab stop is negative or less than the previous stop in the list
    • - *
    - * - * @see StyledText#getTabStops() - * - * @since 3.6 - */ -public void setTabStops(int [] tabs) { - checkWidget(); - if (tabs != null) { - int pos = 0; - int[] newTabs = new int[tabs.length]; - for (int i = 0; i < tabs.length; i++) { - if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - newTabs[i] = pos = tabs[i]; - } - this.tabs = newTabs; - } else { - this.tabs = null; + public String getLeftMargin() { + throw new UnsupportedOperationException("Not implemented yet"); } - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the widget content. - * If the widget has the SWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text - * that was set. - *

    - * Note: Only a single line of text should be set when the SWT.SINGLE - * style is used. - *

    - * - * @param text new widget content. Replaces existing content. Line styles - * that were set using StyledText API are discarded. The - * current selection is also discarded. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT when string is null
    • - *
    - */ -public void setText(String text) { - checkWidget(); - if (text == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - Event event = new Event(); - event.start = 0; - event.end = getCharCount(); - event.text = text; - event.doit = true; - notifyListeners(SWT.Verify, event); - if (event.doit) { - StyledTextEvent styledTextEvent = null; - if (isListening(ST.ExtendedModify)) { - styledTextEvent = new StyledTextEvent(content); - styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); - styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); - } - content.setText(event.text); - notifyListeners(SWT.Modify, event); - if (styledTextEvent != null) { - notifyListeners(ST.ExtendedModify, styledTextEvent); - } + public int getIndent() { + throw new UnsupportedOperationException("Not implemented yet"); } -} -/** - * Sets the base text direction (a.k.a. "paragraph direction") of the receiver, - * which must be one of the constants SWT.LEFT_TO_RIGHT or - * SWT.RIGHT_TO_LEFT. - *

    - * setOrientation would override this value with the text direction - * that is consistent with the new orientation. - *

    - *

    - * Warning: This API is currently only implemented on Windows. - * It doesn't set the base text direction on GTK and Cocoa. - *

    - * - * @param textDirection the base text direction style - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see SWT#FLIP_TEXT_DIRECTION - */ -@Override -public void setTextDirection(int textDirection) { - checkWidget(); - int oldStyle = getStyle(); - super.setTextDirection(textDirection); - if (isAutoDirection () || oldStyle != getStyle()) { - resetBidiData(); + public boolean getWordWrap() { + throw new UnsupportedOperationException("Not implemented yet"); } -} -/** - * Sets the text limit to the specified number of characters. - *

    - * The text limit specifies the amount of text that - * the user can type into the widget. - *

    - * - * @param limit the new text limit. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @exception IllegalArgumentException
      - *
    • ERROR_CANNOT_BE_ZERO when limit is 0
    • - *
    - */ -public void setTextLimit(int limit) { - checkWidget(); - if (limit == 0) { - SWT.error(SWT.ERROR_CANNOT_BE_ZERO); - } - textLimit = limit; -} -/** - * Sets the top index. Do nothing if there is no text set. - *

    - * The top index is the index of the line that is currently at the top - * of the widget. The top index changes when the widget is scrolled. - * Indexing starts from zero. - * Note: The top index is reset to 0 when new text is set in the widget. - *

    - * - * @param topIndex new top index. Must be between 0 and - * getLineCount() - fully visible lines per page. If no lines are fully - * visible the maximum value is getLineCount() - 1. An out of range - * index will be adjusted accordingly. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void setTopIndex(int topIndex) { - checkWidget(); - if (getCharCount() == 0) { - return; - } - int lineCount = content.getLineCount(), pixel; - if (isFixedLineHeight()) { - int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); - if (topIndex < 0) { - topIndex = 0; - } else if (topIndex > lineCount - pageSize) { - topIndex = lineCount - pageSize; - } - pixel = getLinePixel(topIndex); - } else { - topIndex = Math.max(0, Math.min(lineCount - 1, topIndex)); - pixel = getLinePixel(topIndex); - if (pixel > 0) { - pixel = getAvailableHeightBellow(pixel); - } else { - pixel = getAvailableHeightAbove(pixel); - } - } - scrollVertical(pixel, true); -} -/** - * Sets the top margin. - * - * @param topMargin the top margin. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.5 - */ -public void setTopMargin (int topMargin) { - checkWidget(); - setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin); -} -/** - * Sets the top SWT logical point offset. Do nothing if there is no text set. - *

    - * The top point offset is the vertical SWT logical point offset of the widget. The - * widget is scrolled so that the given SWT logical point position is at the top. - * The top index is adjusted to the corresponding top line. - * Note: The top point is reset to 0 when new text is set in the widget. - *

    - * - * @param pixel new top point offset. Must be between 0 and - * (getLineCount() - visible lines per page) / getLineHeight()). An out - * of range offset will be adjusted accordingly. - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * @since 2.0 - */ -public void setTopPixel(int pixel) { - checkWidget(); - if (getCharCount() == 0) { - return; - } - if (pixel < 0) pixel = 0; - int lineCount = content.getLineCount(); - int height = clientAreaHeight - topMargin - bottomMargin; - int verticalOffset = getVerticalScrollOffset(); - if (isFixedLineHeight()) { - int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); - if (pixel > maxTopPixel) pixel = maxTopPixel; - pixel -= verticalOffset; - } else { - pixel -= verticalOffset; - if (pixel > 0) { - pixel = getAvailableHeightBellow(pixel); - } - } - scrollVertical(pixel, true); -} -/** - * Sets whether the widget wraps lines. - *

    - * This overrides the creation style bit SWT.WRAP. - *

    - * - * @param wrap true=widget wraps lines, false=widget does not wrap lines - * @since 2.0 - */ -public void setWordWrap(boolean wrap) { - checkWidget(); - if ((getStyle() & SWT.SINGLE) != 0) return; - if (wordWrap == wrap) return; - if (wordWrap && blockSelection) setBlockSelection(false); - wordWrap = wrap; - resetCache(0, content.getLineCount()); - horizontalScrollOffset = 0; - ScrollBar horizontalBar = getHorizontalBar(); - if (horizontalBar != null) { - horizontalBar.setVisible(!wordWrap); - } - setScrollBars(true); - setCaretLocations(); - super.redraw(); -} -/** - * Sets the wrap line indentation of the widget. - *

    - * It is the amount of blank space, in points, at the beginning of each wrapped line. - * When a line wraps in several lines all the lines but the first one is indented - * by this amount. - *

    - * - * @param wrapIndent the new wrap indent - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @see #setLineWrapIndent(int, int, int) - * - * @since 3.6 - */ -public void setWrapIndent(int wrapIndent) { - checkWidget(); - if (this.wrapIndent == wrapIndent || wrapIndent < 0) return; - this.wrapIndent = wrapIndent; - resetCache(0, content.getLineCount()); - setCaretLocations(); - super.redraw(); -} -boolean showLocation(Rectangle rect, boolean scrollPage) { - boolean scrolled = false; - if (rect.y < topMargin) { - scrolled = scrollVertical(rect.y - topMargin, true); - } else if (rect.y + rect.height > clientAreaHeight - bottomMargin) { - if (clientAreaHeight - topMargin - bottomMargin <= 0) { - scrolled = scrollVertical(rect.y - topMargin, true); - } else { - scrolled = scrollVertical(rect.y + rect.height - (clientAreaHeight - bottomMargin), true); - } - } - int width = clientAreaWidth - rightMargin - leftMargin; - if (width > 0) { - int minScroll = scrollPage ? width / 4 : 0; - if (rect.x < leftMargin) { - int scrollWidth = Math.max(leftMargin - rect.x, minScroll); - int maxScroll = horizontalScrollOffset; - scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true); - } else if (rect.x + rect.width > (clientAreaWidth - rightMargin)) { - int scrollWidth = Math.max(rect.x + rect.width - (clientAreaWidth - rightMargin), minScroll); - int maxScroll = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth; - scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true); - } + public int getAlignment() { + throw new UnsupportedOperationException("Not implemented yet"); } - return scrolled; -} -/** - * Sets the caret location and scrolls the caret offset into view. - */ -void showCaret() { - Rectangle bounds = getBoundsAtOffset(caretOffsets[0]); - if (!showLocation(bounds, true) || (carets != null && caretOffsets.length != carets.length)) { - setCaretLocations(); - } -} -/** - * Scrolls the selection into view. - *

    - * The end of the selection will be scrolled into view. - * Note that if a right-to-left selection exists, the end of the selection is - * the visual beginning of the selection (i.e., where the caret is located). - *

    - * - * @exception SWTException
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ -public void showSelection() { - checkWidget(); - // is selection from right-to-left? - boolean rightToLeft = caretOffsets[0] == selection[0].x; - int startOffset, endOffset; - if (rightToLeft) { - startOffset = selection[0].y; - endOffset = selection[0].x; - } else { - startOffset = selection[0].x; - endOffset = selection[0].y; - } - - Rectangle startBounds = getBoundsAtOffset(startOffset); - Rectangle endBounds = getBoundsAtOffset(endOffset); - // can the selection be fully displayed within the widget's visible width? - int w = clientAreaWidth - leftMargin - rightMargin; - boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; - if (selectionFits) { - // show as much of the selection as possible by first showing - // the start of the selection - if (showLocation(startBounds, false)) { - // endX value could change if showing startX caused a scroll to occur - endBounds = getBoundsAtOffset(endOffset); - } - // the character at endOffset is not part of the selection - endBounds.width = endOffset == caretOffsets[0] ? getCaretWidth() : 0; - showLocation(endBounds, false); - } else { - // just show the end of the selection since the selection start - // will not be visible - showLocation(endBounds, true); + public boolean getJustify() { + throw new UnsupportedOperationException("Not implemented yet"); } -} -void updateCaretVisibility() { - Caret caret = getCaret(); - if (caret != null) { - if (carets == null || carets.length == 0) { - carets = new Caret[] { caret }; - } - if (blockSelection && blockXLocation != -1) { - Arrays.stream(carets).forEach(c -> c.setVisible(false)); - } else { - Arrays.stream(carets).forEach(c -> { - Point location = c.getLocation(); - Point size = c.getSize(); - boolean visible = - topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin && - leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin; - c.setVisible(visible); - }); - } - } -} -/** - * Updates the selection and caret position depending on the text change. - *

    - * If the selection intersects with the replaced text, the selection is - * reset and the caret moved to the end of the new text. - * If the selection is behind the replaced text it is moved so that the - * same text remains selected. If the selection is before the replaced text - * it is left unchanged. - *

    - * - * @param startOffset offset of the text change - * @param replacedLength length of text being replaced - * @param newLength length of new text - */ -void updateSelection(int startOffset, int replacedLength, int newLength) { - if (selection[selection.length - 1].y <= startOffset) { - // selection ends before text change - if (isWordWrap()) setCaretLocations(); - return; - } - // clear selection fragment before text change - Arrays.stream(selection) - .filter(sel -> sel.y > startOffset) - .filter(sel -> sel.x < startOffset) - .forEach(sel -> internalRedrawRange(sel.x, startOffset - sel.x)); - Arrays.stream(selection) - .filter(sel -> sel.y > startOffset) - .filter(sel -> sel.y > startOffset + replacedLength && sel.x < startOffset + replacedLength) - .forEach(sel -> { - // clear selection fragment after text change. - // do this only when the selection is actually affected by the - // change. Selection is only affected if it intersects the change (1GDY217). - int netNewLength = newLength - replacedLength; - int redrawStart = startOffset + newLength; - internalRedrawRange(redrawStart, sel.y + netNewLength - redrawStart); - }); - setSelection(Arrays.stream(selection).map(sel -> { - if (sel.y <= startOffset) { - return sel; - } else if (sel.x == startOffset && sel.y == startOffset + replacedLength) { - return new Point(startOffset + newLength, startOffset + newLength); - } else if (sel.y > startOffset && sel.x < startOffset + replacedLength) { - // selection intersects replaced text. set caret behind text change - return new Point(startOffset + newLength, startOffset + newLength); - } else { - // move selection to keep same text selected - int x = sel.x + newLength - replacedLength; - int y = sel.x + newLength - replacedLength + (sel.y - sel.x); - - return new Point(x < 0 ? 0 : x, y < 0 ? 0 : y); - } - }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)) - .toArray(), true, false); - setCaretLocations(); -} -/** - * The method accepts a StyledText and a callback which takes - * all the carets of the StyledText as the argument and executes it. - * The caret is refreshed after the execution of the callback. - * - * @param styledText the StyledText to get the carets from - * @param caretUpdater the callback which works with the carets - * - * @noreference This method is not intended to be referenced by clients. - */ -public static void updateAndRefreshCarets(StyledText styledText, Consumer caretUpdater) { - caretUpdater.accept(styledText.getCaret()); - caretUpdater.accept(styledText.defaultCaret); - for (Caret caret : styledText.carets) { - caretUpdater.accept(caret); + public int getTextDirection() { + throw new UnsupportedOperationException("Not implemented yet"); } - styledText.updateCaretVisibility(); - styledText.setCaretLocations(); - -} - -} +} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java index 675cad903a8..bff9e09edb0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java @@ -13,9 +13,7 @@ *******************************************************************************/ package org.eclipse.swt.custom; -import org.eclipse.swt.*; import org.eclipse.swt.dnd.*; -import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; /** @@ -48,198 +46,203 @@ * @since 3.3 */ public class StyledTextDropTargetEffect extends DropTargetEffect { - static final int CARET_WIDTH = 2; - static final int SCROLL_HYSTERESIS = 100; // milli seconds - static final int SCROLL_TOLERANCE = 20; // pixels - int currentOffset = -1; - long scrollBeginTime; - int scrollX = -1, scrollY = -1; - Listener paintListener; - - /** - * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified - * StyledText. - * - * @param styledText the StyledText over which the user positions the cursor to drop the data - */ - public StyledTextDropTargetEffect(StyledText styledText) { - super(styledText); - paintListener = event -> { - if (currentOffset != -1) { - StyledText text = (StyledText) getControl(); - Point position = text.getLocationAtOffset(currentOffset); - int height = text.getLineHeight(currentOffset); - event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK)); - event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height); - } - }; - } - - /** - * This implementation of dragEnter provides a default drag under effect - * for the feedback specified in event.feedback. - * - * For additional information see DropTargetAdapter.dragEnter. - * - * Subclasses that override this method should call super.dragEnter(event) - * to get the default drag under effect implementation. - * - * @param event the information associated with the drag start event - * - * @see DropTargetAdapter - * @see DropTargetEvent - */ - @Override - public void dragEnter(DropTargetEvent event) { - currentOffset = -1; - scrollBeginTime = 0; - scrollX = -1; - scrollY = -1; - getControl().removeListener(SWT.Paint, paintListener); - getControl().addListener (SWT.Paint, paintListener); - } - - /** - * This implementation of dragLeave provides a default drag under effect - * for the feedback specified in event.feedback. - * - * For additional information see DropTargetAdapter.dragLeave. - * - * Subclasses that override this method should call super.dragLeave(event) - * to get the default drag under effect implementation. - * - * @param event the information associated with the drag leave event - * - * @see DropTargetAdapter - * @see DropTargetEvent - */ - @Override - public void dragLeave(DropTargetEvent event) { - StyledText text = (StyledText) getControl(); - if (currentOffset != -1) { - refreshCaret(text, currentOffset, -1); - } - text.removeListener(SWT.Paint, paintListener); - scrollBeginTime = 0; - scrollX = -1; - scrollY = -1; - } - - /** - * This implementation of dragOver provides a default drag under effect - * for the feedback specified in event.feedback. - * - * For additional information see DropTargetAdapter.dragOver. - * - * Subclasses that override this method should call super.dragOver(event) - * to get the default drag under effect implementation. - * - * @param event the information associated with the drag over event - * - * @see DropTargetAdapter - * @see DropTargetEvent - * @see DND#FEEDBACK_SELECT - * @see DND#FEEDBACK_SCROLL - */ - @Override - public void dragOver(DropTargetEvent event) { - int effect = event.feedback; - StyledText text = (StyledText) getControl(); - - Point pt = text.getDisplay().map(null, text, event.x, event.y); - if ((effect & DND.FEEDBACK_SCROLL) == 0) { - scrollBeginTime = 0; - scrollX = scrollY = -1; - } else { - if (text.getCharCount() == 0) { - scrollBeginTime = 0; - scrollX = scrollY = -1; - } else { - if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 0 && - (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) || - pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) { - if (System.currentTimeMillis() >= scrollBeginTime) { - Rectangle area = text.getClientArea(); - GC gc = new GC(text); - FontMetrics fm = gc.getFontMetrics(); - gc.dispose(); - double charWidth = fm.getAverageCharacterWidth(); - int scrollAmount = (int) (10*charWidth); - if (pt.x < area.x + 3*charWidth) { - int leftPixel = text.getHorizontalPixel(); - text.setHorizontalPixel(leftPixel - scrollAmount); - } - if (pt.x > area.width - 3*charWidth) { - int leftPixel = text.getHorizontalPixel(); - text.setHorizontalPixel(leftPixel + scrollAmount); - } - int lineHeight = text.getLineHeight(); - if (pt.y < area.y + lineHeight) { - int topPixel = text.getTopPixel(); - text.setTopPixel(topPixel - lineHeight); - } - if (pt.y > area.height - lineHeight) { - int topPixel = text.getTopPixel(); - text.setTopPixel(topPixel + lineHeight); - } - scrollBeginTime = 0; - scrollX = scrollY = -1; - } - } else { - scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS; - scrollX = pt.x; - scrollY = pt.y; - } - } - } - - if ((effect & DND.FEEDBACK_SELECT) != 0) { - int[] trailing = new int [1]; - int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false); - newOffset += trailing [0]; - if (newOffset != currentOffset) { - refreshCaret(text, currentOffset, newOffset); - currentOffset = newOffset; - } - } - } - - void refreshCaret(StyledText text, int oldOffset, int newOffset) { - if (oldOffset != newOffset) { - if (oldOffset != -1) { - Point oldPos = text.getLocationAtOffset(oldOffset); - int oldHeight = text.getLineHeight(oldOffset); - text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false); - } - if (newOffset != -1) { - Point newPos = text.getLocationAtOffset(newOffset); - int newHeight = text.getLineHeight(newOffset); - text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false); - } - } - } - - /** - * This implementation of dropAccept provides a default drag under effect - * for the feedback specified in event.feedback. - * - * For additional information see DropTargetAdapter.dropAccept. - * - * Subclasses that override this method should call super.dropAccept(event) - * to get the default drag under effect implementation. - * - * @param event the information associated with the drop accept event - * - * @see DropTargetAdapter - * @see DropTargetEvent - */ - @Override - public void dropAccept(DropTargetEvent event) { - if (currentOffset != -1) { - StyledText text = (StyledText) getControl(); - text.setSelection(currentOffset); - currentOffset = -1; - } + public StyledTextDropTargetEffect(Control control) { + super(control); + // TODO Auto-generated constructor stub } +// static final int CARET_WIDTH = 2; +// static final int SCROLL_HYSTERESIS = 100; // milli seconds +// static final int SCROLL_TOLERANCE = 20; // pixels +// +// int currentOffset = -1; +// long scrollBeginTime; +// int scrollX = -1, scrollY = -1; +// Listener paintListener; +// +// /** +// * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified +// * StyledText. +// * +// * @param styledText the StyledText over which the user positions the cursor to drop the data +// */ +// public StyledTextDropTargetEffect(StyledText styledText) { +// super(styledText); +// paintListener = event -> { +// if (currentOffset != -1) { +// StyledText text = (StyledText) getControl(); +// Point position = text.getLocationAtOffset(currentOffset); +// int height = text.getLineHeight(currentOffset); +// event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK)); +// event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height); +// } +// }; +// } +// +// /** +// * This implementation of dragEnter provides a default drag under effect +// * for the feedback specified in event.feedback. +// * +// * For additional information see DropTargetAdapter.dragEnter. +// * +// * Subclasses that override this method should call super.dragEnter(event) +// * to get the default drag under effect implementation. +// * +// * @param event the information associated with the drag start event +// * +// * @see DropTargetAdapter +// * @see DropTargetEvent +// */ +// @Override +// public void dragEnter(DropTargetEvent event) { +// currentOffset = -1; +// scrollBeginTime = 0; +// scrollX = -1; +// scrollY = -1; +// getControl().removeListener(SWT.Paint, paintListener); +// getControl().addListener (SWT.Paint, paintListener); +// } +// +// /** +// * This implementation of dragLeave provides a default drag under effect +// * for the feedback specified in event.feedback. +// * +// * For additional information see DropTargetAdapter.dragLeave. +// * +// * Subclasses that override this method should call super.dragLeave(event) +// * to get the default drag under effect implementation. +// * +// * @param event the information associated with the drag leave event +// * +// * @see DropTargetAdapter +// * @see DropTargetEvent +// */ +// @Override +// public void dragLeave(DropTargetEvent event) { +// StyledText text = (StyledText) getControl(); +// if (currentOffset != -1) { +// refreshCaret(text, currentOffset, -1); +// } +// text.removeListener(SWT.Paint, paintListener); +// scrollBeginTime = 0; +// scrollX = -1; +// scrollY = -1; +// } +// +// /** +// * This implementation of dragOver provides a default drag under effect +// * for the feedback specified in event.feedback. +// * +// * For additional information see DropTargetAdapter.dragOver. +// * +// * Subclasses that override this method should call super.dragOver(event) +// * to get the default drag under effect implementation. +// * +// * @param event the information associated with the drag over event +// * +// * @see DropTargetAdapter +// * @see DropTargetEvent +// * @see DND#FEEDBACK_SELECT +// * @see DND#FEEDBACK_SCROLL +// */ +// @Override +// public void dragOver(DropTargetEvent event) { +// int effect = event.feedback; +// StyledText text = (StyledText) getControl(); +// +// Point pt = text.getDisplay().map(null, text, event.x, event.y); +// if ((effect & DND.FEEDBACK_SCROLL) == 0) { +// scrollBeginTime = 0; +// scrollX = scrollY = -1; +// } else { +// if (text.getCharCount() == 0) { +// scrollBeginTime = 0; +// scrollX = scrollY = -1; +// } else { +// if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 0 && +// (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) || +// pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) { +// if (System.currentTimeMillis() >= scrollBeginTime) { +// Rectangle area = text.getClientArea(); +// GC gc = new GC(text); +// FontMetrics fm = gc.getFontMetrics(); +// gc.dispose(); +// double charWidth = fm.getAverageCharacterWidth(); +// int scrollAmount = (int) (10*charWidth); +// if (pt.x < area.x + 3*charWidth) { +// int leftPixel = text.getHorizontalPixel(); +// text.setHorizontalPixel(leftPixel - scrollAmount); +// } +// if (pt.x > area.width - 3*charWidth) { +// int leftPixel = text.getHorizontalPixel(); +// text.setHorizontalPixel(leftPixel + scrollAmount); +// } +// int lineHeight = text.getLineHeight(); +// if (pt.y < area.y + lineHeight) { +// int topPixel = text.getTopPixel(); +// text.setTopPixel(topPixel - lineHeight); +// } +// if (pt.y > area.height - lineHeight) { +// int topPixel = text.getTopPixel(); +// text.setTopPixel(topPixel + lineHeight); +// } +// scrollBeginTime = 0; +// scrollX = scrollY = -1; +// } +// } else { +// scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS; +// scrollX = pt.x; +// scrollY = pt.y; +// } +// } +// } +// +// if ((effect & DND.FEEDBACK_SELECT) != 0) { +// int[] trailing = new int [1]; +// int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false); +// newOffset += trailing [0]; +// if (newOffset != currentOffset) { +// refreshCaret(text, currentOffset, newOffset); +// currentOffset = newOffset; +// } +// } +// } +// +// void refreshCaret(StyledText text, int oldOffset, int newOffset) { +// if (oldOffset != newOffset) { +// if (oldOffset != -1) { +// Point oldPos = text.getLocationAtOffset(oldOffset); +// int oldHeight = text.getLineHeight(oldOffset); +// text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false); +// } +// if (newOffset != -1) { +// Point newPos = text.getLocationAtOffset(newOffset); +// int newHeight = text.getLineHeight(newOffset); +// text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false); +// } +// } +// } +// +// /** +// * This implementation of dropAccept provides a default drag under effect +// * for the feedback specified in event.feedback. +// * +// * For additional information see DropTargetAdapter.dropAccept. +// * +// * Subclasses that override this method should call super.dropAccept(event) +// * to get the default drag under effect implementation. +// * +// * @param event the information associated with the drop accept event +// * +// * @see DropTargetAdapter +// * @see DropTargetEvent +// */ +// @Override +// public void dropAccept(DropTargetEvent event) { +// if (currentOffset != -1) { +// StyledText text = (StyledText) getControl(); +// text.setSelection(currentOffset); +// currentOffset = -1; +// } +// } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index fa0281c2b31..53d5ac9d5c0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -15,2040 +15,2032 @@ *******************************************************************************/ package org.eclipse.swt.custom; - -import java.util.*; -import java.util.List; - -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; -import org.eclipse.swt.widgets.*; - /** * A StyledTextRenderer renders the content of a StyledText widget. * This class can be used to render to the display or to a printer. */ class StyledTextRenderer { - Device device; - StyledText styledText; - StyledTextContent content; - - /* Custom line spacing */ - StyledTextLineSpacingProvider lineSpacingProvider; - boolean lineSpacingComputing; - - /* Custom line metrics */ - private FontMetrics fixedLineMetrics; - - /* Font info */ - Font regularFont, boldFont, italicFont, boldItalicFont; - int tabWidth; - int ascent, descent; - int averageCharWidth; - int tabLength; //tab length in spaces - - /* Line data */ - int topIndex = -1; - TextLayout[] layouts; - int lineCount; - LineSizeInfo[] lineSizes; - LineInfo[] lines; - int maxWidth; - int maxWidthLineIndex; - float averageLineHeight; - int linesInAverageLineHeight; - boolean idleRunning; - - /* Bullet */ - Bullet[] bullets; - int[] bulletsIndices; - int[] redrawLines; - - /* Style data */ - int[] ranges; - int styleCount; - StyleRange[] styles; - StyleRange[] stylesSet; - int stylesSetCount = 0; - boolean hasLinks, fixedPitch; - final static int BULLET_MARGIN = 8; - - final static boolean COMPACT_STYLES = true; - final static boolean MERGE_STYLES = true; - - final static int GROW = 32; - final static int IDLE_TIME = 50; - final static int CACHE_SIZE = 300; - - final static int BACKGROUND = 1 << 0; - final static int ALIGNMENT = 1 << 1; - final static int INDENT = 1 << 2; - final static int JUSTIFY = 1 << 3; - final static int SEGMENTS = 1 << 5; - final static int TABSTOPS = 1 << 6; - final static int WRAP_INDENT = 1 << 7; - final static int SEGMENT_CHARS = 1 << 8; - final static int VERTICAL_INDENT = 1 << 9; - - static class LineSizeInfo { - - private static final int RESETED_SIZE = -1; - - /* Line size */ - int height; - int width; - - public LineSizeInfo() { - resetSize(); - } - - /** - * Reset the line size. - */ - void resetSize() { - height = RESETED_SIZE; - width = RESETED_SIZE; - } - - /** - * Returns true if the TextLayout get from the layout pool can be directly used - * or must be refreshed with styles. - * - * @return true if the TextLayout get from the layout pool can be directly used - * or must be refreshed with styles. - */ - boolean canLayout() { - return !needsRecalculateWidth(); - } - - /** - * Returns true if it needs to recalculate the line size and false - * otherwise. - * - * @return true if it needs to recalculate the line size and false - * otherwise. - */ - boolean needsRecalculateSize() { - return needsRecalculateWidth() || needsRecalculateHeight(); - } - - /** - * Returns true if it needs to recalculate the line width and false - * otherwise. - * - * @return true if it needs to recalculate the line width and false - * otherwise. - */ - boolean needsRecalculateWidth() { - return width == RESETED_SIZE; - } - - /** - * Returns true if it needs to recalculate the line height and false - * otherwise. - * - * @return true if it needs to recalculate the line height and false - * otherwise. - */ - boolean needsRecalculateHeight() { - return height == RESETED_SIZE; - } - } - - static class LineInfo { - int flags; - Color background; - int alignment; - int indent; - int wrapIndent; - boolean justify; - int[] segments; - char[] segmentsChars; - int[] tabStops; - int verticalIndent; - - public LineInfo() { - } - public LineInfo(LineInfo info) { - if (info != null) { - flags = info.flags; - background = info.background; - alignment = info.alignment; - indent = info.indent; - wrapIndent = info.wrapIndent; - justify = info.justify; - segments = info.segments; - segmentsChars = info.segmentsChars; - tabStops = info.tabStops; - verticalIndent = info.verticalIndent; - } - } - } - - private record LineDrawInfo(int index, TextLayout layout, String text, int offset, int height) { - - } - - static int cap (TextLayout layout, int offset) { - if (layout == null) return offset; - return Math.min (layout.getText().length() -1, Math.max (0, offset)); - } - -StyledTextRenderer(Device device, StyledText styledText) { - this.device = device; - this.styledText = styledText; -} -int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { - int rangeCount = styleCount << 1; - StyleRange endStyle = null; - int endStart = 0, endLength = 0; - if (modifyEnd < rangeCount) { - endStyle = styles[modifyEnd >> 1]; - endStart = ranges[modifyEnd]; - endLength = ranges[modifyEnd + 1]; - } - int grow = mergeCount - (modifyEnd - modifyStart); - if (rangeCount + grow >= ranges.length) { - int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)]; - System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart); - StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW]; - System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1); - if (rangeCount > modifyEnd) { - System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd); - System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); - } - ranges = tmpRanges; - styles = tmpStyles; - } else { - if (rangeCount > modifyEnd) { - System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd); - System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); - } - } - if (MERGE_STYLES) { - int j = modifyStart; - for (int i = 0; i < mergeCount; i += 2) { - if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) { - ranges[j - 1] += mergeRanges[i + 1]; - } else { - styles[j >> 1] = mergeStyles[i >> 1]; - ranges[j++] = mergeRanges[i]; - ranges[j++] = mergeRanges[i + 1]; - } - } - if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) { - ranges[j - 1] += endLength; - modifyEnd += 2; - mergeCount += 2; - } - if (rangeCount > modifyEnd) { - System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd); - System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1)); - } - grow = (j - modifyStart) - (modifyEnd - modifyStart); - } else { - System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount); - System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1); - } - styleCount += grow >> 1; - return grow; -} -int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { - int grow = mergeCount - (modifyEnd - modifyStart); - StyleRange endStyle = null; - if (modifyEnd < styleCount) endStyle = styles[modifyEnd]; - if (styleCount + grow >= styles.length) { - StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW]; - System.arraycopy(styles, 0, tmpStyles, 0, modifyStart); - if (styleCount > modifyEnd) { - System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd); - } - styles = tmpStyles; - } else { - if (styleCount > modifyEnd) { - System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd); - } - } - if (MERGE_STYLES) { - int j = modifyStart; - for (int i = 0; i < mergeCount; i++) { - StyleRange newStyle = mergeStyles[i], style; - if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) { - style.length += newStyle.length; - } else { - styles[j++] = newStyle; - } - } - StyleRange style = styles[j - 1]; - if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) { - style.length += endStyle.length; - modifyEnd++; - mergeCount++; - } - if (styleCount > modifyEnd) { - System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd); - } - grow = (j - modifyStart) - (modifyEnd - modifyStart); - } else { - System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount); - } - styleCount += grow; - return grow; -} -void calculate(int startLine, int lineCount) { - int endLine = startLine + lineCount; - if (startLine < 0 || endLine > lineSizes.length) { - return; - } - int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth(); - for (int i = startLine; i < endLine; i++) { - LineSizeInfo line = getLineSize(i); - if (line.needsRecalculateSize()) { - TextLayout layout = getTextLayout(i); - Rectangle rect = layout.getBounds(); - line.width = rect.width + hTrim; - line.height = rect.height; - averageLineHeight += (line.height - Math.round(averageLineHeight)) / ++linesInAverageLineHeight; - disposeTextLayout(layout); - } - if (line.width > maxWidth) { - maxWidth = line.width; - maxWidthLineIndex = i; - } - } -} -LineSizeInfo getLineSize(int i) { - if (lineSizes[i] == null) { - lineSizes[i] = new LineSizeInfo(); - } - return lineSizes[i]; -} -void calculateClientArea () { - int index = Math.max (0, styledText.getTopIndex()); - int lineCount = content.getLineCount(); - int height = styledText.getClientArea().height; - int y = 0; - /* - * There exists a possibility of ArrayIndexOutOfBounds Exception in - * below code, exact scenario not known. To avoid this exception added - * check for 'index' value, refer Bug 471192. - */ - while (height > y && lineCount > index && lineSizes.length > index) { - calculate(index, 1); - y += lineSizes[index++].height; - } -} -void calculateIdle () { - if (idleRunning) return; - Runnable runnable = new Runnable() { - @Override - public void run() { - if (styledText == null) return; - int i; - long start = System.currentTimeMillis(); - for (i = 0; i < lineCount; i++) { - LineSizeInfo line = getLineSize(i); - if (line.needsRecalculateSize()) { - calculate(i, 1); - if (System.currentTimeMillis() - start > IDLE_TIME) break; - } - } - if (i < lineCount) { - Display display = styledText.getDisplay(); - display.asyncExec(this); - } else { - idleRunning = false; - styledText.setScrollBars(true); - ScrollBar bar = styledText.getVerticalBar(); - if (bar != null) { - bar.setSelection(styledText.getVerticalScrollOffset()); - } - } - } - }; - Display display = styledText.getDisplay(); - display.asyncExec(runnable); - idleRunning = true; -} -void clearLineBackground(int startLine, int count) { - if (lines == null) return; - for (int i = startLine; i < startLine + count; i++) { - LineInfo info = lines[i]; - if (info != null) { - info.flags &= ~BACKGROUND; - info.background = null; - if (info.flags == 0) lines[i] = null; - } - } -} -void clearLineStyle(int startLine, int count) { - if (lines == null) return; - for (int i = startLine; i < startLine + count; i++) { - LineInfo info = lines[i]; - if (info != null) { - info.flags &= ~(ALIGNMENT | INDENT | VERTICAL_INDENT | WRAP_INDENT | JUSTIFY | TABSTOPS); - if (info.flags == 0) lines[i] = null; - } - } -} -void copyInto(StyledTextRenderer renderer) { - if (ranges != null) { - int[] newRanges = renderer.ranges = new int[styleCount << 1]; - System.arraycopy(ranges, 0, newRanges, 0, newRanges.length); - } - if (styles != null) { - StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount]; - for (int i = 0; i < newStyles.length; i++) { - newStyles[i] = (StyleRange)styles[i].clone(); - } - renderer.styleCount = styleCount; - } - if (lines != null) { - LineInfo[] newLines = renderer.lines = new LineInfo[lineCount]; - for (int i = 0; i < newLines.length; i++) { - newLines[i] = new LineInfo(lines[i]); - } - renderer.lineCount = lineCount; - } -} -void dispose() { - if (boldFont != null) boldFont.dispose(); - if (italicFont != null) italicFont.dispose(); - if (boldItalicFont != null) boldItalicFont.dispose(); - boldFont = italicFont = boldItalicFont = null; - reset(); - content = null; - device = null; - styledText = null; -} -void disposeTextLayout (TextLayout layout) { - if (layouts != null) { - for (TextLayout l : layouts) { - if (l == layout) return; - } - } - layout.dispose(); -} -void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) { - StyleRange style = bullet.style; - GlyphMetrics metrics = style.metrics; - Color color = style.foreground; - if (color != null) gc.setForeground(color); - Font font = style.font; - if (font != null) gc.setFont(font); - String string = ""; - int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER); - switch (type) { - case ST.BULLET_DOT: string = "\u2022"; break; - case ST.BULLET_NUMBER: string = String.valueOf(index + 1); break; - case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break; - case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break; - } - if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text; - Display display = styledText.getDisplay(); - TextLayout layout = new TextLayout(display); - layout.setText(string); - layout.setAscent(lineAscent); - layout.setDescent(lineDescent); - style = (StyleRange)style.clone(); - style.metrics = null; - if (style.font == null) style.font = getFont(style.fontStyle); - layout.setStyle(style, 0, string.length()); - int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN); - layout.draw(gc, x, paintY); - layout.dispose(); -} - -/** - * Caches draw-related info that may be expensive to calculate twice when - * drawing first background and then foreground. - */ -private LineDrawInfo makeLineDrawInfo(int lineIndex) { - TextLayout layout = getTextLayout(lineIndex); - String text = content.getLine(lineIndex); - int offset = content.getOffsetAtLine(lineIndex); - int height = layout.getBounds().height; - return new LineDrawInfo(lineIndex, layout, text, offset, height); -} - -int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, Color widgetBackground, Color widgetForeground) { - // When fixed line metrics is in effect, tall unicode characters - // will not always fit line's height. In this case, they will - // draw out of line's bounds. To prevent them from being clipped - // by next line's background, paint entire background before any - // foreground. - // I considered to make this mode default, but was worried about - // potential regressions in various legacy code. For example, it - // could change something about line heights/colors during - // painting. While this doesn't sound like a good thing to do, yet - // still, I'd rather stay safe. - final boolean drawBackBeforeFore = (fixedLineMetrics != null); - - if (drawBackBeforeFore) { - // Cache drawing information - final List drawInfos = new ArrayList<>(); - int y = begY; - for (int iLine = startLine; y < endY && iLine < endLine; iLine++) { - LineDrawInfo lineInfo = makeLineDrawInfo(iLine); - drawInfos.add(lineInfo); - y += lineInfo.height; - } - - // Draw background - y = begY; - for (LineDrawInfo lineInfo : drawInfos) { - drawLineBackground(lineInfo, y, gc, widgetBackground); - y += lineInfo.height; - } - - // Draw foreground - y = begY; - for (LineDrawInfo lineInfo : drawInfos) { - drawLineForeground(lineInfo, begX, y, gc, widgetForeground); - y += lineInfo.height; - } - - // cleanup - for (LineDrawInfo lineInfo : drawInfos) { - disposeTextLayout(lineInfo.layout); - } - - return y - begY; - } - - int y = begY; - for (int iLine = startLine; y < endY && iLine < endLine; iLine++) { - LineDrawInfo lineInfo = makeLineDrawInfo(iLine); - drawLineBackground(lineInfo, y, gc, widgetBackground); - drawLineForeground(lineInfo, begX, y, gc, widgetForeground); - disposeTextLayout(lineInfo.layout); - y += lineInfo.height; - } - return y - begY; -} - -private void drawLineBackground(LineDrawInfo lineInfo, int paintY, GC gc, Color widgetBackground) { - Rectangle client = styledText.getClientArea(); - Color lineBackground = getLineBackground(lineInfo.index, null); - StyledTextEvent event = styledText.getLineBackgroundData(lineInfo.offset, lineInfo.text); - if (event != null && event.lineBackground != null) lineBackground = event.lineBackground; - int verticalIndent = lineInfo.layout.getVerticalIndent(); - - if (lineBackground != null) { - if (verticalIndent > 0) { - gc.setBackground(widgetBackground); - gc.fillRectangle(client.x, paintY, client.width, verticalIndent); - } - gc.setBackground(lineBackground); - gc.fillRectangle(client.x, paintY + verticalIndent, client.width, lineInfo.height - verticalIndent); - } else { - gc.setBackground(widgetBackground); - styledText.drawBackground(gc, client.x, paintY, client.width, lineInfo.height); - } -} - -private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground) { - int lineLength = lineInfo.text.length(); - gc.setForeground(widgetForeground); - Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength); - if (styledText.getBlockSelection() || selection.length == 0) { - lineInfo.layout.draw(gc, paintX, paintY); - } else { - Color selectionFg = styledText.getSelectionForeground(); - Color selectionBg = styledText.getSelectionBackground(); - final int baseFlags = (styledText.getStyle() & SWT.FULL_SELECTION) != 0 ? SWT.FULL_SELECTION : SWT.DELIMITER_SELECTION; - for (Point relativeSelection : selection) { - int start = Math.max(0, relativeSelection.x); - int end = Math.min(lineLength, relativeSelection.y); - int flags = baseFlags; - if (relativeSelection.x <= lineLength && lineLength < relativeSelection.y ) { - flags |= SWT.LAST_LINE_SELECTION; - } - // TODO calling draw multiple times here prints line multiple times, overriding some colors - lineInfo.layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags); - } - } - - // draw objects - Bullet bullet = null; - int bulletIndex = -1; - if (bullets != null) { - if (bulletsIndices != null) { - int index = lineInfo.index - topIndex; - if (0 <= index && index < CACHE_SIZE) { - bullet = bullets[index]; - bulletIndex = bulletsIndices[index]; - } - } else { - for (Bullet b : bullets) { - bullet = b; - bulletIndex = bullet.indexOf(lineInfo.index); - if (bulletIndex != -1) break; - } - } - } - if (bulletIndex != -1 && bullet != null) { - FontMetrics metrics = lineInfo.layout.getLineMetrics(0); - int lineAscent = metrics.getAscent() + metrics.getLeading(); - if (bullet.type == ST.BULLET_CUSTOM) { - bullet.style.start = lineInfo.offset; - styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex); - } else { - drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent()); - } - } - TextStyle[] styles = lineInfo.layout.getStyles(); - int[] ranges = null; - for (int i = 0; i < styles.length; i++) { - if (styles[i].metrics != null) { - if (ranges == null) ranges = lineInfo.layout.getRanges(); - int start = ranges[i << 1]; - int length = ranges[(i << 1) + 1] - start + 1; - Point point = lineInfo.layout.getLocation(start, false); - FontMetrics metrics = lineInfo.layout.getLineMetrics(lineInfo.layout.getLineIndex(start)); - StyleRange style = (StyleRange)((StyleRange)styles[i]).clone(); - style.start = start + lineInfo.offset; - style.length = length; - int lineAscent = metrics.getAscent() + metrics.getLeading(); - styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0); - } - } -} - -private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset) { - int[] selectionRanges = styledText.getSelectionRanges(); - int lineLength = toOffset - fromOffset; - List res = new ArrayList<>(); - for (int i = 0; i < selectionRanges.length; i += 2) { - // ranges are assumed to be sorted by start offset, then (positive)length or higher end offset - Point relativeSelection = new Point(selectionRanges[i] - fromOffset, selectionRanges[i] + selectionRanges[i + 1] - fromOffset); - if (relativeSelection.x != relativeSelection.y && - relativeSelection.x <= lineLength && relativeSelection.y >= 0) { - res.add(relativeSelection); - } - } - return res.toArray(new Point[res.size()]); -} - -int getBaseline() { - return ascent; -} -int getCachedLineHeight(int lineIndex) { - return getLineHeight(lineIndex, false); -} -Font getFont(int style) { - switch (style) { - case SWT.BOLD: - if (boldFont != null) return boldFont; - return boldFont = new Font(device, getFontData(style)); - case SWT.ITALIC: - if (italicFont != null) return italicFont; - return italicFont = new Font(device, getFontData(style)); - case SWT.BOLD | SWT.ITALIC: - if (boldItalicFont != null) return boldItalicFont; - return boldItalicFont = new Font(device, getFontData(style)); - default: - return regularFont; - } -} -FontData[] getFontData(int style) { - FontData[] fontDatas = regularFont.getFontData(); - for (FontData fontData : fontDatas) { - fontData.setStyle(style); - } - return fontDatas; -} -int getHeight () { - int defaultLineHeight = getLineHeight(); - if (styledText.isFixedLineHeight()) { - return lineCount * defaultLineHeight + styledText.topMargin + styledText.bottomMargin; - } - int totalHeight = 0; - int width = styledText.getWrapWidth(); - for (int i = 0; i < lineCount; i++) { - LineSizeInfo line = getLineSize(i); - int height = line.height; - if (line.needsRecalculateHeight()) { - if (width > 0) { - int length = content.getLine(i).length(); - height = ((length * averageCharWidth / width) + 1) * defaultLineHeight; - } else { - height = defaultLineHeight; - } - } - totalHeight += height; - } - return totalHeight + styledText.topMargin + styledText.bottomMargin; -} -boolean hasLink(int offset) { - if (offset == -1) return false; - int lineIndex = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(lineIndex); - String line = content.getLine(lineIndex); - StyledTextEvent event = styledText.getLineStyleData(lineOffset, line); - if (event != null) { - StyleRange[] styles = event.styles; - if (styles != null) { - int[] ranges = event.ranges; - if (ranges != null) { - for (int i = 0; i < ranges.length; i+=2) { - if (ranges[i] <= offset && offset < ranges[i] + ranges[i+1] && styles[i >> 1].underline && styles[i >> 1].underlineStyle == SWT.UNDERLINE_LINK) { - return true; - } - } - } else { - for (StyleRange style : styles) { - if (style.start <= offset && offset < style.start + style.length && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) { - return true; - } - } - } - } - } else { - if (ranges != null) { - int rangeCount = styleCount << 1; - int index = getRangeIndex(offset, -1, rangeCount); - if (index >= rangeCount) return false; - int rangeStart = ranges[index]; - int rangeLength = ranges[index + 1]; - StyleRange rangeStyle = styles[index >> 1]; - if (rangeStart <= offset && offset < rangeStart + rangeLength && rangeStyle.underline && rangeStyle.underlineStyle == SWT.UNDERLINE_LINK) { - return true; - } - } - } - return false; -} -int getLineAlignment(int index, int defaultAlignment) { - if (lines == null) return defaultAlignment; - LineInfo info = lines[index]; - if (info != null && (info.flags & ALIGNMENT) != 0) { - return info.alignment; - } - return defaultAlignment; -} -Color getLineBackground(int index, Color defaultBackground) { - if (lines == null) return defaultBackground; - LineInfo info = lines[index]; - if (info != null && (info.flags & BACKGROUND) != 0) { - return info.background; - } - return defaultBackground; -} -Bullet getLineBullet (int index, Bullet defaultBullet) { - if (bullets == null) return defaultBullet; - if (bulletsIndices != null) return defaultBullet; - for (Bullet bullet : bullets) { - if (bullet.indexOf(index) != -1) return bullet; - } - return defaultBullet; -} -int getLineHeight() { - return ascent + descent; -} -int getLineHeight(int lineIndex) { - return getLineHeight(lineIndex, true); -} -int getLineHeight(int lineIndex, boolean exact) { - LineSizeInfo line = getLineSize(lineIndex); - if (line.needsRecalculateHeight()) { - // here we are in "variable line height", the call of calculate which uses TextLayout is very slow - // so use the average line height of all calculated lines when many heights are needed e.g. for scrolling. - if (isVariableHeight(lineIndex)) { - if (exact) { - calculate(lineIndex, 1); - } else { - return Math.round(averageLineHeight); - } - } else { - line.height = getLineHeight() + getLineSpacing(lineIndex) + getLineVerticalIndent(lineIndex); - } - } - return line.height; -} -/** - * Returns true if the given line can use the default line height and false - * otherwise. - * - * @param lineIndex - * line index - * @return true if the given line can use the default line height and false - * otherwise. - */ -private boolean isVariableHeight(int lineIndex) { - if (styledText.isWordWrap()) { - // In word wrap mode, the line height must be recomputed with TextLayout - return true; - } - StyleRange[] styles = getStylesForLine(lineIndex); - if (styles != null) { - for (StyleRange style : styles) { - if (style.isVariableHeight()) { - // style is variable height - return true; - } - } - } - return false; -} -/** - * returns true if the given line index defines custom line spacing and false - * otherwise. - * - * @param lineIndex - * the line index. - * @return true if the given line index defines custom line spacing and false - * otherwise. - */ -private int getLineSpacing(int lineIndex) { - if (styledText.lineSpacing > 0) { - return styledText.lineSpacing; - } else if (lineSpacingProvider != null) { - Integer lineSpacing = lineSpacingProvider.getLineSpacing(lineIndex); - if (lineSpacing != null) { - return lineSpacing; - } - } - return 0; -} -/** - * Returns styles range for the given line index and null otherwise. - * - * @param lineIndex - * the line index. - * @return styles range for the given line index and null otherwise. - */ -private StyleRange[] getStylesForLine(int lineIndex) { - int start = styledText.getOffsetAtLine(lineIndex); - int length = styledText.getLine(lineIndex).length(); - return getStyleRanges(start, length, false); -} -int getLineIndent(int index, int defaultIndent) { - if (lines == null) return defaultIndent; - LineInfo info = lines[index]; - if (info != null && (info.flags & INDENT) != 0) { - return info.indent; - } - return defaultIndent; -} -int getLineVerticalIndent(int index) { - if (lines == null) return 0; - LineInfo info = lines[index]; - if (info != null && (info.flags & VERTICAL_INDENT) != 0) { - return info.verticalIndent; - } - return 0; -} -int getLineWrapIndent(int index, int defaultWrapIndent) { - if (lines == null) return defaultWrapIndent; - LineInfo info = lines[index]; - if (info != null && (info.flags & WRAP_INDENT) != 0) { - return info.wrapIndent; - } - return defaultWrapIndent; -} -boolean getLineJustify(int index, boolean defaultJustify) { - if (lines == null) return defaultJustify; - LineInfo info = lines[index]; - if (info != null && (info.flags & JUSTIFY) != 0) { - return info.justify; - } - return defaultJustify; -} -int[] getLineTabStops(int index, int[] defaultTabStops) { - if (lines == null) return defaultTabStops; - LineInfo info = lines[index]; - if (info != null && (info.flags & TABSTOPS) != 0) { - return info.tabStops; - } - return defaultTabStops; -} -StyledTextLineSpacingProvider getLineSpacingProvider() { - return lineSpacingProvider; -} -int getRangeIndex(int offset, int low, int high) { - if (styleCount == 0) return 0; - if (ranges != null) { - while (high - low > 2) { - int index = ((high + low) / 2) / 2 * 2; - int end = ranges[index] + ranges[index + 1]; - if (end > offset) { - high = index; - } else { - low = index; - } - } - } else { - while (high - low > 1) { - int index = ((high + low) / 2); - int end = styles[index].start + styles[index].length; - if (end > offset) { - high = index; - } else { - low = index; - } - } - } - return high; -} -int[] getRanges(int start, int length) { - if (length == 0) return null; - int[] newRanges; - int end = start + length - 1; - if (ranges != null) { - int rangeCount = styleCount << 1; - int rangeStart = getRangeIndex(start, -1, rangeCount); - if (rangeStart >= rangeCount) return null; - if (ranges[rangeStart] > end) return null; - int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount)); - if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2); - newRanges = new int[rangeEnd - rangeStart + 2]; - System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length); - } else { - int rangeStart = getRangeIndex(start, -1, styleCount); - if (rangeStart >= styleCount) return null; - if (styles[rangeStart].start > end) return null; - int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); - if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1); - newRanges = new int[(rangeEnd - rangeStart + 1) << 1]; - for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) { - StyleRange style = styles[i]; - newRanges[j] = style.start; - newRanges[j + 1] = style.length; - } - } - if (start > newRanges[0]) { - newRanges[1] = newRanges[0] + newRanges[1] - start; - newRanges[0] = start; - } - if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) { - newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1; - } - return newRanges; -} -StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { - if (length == 0) return null; - StyleRange[] newStyles; - int end = start + length - 1; - if (ranges != null) { - int rangeCount = styleCount << 1; - int rangeStart = getRangeIndex(start, -1, rangeCount); - if (rangeStart >= rangeCount) return null; - if (ranges[rangeStart] > end) return null; - int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount)); - if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2); - newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1]; - if (includeRanges) { - for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) { - newStyles[j] = (StyleRange)styles[i >> 1].clone(); - newStyles[j].start = ranges[i]; - newStyles[j].length = ranges[i + 1]; - } - } else { - System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length); - } - } else { - int rangeStart = getRangeIndex(start, -1, styleCount); - if (rangeStart >= styleCount) return null; - if (styles[rangeStart].start > end) return null; - int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); - if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1); - newStyles = new StyleRange[rangeEnd - rangeStart + 1]; - System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length); - } - if (includeRanges || ranges == null) { - StyleRange style = newStyles[0]; - if (start > style.start) { - newStyles[0] = style = (StyleRange)style.clone(); - style.length = style.start + style.length - start; - style.start = start; - } - style = newStyles[newStyles.length - 1]; - if (end < style.start + style.length - 1) { - newStyles[newStyles.length - 1] = style = (StyleRange)style.clone(); - style.length = end - style.start + 1; - } - } - return newStyles; -} -StyleRange getStyleRange(StyleRange style) { - if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) hasLinks = true; - if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style; - StyleRange clone = (StyleRange)style.clone(); - clone.start = clone.length = 0; - clone.fontStyle = SWT.NORMAL; - if (clone.font == null) clone.font = getFont(style.fontStyle); - return clone; -} -TextLayout getTextLayout(int lineIndex) { - if (lineSpacingProvider == null) { - return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing); - } - // Compute line spacing for the given line index. - int newLineSpacing = styledText.lineSpacing; - Integer spacing = lineSpacingProvider.getLineSpacing(lineIndex); - if (spacing != null && spacing.intValue() >= 0) { - newLineSpacing = spacing; - } - // Check if line spacing has not changed - if (isSameLineSpacing(lineIndex, newLineSpacing)) { - return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), newLineSpacing); - } - // Get text layout with original StyledText line spacing. - TextLayout layout = getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), - styledText.lineSpacing); - if (layout.getSpacing() != newLineSpacing) { - layout.setSpacing(newLineSpacing); - if (lineSpacingComputing) { - return layout; - } - try { - /* Call of resetCache, setCaretLocation, redraw call getTextLayout method - * To avoid having stack overflow, lineSpacingComputing flag is used to call - * resetCache, setCaretLocation, redraw methods only at the end of the compute of all lines spacing. - */ - lineSpacingComputing = true; - styledText.resetCache(lineIndex, 1); - styledText.setCaretLocations(); - styledText.redraw(); - } finally { - lineSpacingComputing = false; - } - } - return layout; -} -boolean isSameLineSpacing(int lineIndex, int newLineSpacing) { - if (layouts == null) { - return false; - } - int layoutIndex = lineIndex - topIndex; - if (0 <= layoutIndex && layoutIndex < layouts.length) { - TextLayout layout = layouts[layoutIndex]; - return layout != null && !layout.isDisposed() && layout.getSpacing() == newLineSpacing; - } - return false; -} - -private static final class StyleEntry { - public final int start; - public final int end; - public final TextStyle style; - - public StyleEntry(TextStyle style, int start, int end) { - this.style = style; - this.start = start; - this.end = end; - } -} - -TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) { - TextLayout layout = null; - if (styledText != null) { - int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0; - if (layouts == null || topIndex != this.topIndex) { - TextLayout[] newLayouts = new TextLayout[CACHE_SIZE]; - if (layouts != null) { - for (int i = 0; i < layouts.length; i++) { - if (layouts[i] != null) { - int layoutIndex = (i + this.topIndex) - topIndex; - if (0 <= layoutIndex && layoutIndex < newLayouts.length) { - newLayouts[layoutIndex] = layouts[i]; - } else { - layouts[i].dispose(); - } - } - } - } - if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) { - int delta = topIndex - this.topIndex; - if (delta > 0) { - if (delta < bullets.length) { - System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta); - System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta); - } - int startIndex = Math.max(0, bullets.length - delta); - for (int i = startIndex; i < bullets.length; i++) bullets[i] = null; - } else { - if (-delta < bullets.length) { - System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta); - System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta); - } - int endIndex = Math.min(bullets.length, -delta); - for (int i = 0; i < endIndex; i++) bullets[i] = null; - } - } - this.topIndex = topIndex; - layouts = newLayouts; - } - if (layouts != null) { - int layoutIndex = lineIndex - topIndex; - if (0 <= layoutIndex && layoutIndex < layouts.length) { - layout = layouts[layoutIndex]; - if (layout != null) { - // Bug 520374: lineIndex can be >= linesSize.length - if(lineIndex < lineSizes.length && getLineSize(lineIndex).canLayout()) { - return layout; - } - } else { - layout = layouts[layoutIndex] = new TextLayout(device); - } - } - } - } - if (layout == null) layout = new TextLayout(device); - String line = content.getLine(lineIndex); - int lineOffset = content.getOffsetAtLine(lineIndex); - int[] segments = null; - char[] segmentChars = null; - int indent = 0; - int wrapIndent = 0; - int verticalIndent = 0; - int alignment = SWT.LEFT; - int textDirection = orientation; - boolean justify = false; - int[] tabs = {tabWidth}; - Bullet bullet = null; - int[] ranges = null; - StyleRange[] styles = null; - int rangeStart = 0, styleCount = 0; - StyledTextEvent event = null; - if (styledText != null) { - event = styledText.getBidiSegments(lineOffset, line); - if (event != null) { - segments = event.segments; - segmentChars = event.segmentsChars; - } - event = styledText.getLineStyleData(lineOffset, line); - indent = styledText.indent; - wrapIndent = styledText.wrapIndent; - alignment = styledText.alignment; - if (styledText.isAutoDirection()) { - textDirection = SWT.AUTO_TEXT_DIRECTION; - } else if ((styledText.getStyle() & SWT.FLIP_TEXT_DIRECTION) != 0) { - textDirection = orientation == SWT.RIGHT_TO_LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT; - } - justify = styledText.justify; - if (styledText.tabs != null) tabs = styledText.tabs; - } - if (event != null) { - indent = event.indent; - verticalIndent = event.verticalIndent; - wrapIndent = event.wrapIndent; - alignment = event.alignment; - justify = event.justify; - bullet = event.bullet; - ranges = event.ranges; - styles = event.styles; - if (event.tabStops != null) tabs = event.tabStops; - if (styles != null) { - styleCount = styles.length; - if (styledText.isFixedLineHeight()) { - for (int i = 0; i < styleCount; i++) { - if (styles[i].isVariableHeight()) { - styledText.hasStyleWithVariableHeight = true; - styledText.verticalScrollOffset = -1; - styledText.redraw(); - break; - } - } - } - } - if (bullets == null || bulletsIndices == null) { - bullets = new Bullet[CACHE_SIZE]; - bulletsIndices = new int[CACHE_SIZE]; - } - int index = lineIndex - topIndex; - if (0 <= index && index < CACHE_SIZE) { - bullets[index] = bullet; - bulletsIndices[index] = event.bulletIndex; - } - } else { - if (lines != null) { - LineInfo info = lines[lineIndex]; - if (info != null) { - if ((info.flags & INDENT) != 0) indent = info.indent; - if ((info.flags & VERTICAL_INDENT) != 0) verticalIndent = info.verticalIndent; - if ((info.flags & WRAP_INDENT) != 0) wrapIndent = info.wrapIndent; - if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment; - if ((info.flags & JUSTIFY) != 0) justify = info.justify; - if ((info.flags & SEGMENTS) != 0) segments = info.segments; - if ((info.flags & SEGMENT_CHARS) != 0) segmentChars = info.segmentsChars; - if ((info.flags & TABSTOPS) != 0) tabs = info.tabStops; - } - } - if (bulletsIndices != null) { - bullets = null; - bulletsIndices = null; - } - if (bullets != null) { - for (Bullet b : bullets) { - if (b.indexOf(lineIndex) != -1) { - bullet = b; - break; - } - } - } - ranges = this.ranges; - styles = this.styles; - styleCount = this.styleCount; - if (ranges != null) { - rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1); - } else { - rangeStart = getRangeIndex(lineOffset, -1, styleCount); - } - } - if (bullet != null) { - StyleRange style = bullet.style; - GlyphMetrics metrics = style.metrics; - indent += metrics.width; - } - - // prepare styles, as it may change the line content, do it before calling layout.setText() - // This needs to happen early to handle the case of GlyphMetrics on \t. - // The root cause is that TextLayout doesn't return the right value for the bounds when - // GlyphMetrics are applied on \t. A better fix could be implemented directly in (all 3) - // TextLayout classes. - List styleEntries = new ArrayList<>(); - int lastOffset = 0; - int length = line.length(); - if (styles != null) { - if (ranges != null) { - int rangeCount = styleCount << 1; - for (int i = rangeStart; i < rangeCount; i += 2) { - int start, end; - if (lineOffset > ranges[i]) { - start = 0; - end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]); - } else { - start = ranges[i] - lineOffset; - end = Math.min(length, start + ranges[i + 1]); - } - if (start >= length) break; - if (lastOffset < start) { - styleEntries.add(new StyleEntry(null, lastOffset, start - 1)); - } - TextStyle style = getStyleRange(styles[i >> 1]); - int endIndex = Math.max(start, Math.min(length, end + 1)); - if (style.metrics != null && line.substring(start, endIndex).contains("\t")) { - line = - line.substring(0, start) + - line.substring(start, endIndex).replace('\t', ' ') + - (end < line.length() ? line.substring(end + 1, line.length()) : ""); - } - styleEntries.add(new StyleEntry(style, start, end)); - lastOffset = Math.max(lastOffset, end); - } - } else { - for (int i = rangeStart; i < styleCount; i++) { - int start, end; - if (lineOffset > styles[i].start) { - start = 0; - end = Math.min (length, styles[i].length - lineOffset + styles[i].start); - } else { - start = styles[i].start - lineOffset; - end = Math.min(length, start + styles[i].length); - } - if (start >= length) break; - if (lastOffset < start) { - styleEntries.add(new StyleEntry(null, lastOffset, start - 1)); - } - TextStyle style = getStyleRange(styles[i]); - int endIndex = Math.max(start, Math.min(length, end + 1)); - if (style.metrics != null && line.substring(start, endIndex).contains("\t")) { - line = - line.substring(0, start) + - line.substring(start, endIndex).replace('\t', ' ') + - (end < line.length() ? line.substring(end + 1, line.length()) : ""); - } - styleEntries.add(new StyleEntry(style, start, end)); - lastOffset = Math.max(lastOffset, end); - } - } - } - if (lastOffset < length) styleEntries.add(new StyleEntry(null, lastOffset, length)); - - layout.setFont(regularFont); - layout.setAscent(ascent); - layout.setDescent(descent); - layout.setFixedLineMetrics(fixedLineMetrics); - layout.setText(line); - layout.setOrientation(orientation); - layout.setSegments(segments); - layout.setSegmentsChars(segmentChars); - layout.setWidth(width); - layout.setSpacing(lineSpacing); - layout.setTabs(tabs); - layout.setDefaultTabWidth(tabLength); - layout.setIndent(indent); - layout.setVerticalIndent(verticalIndent); - layout.setWrapIndent(wrapIndent); - layout.setAlignment(alignment); - layout.setJustify(justify); - layout.setTextDirection(textDirection); - // apply styles, must be done after layout.setText() - for (StyleEntry styleEntry : styleEntries) { - layout.setStyle(styleEntry.style, styleEntry.start, styleEntry.end); - } - - if (styledText != null && styledText.ime != null) { - IME ime = styledText.ime; - int compositionOffset = ime.getCompositionOffset(); - if (compositionOffset != -1 && compositionOffset <= content.getCharCount()) { - int commitCount = ime.getCommitCount(); - int compositionLength = ime.getText().length(); - if (compositionLength != commitCount) { - int compositionLine = content.getLineAtOffset(compositionOffset); - if (compositionLine == lineIndex) { - int[] imeRanges = ime.getRanges(); - TextStyle[] imeStyles = ime.getStyles(); - if (imeRanges.length > 0) { - for (int i = 0; i < imeStyles.length; i++) { - int start = imeRanges[i*2] - lineOffset; - int end = imeRanges[i*2+1] - lineOffset; - TextStyle imeStyle = imeStyles[i], userStyle; - for (int j = start; j <= end; j++) { - if (!(0 <= j && j < length)) break; - userStyle = layout.getStyle(cap(layout, j)); - if (userStyle == null && j > 0) userStyle = layout.getStyle(cap(layout, j - 1)); - if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(cap(layout, j + 1)); - if (userStyle == null) { - layout.setStyle(imeStyle, j, j); - } else { - TextStyle newStyle = new TextStyle(imeStyle); - if (newStyle.font == null) newStyle.font = userStyle.font; - if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground; - if (newStyle.background == null) newStyle.background = userStyle.background; - layout.setStyle(newStyle, j, j); - } - } - } - } else { - int start = compositionOffset - lineOffset; - int end = start + compositionLength - 1; - TextStyle userStyle = layout.getStyle(cap(layout, start)); - if (userStyle == null) { - if (start > 0) userStyle = layout.getStyle(cap(layout, start - 1)); - if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(cap(layout, end + 1)); - if (userStyle != null) { - TextStyle newStyle = new TextStyle(); - newStyle.font = userStyle.font; - newStyle.foreground = userStyle.foreground; - newStyle.background = userStyle.background; - layout.setStyle(newStyle, start, end); - } - } - } - } - } - } - } - - if (styledText != null && styledText.isFixedLineHeight()) { - int index = -1; - int lineCount = layout.getLineCount(); - int height = getLineHeight(); - for (int i = 0; i < lineCount; i++) { - int lineHeight = layout.getLineBounds(i).height; - if (lineHeight > height) { - height = lineHeight; - index = i; - } - } - if (index != -1) { - FontMetrics metrics = layout.getLineMetrics(index); - ascent = metrics.getAscent() + metrics.getLeading(); - descent = metrics.getDescent(); - if (layouts != null) { - for (TextLayout l : layouts) { - if (l != null && l != layout) { - l.setAscent(ascent); - l.setDescent(descent); - } - } - } - styledText.calculateScrollBars(); - if (styledText.verticalScrollOffset != 0) { - int topIndex = styledText.topIndex; - int topIndexY = styledText.topIndexY; - int lineHeight = getLineHeight(); - int newVerticalScrollOffset; - if (topIndexY >= 0) { - newVerticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY; - } else { - newVerticalScrollOffset = topIndex * lineHeight - topIndexY; - } - styledText.scrollVertical(newVerticalScrollOffset - styledText.verticalScrollOffset, true); - } - if (styledText.isBidiCaret()) styledText.createCaretBitmaps(); - styledText.caretDirection = SWT.NULL; - styledText.setCaretLocations(); - styledText.redraw(); - } - } - return layout; -} -int getWidth() { - return maxWidth; -} -void reset() { - if (layouts != null) { - for (TextLayout layout : layouts) { - if (layout != null) layout.dispose(); - } - layouts = null; - } - topIndex = -1; - stylesSetCount = styleCount = lineCount = 0; - ranges = null; - styles = null; - stylesSet = null; - lines = null; - lineSizes = null; - bullets = null; - bulletsIndices = null; - redrawLines = null; - hasLinks = false; -} -void reset(int startLine, int lineCount) { - int endLine = startLine + lineCount; - if (startLine < 0 || endLine > lineSizes.length) return; - SortedSet lines = new TreeSet<>(); - for (int i = startLine; i < endLine; i++) { - lines.add(Integer.valueOf(i)); - } - reset(lines); -} -void reset(Set lines) { - if (lines == null || lines.isEmpty()) return; - int resetLineCount = 0; - for (Integer line : lines) { - if (line >= 0 || line < lineCount) { - resetLineCount++; - getLineSize(line.intValue()).resetSize(); - } - } - if (linesInAverageLineHeight > resetLineCount) { - linesInAverageLineHeight -= resetLineCount; - } else { - linesInAverageLineHeight = 0; - averageLineHeight = 0.0f; - } - if (lines.contains(Integer.valueOf(maxWidthLineIndex))) { - maxWidth = 0; - maxWidthLineIndex = -1; - if (resetLineCount != this.lineCount) { - for (int i = 0; i < this.lineCount; i++) { - LineSizeInfo lineSize = getLineSize(i); - if (lineSize.width > maxWidth) { - maxWidth = lineSize.width; - maxWidthLineIndex = i; - } - } - } - } -} -void setContent(StyledTextContent content) { - reset(); - this.content = content; - lineCount = content.getLineCount(); - lineSizes = new LineSizeInfo[lineCount]; - maxWidth = 0; - maxWidthLineIndex = -1; - reset(0, lineCount); -} - -/** - * See {@link TextLayout#setFixedLineMetrics} - * - * @since 3.125 - */ -public void setFixedLineMetrics(FontMetrics metrics) { - fixedLineMetrics = metrics; -} - -void setFont(Font font, int tabs) { - TextLayout layout = new TextLayout(device); - layout.setFont(regularFont); - tabLength = tabs; - if (font != null) { - if (boldFont != null) boldFont.dispose(); - if (italicFont != null) italicFont.dispose(); - if (boldItalicFont != null) boldItalicFont.dispose(); - boldFont = italicFont = boldItalicFont = null; - regularFont = font; - layout.setText(" "); - layout.setFont(font); - layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0); - layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1); - layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2); - layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3); - FontMetrics metrics = layout.getLineMetrics(0); - ascent = metrics.getAscent() + metrics.getLeading(); - descent = metrics.getDescent(); - boldFont.dispose(); - italicFont.dispose(); - boldItalicFont.dispose(); - boldFont = italicFont = boldItalicFont = null; - } - layout.dispose(); - layout = new TextLayout(device); - layout.setFont(regularFont); - StringBuilder tabBuffer = new StringBuilder(tabs); - for (int i = 0; i < tabs; i++) { - tabBuffer.append(' '); - } - layout.setText(tabBuffer.toString()); - tabWidth = layout.getBounds().width; - layout.dispose(); - if (styledText != null) { - GC gc = new GC(styledText); - averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth(); - fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$ - gc.dispose(); - } -} -void setLineAlignment(int startLine, int count, int alignment) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= ALIGNMENT; - lines[i].alignment = alignment; - } -} -void setLineBackground(int startLine, int count, Color background) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= BACKGROUND; - lines[i].background = background; - } -} -void setLineBullet(int startLine, int count, Bullet bullet) { - if (bulletsIndices != null) { - bulletsIndices = null; - bullets = null; - } - if (bullets == null) { - if (bullet == null) return; - bullets = new Bullet[1]; - bullets[0] = bullet; - } - int index = 0; - while (index < bullets.length) { - if (bullet == bullets[index]) break; - index++; - } - if (bullet != null) { - if (index == bullets.length) { - Bullet[] newBulletsList = new Bullet[bullets.length + 1]; - System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length); - newBulletsList[index] = bullet; - bullets = newBulletsList; - } - bullet.addIndices(startLine, count); - } else { - updateBullets(startLine, count, 0, false); - styledText.redrawLinesBullet(redrawLines); - redrawLines = null; - } -} -void setLineIndent(int startLine, int count, int indent) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= INDENT; - lines[i].indent = indent; - } -} -void setLineVerticalIndent(int lineIndex, int verticalLineIndent) { - if (lines == null) - lines = new LineInfo[lineCount]; - if (lines[lineIndex] == null) { - lines[lineIndex] = new LineInfo(); - } - lines[lineIndex].flags |= VERTICAL_INDENT; - int delta = verticalLineIndent - lines[lineIndex].verticalIndent; - lines[lineIndex].verticalIndent = verticalLineIndent; - LineSizeInfo info = getLineSize(lineIndex); - if (!info.needsRecalculateHeight()) { - info.height += delta; - } -} -void setLineWrapIndent(int startLine, int count, int wrapIndent) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= WRAP_INDENT; - lines[i].wrapIndent = wrapIndent; - } -} -void setLineJustify(int startLine, int count, boolean justify) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= JUSTIFY; - lines[i].justify = justify; - } -} -void setLineSegments(int startLine, int count, int[] segments) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= SEGMENTS; - lines[i].segments = segments; - } -} -void setLineSegmentChars(int startLine, int count, char[] segmentChars) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= SEGMENT_CHARS; - lines[i].segmentsChars = segmentChars; - } -} -void setLineTabStops(int startLine, int count, int[] tabStops) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); - } - lines[i].flags |= TABSTOPS; - lines[i].tabStops = tabStops; - } -} -void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) { - this.lineSpacingProvider = lineSpacingProvider; -} -void setStyleRanges (int[] newRanges, StyleRange[] newStyles) { - if (newStyles == null) { - stylesSetCount = styleCount = 0; - ranges = null; - styles = null; - stylesSet = null; - hasLinks = false; - return; - } - if (newRanges == null && COMPACT_STYLES) { - newRanges = new int[newStyles.length << 1]; - StyleRange[] tmpStyles = new StyleRange[newStyles.length]; - if (stylesSet == null) stylesSet = new StyleRange[4]; - for (int i = 0, j = 0; i < newStyles.length; i++) { - StyleRange newStyle = newStyles[i]; - newRanges[j++] = newStyle.start; - newRanges[j++] = newStyle.length; - int index = 0; - while (index < stylesSetCount) { - if (stylesSet[index].similarTo(newStyle)) break; - index++; - } - if (index == stylesSetCount) { - if (stylesSetCount == stylesSet.length) { - StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4]; - System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount); - stylesSet = tmpStylesSet; - } - stylesSet[stylesSetCount++] = newStyle; - } - tmpStyles[i] = stylesSet[index]; - } - newStyles = tmpStyles; - } - - if (styleCount == 0) { - if (newRanges != null) { - ranges = new int[newRanges.length]; - System.arraycopy(newRanges, 0, ranges, 0, ranges.length); - } - styles = new StyleRange[newStyles.length]; - System.arraycopy(newStyles, 0, styles, 0, styles.length); - styleCount = newStyles.length; - return; - } - if (newRanges != null && ranges == null) { - ranges = new int[styles.length << 1]; - for (int i = 0, j = 0; i < styleCount; i++) { - ranges[j++] = styles[i].start; - ranges[j++] = styles[i].length; - } - } - if (newRanges == null && ranges != null) { - newRanges = new int[newStyles.length << 1]; - for (int i = 0, j = 0; i < newStyles.length; i++) { - newRanges[j++] = newStyles[i].start; - newRanges[j++] = newStyles[i].length; - } - } - if (ranges != null) { - int rangeCount = styleCount << 1; - int start = newRanges[0]; - int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd; - boolean insert = modifyStart == rangeCount; - if (!insert) { - int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1]; - modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); - insert = modifyStart == modifyEnd && ranges[modifyStart] >= end; - } - if (insert) { - addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart); - return; - } - modifyEnd = modifyStart; - int[] mergeRanges = new int[6]; - StyleRange[] mergeStyles = new StyleRange[3]; - for (int i = 0; i < newRanges.length; i += 2) { - int newStart = newRanges[i]; - int newEnd = newStart + newRanges[i + 1]; - if (newStart == newEnd) continue; - int modifyLast = 0, mergeCount = 0; - while (modifyEnd < rangeCount) { - if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2; - if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break; - modifyEnd += 2; - } - if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) { - mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1]; - mergeRanges[mergeCount] = ranges[modifyStart]; - mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart]; - mergeCount += 2; - } - mergeStyles[mergeCount >> 1] = newStyles[i >> 1]; - mergeRanges[mergeCount] = newStart; - mergeRanges[mergeCount + 1] = newRanges[i + 1]; - mergeCount += 2; - if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) { - mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1]; - mergeRanges[mergeCount] = newEnd; - mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd; - mergeCount += 2; - modifyLast = 2; - } - int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); - rangeCount += grow; - modifyStart = modifyEnd += grow; - } - } else { - int start = newStyles[0].start; - int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd; - boolean insert = modifyStart == styleCount; - if (!insert) { - int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length; - modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); - insert = modifyStart == modifyEnd && styles[modifyStart].start >= end; - } - if (insert) { - addMerge(newStyles, newStyles.length, modifyStart, modifyStart); - return; - } - modifyEnd = modifyStart; - StyleRange[] mergeStyles = new StyleRange[3]; - for (StyleRange newStyle : newStyles) { - StyleRange style; - int newStart = newStyle.start; - int newEnd = newStart + newStyle.length; - if (newStart == newEnd) continue; - int modifyLast = 0, mergeCount = 0; - while (modifyEnd < styleCount) { - if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++; - if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break; - modifyEnd++; - } - style = styles[modifyStart]; - if (style.start < newStart && newStart < style.start + style.length) { - style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); - style.length = newStart - style.start; - } - mergeStyles[mergeCount++] = newStyle; - if (modifyEnd < styleCount) { - style = styles[modifyEnd]; - if (style.start < newEnd && newEnd < style.start + style.length) { - style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); - style.length += style.start - newEnd; - style.start = newEnd; - modifyLast = 1; - } - } - int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); - modifyStart = modifyEnd += grow; - } - } -} -void textChanging(TextChangingEvent event) { - int start = event.start; - int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount; - int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount; - - updateRanges(start, replaceCharCount, newCharCount); - - int startLine = content.getLineAtOffset(start); - if (replaceCharCount == content.getCharCount()) lines = null; - if (replaceLineCount == lineCount) { - lineCount = newLineCount; - lineSizes = new LineSizeInfo[lineCount]; - reset(0, lineCount); - } else { - int startIndex = startLine + replaceLineCount + 1; - int endIndex = startLine + newLineCount + 1; - if(lineCount < startLine) { - SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startLine: " + lineCount + ":" + startLine); - } - if(lineCount < startIndex) { - SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startIndex: " + lineCount + ":" + startIndex); - } - int delta = newLineCount - replaceLineCount; - if (lineCount + delta > lineSizes.length) { - LineSizeInfo[] newLineSizes = new LineSizeInfo[lineCount + delta + GROW]; - System.arraycopy(lineSizes, 0, newLineSizes, 0, lineCount); - lineSizes = newLineSizes; - } - if (lines != null) { - if (lineCount + delta > lines.length) { - LineInfo[] newLines = new LineInfo[lineCount + delta + GROW]; - System.arraycopy(lines, 0, newLines, 0, lineCount); - lines = newLines; - } - } - System.arraycopy(lineSizes, startIndex, lineSizes, endIndex, lineCount - startIndex); - for (int i = startLine; i < endIndex; i++) { - lineSizes[i] = null; - } - for (int i = lineCount + delta; i < lineCount; i++) { - lineSizes[i] = null; - } - if (layouts != null) { - int layoutStartLine = startLine - topIndex; - int layoutEndLine = layoutStartLine + replaceLineCount + 1; - for (int i = layoutStartLine; i < layoutEndLine; i++) { - if (0 <= i && i < layouts.length) { - if (layouts[i] != null) layouts[i].dispose(); - layouts[i] = null; - if (bullets != null && bulletsIndices != null) bullets[i] = null; - } - } - if (delta > 0) { - for (int i = layouts.length - 1; i >= layoutEndLine; i--) { - if (0 <= i && i < layouts.length) { - endIndex = i + delta; - if (0 <= endIndex && endIndex < layouts.length) { - layouts[endIndex] = layouts[i]; - layouts[i] = null; - if (bullets != null && bulletsIndices != null) { - bullets[endIndex] = bullets[i]; - bulletsIndices[endIndex] = bulletsIndices[i]; - bullets[i] = null; - } - } else { - if (layouts[i] != null) layouts[i].dispose(); - layouts[i] = null; - if (bullets != null && bulletsIndices != null) bullets[i] = null; - } - } - } - } else if (delta < 0) { - for (int i = layoutEndLine; i < layouts.length; i++) { - if (0 <= i && i < layouts.length) { - endIndex = i + delta; - if (0 <= endIndex && endIndex < layouts.length) { - layouts[endIndex] = layouts[i]; - layouts[i] = null; - if (bullets != null && bulletsIndices != null) { - bullets[endIndex] = bullets[i]; - bulletsIndices[endIndex] = bulletsIndices[i]; - bullets[i] = null; - } - } else { - if (layouts[i] != null) layouts[i].dispose(); - layouts[i] = null; - if (bullets != null && bulletsIndices != null) bullets[i] = null; - } - } - } - } - } - if (replaceLineCount != 0 || newLineCount != 0) { - int startLineOffset = content.getOffsetAtLine(startLine); - if (startLineOffset != start) startLine++; - updateBullets(startLine, replaceLineCount, newLineCount, true); - if (lines != null) { - startIndex = startLine + replaceLineCount; - endIndex = startLine + newLineCount; - System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex); - for (int i = startLine; i < endIndex; i++) { - lines[i] = null; - } - for (int i = lineCount + delta; i < lineCount; i++) { - lines[i] = null; - } - } - } - lineCount += delta; - if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) { - maxWidth = 0; - maxWidthLineIndex = -1; - for (int i = 0; i < lineCount; i++) { - LineSizeInfo lineSize = getLineSize(i); - if (lineSize.width > maxWidth) { - maxWidth = lineSize.width; - maxWidthLineIndex = i; - } - } - } - } -} -void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) { - if (bullets == null) return; - if (bulletsIndices != null) return; - for (Bullet bullet : bullets) { - int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update); - if (lines != null) { - if (redrawLines == null) { - redrawLines = lines; - } else { - int[] newRedrawBullets = new int[redrawLines.length + lines.length]; - System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length); - System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length); - redrawLines = newRedrawBullets; - } - } - } - int removed = 0; - for (Bullet bullet : bullets) { - if (bullet.size() == 0) removed++; - } - if (removed > 0) { - if (removed == bullets.length) { - bullets = null; - } else { - Bullet[] newBulletsList = new Bullet[bullets.length - removed]; - for (int i = 0, j = 0; i < bullets.length; i++) { - Bullet bullet = bullets[i]; - if (bullet.size() > 0) newBulletsList[j++] = bullet; - } - bullets = newBulletsList; - } - } -} -void updateRanges(int start, int replaceCharCount, int newCharCount) { - if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return; - if (ranges != null) { - int rangeCount = styleCount << 1; - int modifyStart = getRangeIndex(start, -1, rangeCount); - if (modifyStart == rangeCount) return; - int end = start + replaceCharCount; - int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); - int offset = newCharCount - replaceCharCount; - if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { - if (newCharCount == 0) { - ranges[modifyStart + 1] -= replaceCharCount; - modifyEnd += 2; - } else { - if (rangeCount + 2 > ranges.length) { - int[] newRanges = new int[ranges.length + (GROW << 1)]; - System.arraycopy(ranges, 0, newRanges, 0, rangeCount); - ranges = newRanges; - StyleRange[] newStyles = new StyleRange[styles.length + GROW]; - System.arraycopy(styles, 0, newStyles, 0, styleCount); - styles = newStyles; - } - System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2)); - System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1)); - ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end; - ranges[modifyStart + 2] = start + newCharCount; - ranges[modifyStart + 1] = start - ranges[modifyStart]; - styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1]; - rangeCount += 2; - styleCount++; - modifyEnd += 4; - } - if (offset != 0) { - for (int i = modifyEnd; i < rangeCount; i += 2) { - ranges[i] += offset; - } - } - } else { - if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) { - ranges[modifyStart + 1] = start - ranges[modifyStart]; - modifyStart += 2; - } - if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { - ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end; - ranges[modifyEnd] = end; - } - if (offset != 0) { - for (int i = modifyEnd; i < rangeCount; i += 2) { - ranges[i] += offset; - } - } - System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd); - System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1)); - styleCount -= (modifyEnd - modifyStart) >> 1; - } - } else { - int modifyStart = getRangeIndex(start, -1, styleCount); - if (modifyStart == styleCount) return; - int end = start + replaceCharCount; - int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); - int offset = newCharCount - replaceCharCount; - if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) { - if (newCharCount == 0) { - styles[modifyStart].length -= replaceCharCount; - modifyEnd++; - } else { - if (styleCount + 1 > styles.length) { - StyleRange[] newStyles = new StyleRange[styles.length + GROW]; - System.arraycopy(styles, 0, newStyles, 0, styleCount); - styles = newStyles; - } - System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1)); - styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone(); - styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end; - styles[modifyStart + 1].start = start + newCharCount; - styles[modifyStart].length = start - styles[modifyStart].start; - styleCount++; - modifyEnd += 2; - } - if (offset != 0) { - for (int i = modifyEnd; i < styleCount; i++) { - styles[i].start += offset; - } - } - } else { - if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) { - styles[modifyStart].length = start - styles[modifyStart].start; - modifyStart++; - } - if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) { - styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end; - styles[modifyEnd].start = end; - } - if (offset != 0) { - for (int i = modifyEnd; i < styleCount; i++) { - styles[i].start += offset; - } - } - System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd); - styleCount -= modifyEnd - modifyStart; - } - } -} - -public boolean hasVerticalIndent() { - return Arrays.stream(lines).filter(Objects::nonNull) // - .mapToInt(line -> line.verticalIndent) // - .anyMatch(n -> n != 0); -} - - +// Device device; +// StyledText styledText; +// StyledTextContent content; +// +// /* Custom line spacing */ +// StyledTextLineSpacingProvider lineSpacingProvider; +// boolean lineSpacingComputing; +// +// /* Custom line metrics */ +// private FontMetrics fixedLineMetrics; +// +// /* Font info */ +// Font regularFont, boldFont, italicFont, boldItalicFont; +// int tabWidth; +// int ascent, descent; +// int averageCharWidth; +// int tabLength; //tab length in spaces +// +// /* Line data */ +// int topIndex = -1; +// TextLayout[] layouts; +// int lineCount; +// LineSizeInfo[] lineSizes; +// LineInfo[] lines; +// int maxWidth; +// int maxWidthLineIndex; +// float averageLineHeight; +// int linesInAverageLineHeight; +// boolean idleRunning; +// +// /* Bullet */ +// Bullet[] bullets; +// int[] bulletsIndices; +// int[] redrawLines; +// +// /* Style data */ +// int[] ranges; +// int styleCount; +// StyleRange[] styles; +// StyleRange[] stylesSet; +// int stylesSetCount = 0; +// boolean hasLinks, fixedPitch; +// final static int BULLET_MARGIN = 8; +// +// final static boolean COMPACT_STYLES = true; +// final static boolean MERGE_STYLES = true; +// +// final static int GROW = 32; +// final static int IDLE_TIME = 50; +// final static int CACHE_SIZE = 300; +// +// final static int BACKGROUND = 1 << 0; +// final static int ALIGNMENT = 1 << 1; +// final static int INDENT = 1 << 2; +// final static int JUSTIFY = 1 << 3; +// final static int SEGMENTS = 1 << 5; +// final static int TABSTOPS = 1 << 6; +// final static int WRAP_INDENT = 1 << 7; +// final static int SEGMENT_CHARS = 1 << 8; +// final static int VERTICAL_INDENT = 1 << 9; +// +// static class LineSizeInfo { +// +// private static final int RESETED_SIZE = -1; +// +// /* Line size */ +// int height; +// int width; +// +// public LineSizeInfo() { +// resetSize(); +// } +// +// /** +// * Reset the line size. +// */ +// void resetSize() { +// height = RESETED_SIZE; +// width = RESETED_SIZE; +// } +// +// /** +// * Returns true if the TextLayout get from the layout pool can be directly used +// * or must be refreshed with styles. +// * +// * @return true if the TextLayout get from the layout pool can be directly used +// * or must be refreshed with styles. +// */ +// boolean canLayout() { +// return !needsRecalculateWidth(); +// } +// +// /** +// * Returns true if it needs to recalculate the line size and false +// * otherwise. +// * +// * @return true if it needs to recalculate the line size and false +// * otherwise. +// */ +// boolean needsRecalculateSize() { +// return needsRecalculateWidth() || needsRecalculateHeight(); +// } +// +// /** +// * Returns true if it needs to recalculate the line width and false +// * otherwise. +// * +// * @return true if it needs to recalculate the line width and false +// * otherwise. +// */ +// boolean needsRecalculateWidth() { +// return width == RESETED_SIZE; +// } +// +// /** +// * Returns true if it needs to recalculate the line height and false +// * otherwise. +// * +// * @return true if it needs to recalculate the line height and false +// * otherwise. +// */ +// boolean needsRecalculateHeight() { +// return height == RESETED_SIZE; +// } +// } +// +// static class LineInfo { +// int flags; +// Color background; +// int alignment; +// int indent; +// int wrapIndent; +// boolean justify; +// int[] segments; +// char[] segmentsChars; +// int[] tabStops; +// int verticalIndent; +// +// public LineInfo() { +// } +// public LineInfo(LineInfo info) { +// if (info != null) { +// flags = info.flags; +// background = info.background; +// alignment = info.alignment; +// indent = info.indent; +// wrapIndent = info.wrapIndent; +// justify = info.justify; +// segments = info.segments; +// segmentsChars = info.segmentsChars; +// tabStops = info.tabStops; +// verticalIndent = info.verticalIndent; +// } +// } +// } +// +// private record LineDrawInfo(int index, TextLayout layout, String text, int offset, int height) { +// +// } +// +// static int cap (TextLayout layout, int offset) { +// if (layout == null) return offset; +// return Math.min (layout.getText().length() -1, Math.max (0, offset)); +// } +// +//StyledTextRenderer(Device device, StyledText styledText) { +// this.device = device; +// this.styledText = styledText; +//} +//int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { +// int rangeCount = styleCount << 1; +// StyleRange endStyle = null; +// int endStart = 0, endLength = 0; +// if (modifyEnd < rangeCount) { +// endStyle = styles[modifyEnd >> 1]; +// endStart = ranges[modifyEnd]; +// endLength = ranges[modifyEnd + 1]; +// } +// int grow = mergeCount - (modifyEnd - modifyStart); +// if (rangeCount + grow >= ranges.length) { +// int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)]; +// System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart); +// StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW]; +// System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1); +// if (rangeCount > modifyEnd) { +// System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd); +// System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); +// } +// ranges = tmpRanges; +// styles = tmpStyles; +// } else { +// if (rangeCount > modifyEnd) { +// System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd); +// System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); +// } +// } +// if (MERGE_STYLES) { +// int j = modifyStart; +// for (int i = 0; i < mergeCount; i += 2) { +// if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) { +// ranges[j - 1] += mergeRanges[i + 1]; +// } else { +// styles[j >> 1] = mergeStyles[i >> 1]; +// ranges[j++] = mergeRanges[i]; +// ranges[j++] = mergeRanges[i + 1]; +// } +// } +// if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) { +// ranges[j - 1] += endLength; +// modifyEnd += 2; +// mergeCount += 2; +// } +// if (rangeCount > modifyEnd) { +// System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd); +// System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1)); +// } +// grow = (j - modifyStart) - (modifyEnd - modifyStart); +// } else { +// System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount); +// System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1); +// } +// styleCount += grow >> 1; +// return grow; +//} +//int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { +// int grow = mergeCount - (modifyEnd - modifyStart); +// StyleRange endStyle = null; +// if (modifyEnd < styleCount) endStyle = styles[modifyEnd]; +// if (styleCount + grow >= styles.length) { +// StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW]; +// System.arraycopy(styles, 0, tmpStyles, 0, modifyStart); +// if (styleCount > modifyEnd) { +// System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd); +// } +// styles = tmpStyles; +// } else { +// if (styleCount > modifyEnd) { +// System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd); +// } +// } +// if (MERGE_STYLES) { +// int j = modifyStart; +// for (int i = 0; i < mergeCount; i++) { +// StyleRange newStyle = mergeStyles[i], style; +// if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) { +// style.length += newStyle.length; +// } else { +// styles[j++] = newStyle; +// } +// } +// StyleRange style = styles[j - 1]; +// if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) { +// style.length += endStyle.length; +// modifyEnd++; +// mergeCount++; +// } +// if (styleCount > modifyEnd) { +// System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd); +// } +// grow = (j - modifyStart) - (modifyEnd - modifyStart); +// } else { +// System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount); +// } +// styleCount += grow; +// return grow; +//} +//void calculate(int startLine, int lineCount) { +// int endLine = startLine + lineCount; +// if (startLine < 0 || endLine > lineSizes.length) { +// return; +// } +// int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth(); +// for (int i = startLine; i < endLine; i++) { +// LineSizeInfo line = getLineSize(i); +// if (line.needsRecalculateSize()) { +// TextLayout layout = getTextLayout(i); +// Rectangle rect = layout.getBounds(); +// line.width = rect.width + hTrim; +// line.height = rect.height; +// averageLineHeight += (line.height - Math.round(averageLineHeight)) / ++linesInAverageLineHeight; +// disposeTextLayout(layout); +// } +// if (line.width > maxWidth) { +// maxWidth = line.width; +// maxWidthLineIndex = i; +// } +// } +//} +//LineSizeInfo getLineSize(int i) { +// if (lineSizes[i] == null) { +// lineSizes[i] = new LineSizeInfo(); +// } +// return lineSizes[i]; +//} +//void calculateClientArea () { +// int index = Math.max (0, styledText.getTopIndex()); +// int lineCount = content.getLineCount(); +// int height = styledText.getClientArea().height; +// int y = 0; +// /* +// * There exists a possibility of ArrayIndexOutOfBounds Exception in +// * below code, exact scenario not known. To avoid this exception added +// * check for 'index' value, refer Bug 471192. +// */ +// while (height > y && lineCount > index && lineSizes.length > index) { +// calculate(index, 1); +// y += lineSizes[index++].height; +// } +//} +//void calculateIdle () { +// if (idleRunning) return; +// Runnable runnable = new Runnable() { +// @Override +// public void run() { +// if (styledText == null) return; +// int i; +// long start = System.currentTimeMillis(); +// for (i = 0; i < lineCount; i++) { +// LineSizeInfo line = getLineSize(i); +// if (line.needsRecalculateSize()) { +// calculate(i, 1); +// if (System.currentTimeMillis() - start > IDLE_TIME) break; +// } +// } +// if (i < lineCount) { +// Display display = styledText.getDisplay(); +// display.asyncExec(this); +// } else { +// idleRunning = false; +// styledText.setScrollBars(true); +// ScrollBar bar = styledText.getVerticalBar(); +// if (bar != null) { +// bar.setSelection(styledText.getVerticalScrollOffset()); +// } +// } +// } +// }; +// Display display = styledText.getDisplay(); +// display.asyncExec(runnable); +// idleRunning = true; +//} +//void clearLineBackground(int startLine, int count) { +// if (lines == null) return; +// for (int i = startLine; i < startLine + count; i++) { +// LineInfo info = lines[i]; +// if (info != null) { +// info.flags &= ~BACKGROUND; +// info.background = null; +// if (info.flags == 0) lines[i] = null; +// } +// } +//} +//void clearLineStyle(int startLine, int count) { +// if (lines == null) return; +// for (int i = startLine; i < startLine + count; i++) { +// LineInfo info = lines[i]; +// if (info != null) { +// info.flags &= ~(ALIGNMENT | INDENT | VERTICAL_INDENT | WRAP_INDENT | JUSTIFY | TABSTOPS); +// if (info.flags == 0) lines[i] = null; +// } +// } +//} +//void copyInto(StyledTextRenderer renderer) { +// if (ranges != null) { +// int[] newRanges = renderer.ranges = new int[styleCount << 1]; +// System.arraycopy(ranges, 0, newRanges, 0, newRanges.length); +// } +// if (styles != null) { +// StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount]; +// for (int i = 0; i < newStyles.length; i++) { +// newStyles[i] = (StyleRange)styles[i].clone(); +// } +// renderer.styleCount = styleCount; +// } +// if (lines != null) { +// LineInfo[] newLines = renderer.lines = new LineInfo[lineCount]; +// for (int i = 0; i < newLines.length; i++) { +// newLines[i] = new LineInfo(lines[i]); +// } +// renderer.lineCount = lineCount; +// } +//} +//void dispose() { +// if (boldFont != null) boldFont.dispose(); +// if (italicFont != null) italicFont.dispose(); +// if (boldItalicFont != null) boldItalicFont.dispose(); +// boldFont = italicFont = boldItalicFont = null; +// reset(); +// content = null; +// device = null; +// styledText = null; +//} +//void disposeTextLayout (TextLayout layout) { +// if (layouts != null) { +// for (TextLayout l : layouts) { +// if (l == layout) return; +// } +// } +// layout.dispose(); +//} +//void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) { +// StyleRange style = bullet.style; +// GlyphMetrics metrics = style.metrics; +// Color color = style.foreground; +// if (color != null) gc.setForeground(color); +// Font font = style.font; +// if (font != null) gc.setFont(font); +// String string = ""; +// int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER); +// switch (type) { +// case ST.BULLET_DOT: string = "\u2022"; break; +// case ST.BULLET_NUMBER: string = String.valueOf(index + 1); break; +// case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break; +// case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break; +// } +// if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text; +// Display display = styledText.getDisplay(); +// TextLayout layout = new TextLayout(display); +// layout.setText(string); +// layout.setAscent(lineAscent); +// layout.setDescent(lineDescent); +// style = (StyleRange)style.clone(); +// style.metrics = null; +// if (style.font == null) style.font = getFont(style.fontStyle); +// layout.setStyle(style, 0, string.length()); +// int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN); +// layout.draw(gc, x, paintY); +// layout.dispose(); +//} +// +///** +// * Caches draw-related info that may be expensive to calculate twice when +// * drawing first background and then foreground. +// */ +//private LineDrawInfo makeLineDrawInfo(int lineIndex) { +// TextLayout layout = getTextLayout(lineIndex); +// String text = content.getLine(lineIndex); +// int offset = content.getOffsetAtLine(lineIndex); +// int height = layout.getBounds().height; +// return new LineDrawInfo(lineIndex, layout, text, offset, height); +//} +// +//int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, Color widgetBackground, Color widgetForeground) { +// // When fixed line metrics is in effect, tall unicode characters +// // will not always fit line's height. In this case, they will +// // draw out of line's bounds. To prevent them from being clipped +// // by next line's background, paint entire background before any +// // foreground. +// // I considered to make this mode default, but was worried about +// // potential regressions in various legacy code. For example, it +// // could change something about line heights/colors during +// // painting. While this doesn't sound like a good thing to do, yet +// // still, I'd rather stay safe. +// final boolean drawBackBeforeFore = (fixedLineMetrics != null); +// +// if (drawBackBeforeFore) { +// // Cache drawing information +// final List drawInfos = new ArrayList<>(); +// int y = begY; +// for (int iLine = startLine; y < endY && iLine < endLine; iLine++) { +// LineDrawInfo lineInfo = makeLineDrawInfo(iLine); +// drawInfos.add(lineInfo); +// y += lineInfo.height; +// } +// +// // Draw background +// y = begY; +// for (LineDrawInfo lineInfo : drawInfos) { +// drawLineBackground(lineInfo, y, gc, widgetBackground); +// y += lineInfo.height; +// } +// +// // Draw foreground +// y = begY; +// for (LineDrawInfo lineInfo : drawInfos) { +// drawLineForeground(lineInfo, begX, y, gc, widgetForeground); +// y += lineInfo.height; +// } +// +// // cleanup +// for (LineDrawInfo lineInfo : drawInfos) { +// disposeTextLayout(lineInfo.layout); +// } +// +// return y - begY; +// } +// +// int y = begY; +// for (int iLine = startLine; y < endY && iLine < endLine; iLine++) { +// LineDrawInfo lineInfo = makeLineDrawInfo(iLine); +// drawLineBackground(lineInfo, y, gc, widgetBackground); +// drawLineForeground(lineInfo, begX, y, gc, widgetForeground); +// disposeTextLayout(lineInfo.layout); +// y += lineInfo.height; +// } +// return y - begY; +//} +// +//private void drawLineBackground(LineDrawInfo lineInfo, int paintY, GC gc, Color widgetBackground) { +// Rectangle client = styledText.getClientArea(); +// Color lineBackground = getLineBackground(lineInfo.index, null); +// StyledTextEvent event = styledText.getLineBackgroundData(lineInfo.offset, lineInfo.text); +// if (event != null && event.lineBackground != null) lineBackground = event.lineBackground; +// int verticalIndent = lineInfo.layout.getVerticalIndent(); +// +// if (lineBackground != null) { +// if (verticalIndent > 0) { +// gc.setBackground(widgetBackground); +// gc.fillRectangle(client.x, paintY, client.width, verticalIndent); +// } +// gc.setBackground(lineBackground); +// gc.fillRectangle(client.x, paintY + verticalIndent, client.width, lineInfo.height - verticalIndent); +// } else { +// gc.setBackground(widgetBackground); +// styledText.drawBackground(gc, client.x, paintY, client.width, lineInfo.height); +// } +//} +// +//private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground) { +// int lineLength = lineInfo.text.length(); +// gc.setForeground(widgetForeground); +// Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength); +// if (styledText.getBlockSelection() || selection.length == 0) { +// lineInfo.layout.draw(gc, paintX, paintY); +// } else { +// Color selectionFg = styledText.getSelectionForeground(); +// Color selectionBg = styledText.getSelectionBackground(); +// final int baseFlags = (styledText.getStyle() & SWT.FULL_SELECTION) != 0 ? SWT.FULL_SELECTION : SWT.DELIMITER_SELECTION; +// for (Point relativeSelection : selection) { +// int start = Math.max(0, relativeSelection.x); +// int end = Math.min(lineLength, relativeSelection.y); +// int flags = baseFlags; +// if (relativeSelection.x <= lineLength && lineLength < relativeSelection.y ) { +// flags |= SWT.LAST_LINE_SELECTION; +// } +// // TODO calling draw multiple times here prints line multiple times, overriding some colors +// lineInfo.layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags); +// } +// } +// +// // draw objects +// Bullet bullet = null; +// int bulletIndex = -1; +// if (bullets != null) { +// if (bulletsIndices != null) { +// int index = lineInfo.index - topIndex; +// if (0 <= index && index < CACHE_SIZE) { +// bullet = bullets[index]; +// bulletIndex = bulletsIndices[index]; +// } +// } else { +// for (Bullet b : bullets) { +// bullet = b; +// bulletIndex = bullet.indexOf(lineInfo.index); +// if (bulletIndex != -1) break; +// } +// } +// } +// if (bulletIndex != -1 && bullet != null) { +// FontMetrics metrics = lineInfo.layout.getLineMetrics(0); +// int lineAscent = metrics.getAscent() + metrics.getLeading(); +// if (bullet.type == ST.BULLET_CUSTOM) { +// bullet.style.start = lineInfo.offset; +// styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex); +// } else { +// drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent()); +// } +// } +// TextStyle[] styles = lineInfo.layout.getStyles(); +// int[] ranges = null; +// for (int i = 0; i < styles.length; i++) { +// if (styles[i].metrics != null) { +// if (ranges == null) ranges = lineInfo.layout.getRanges(); +// int start = ranges[i << 1]; +// int length = ranges[(i << 1) + 1] - start + 1; +// Point point = lineInfo.layout.getLocation(start, false); +// FontMetrics metrics = lineInfo.layout.getLineMetrics(lineInfo.layout.getLineIndex(start)); +// StyleRange style = (StyleRange)((StyleRange)styles[i]).clone(); +// style.start = start + lineInfo.offset; +// style.length = length; +// int lineAscent = metrics.getAscent() + metrics.getLeading(); +// styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0); +// } +// } +//} +// +//private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset) { +// int[] selectionRanges = styledText.getSelectionRanges(); +// int lineLength = toOffset - fromOffset; +// List res = new ArrayList<>(); +// for (int i = 0; i < selectionRanges.length; i += 2) { +// // ranges are assumed to be sorted by start offset, then (positive)length or higher end offset +// Point relativeSelection = new Point(selectionRanges[i] - fromOffset, selectionRanges[i] + selectionRanges[i + 1] - fromOffset); +// if (relativeSelection.x != relativeSelection.y && +// relativeSelection.x <= lineLength && relativeSelection.y >= 0) { +// res.add(relativeSelection); +// } +// } +// return res.toArray(new Point[res.size()]); +//} +// +//int getBaseline() { +// return ascent; +//} +//int getCachedLineHeight(int lineIndex) { +// return getLineHeight(lineIndex, false); +//} +//Font getFont(int style) { +// switch (style) { +// case SWT.BOLD: +// if (boldFont != null) return boldFont; +// return boldFont = new Font(device, getFontData(style)); +// case SWT.ITALIC: +// if (italicFont != null) return italicFont; +// return italicFont = new Font(device, getFontData(style)); +// case SWT.BOLD | SWT.ITALIC: +// if (boldItalicFont != null) return boldItalicFont; +// return boldItalicFont = new Font(device, getFontData(style)); +// default: +// return regularFont; +// } +//} +//FontData[] getFontData(int style) { +// FontData[] fontDatas = regularFont.getFontData(); +// for (FontData fontData : fontDatas) { +// fontData.setStyle(style); +// } +// return fontDatas; +//} +//int getHeight () { +// int defaultLineHeight = getLineHeight(); +// if (styledText.isFixedLineHeight()) { +// return lineCount * defaultLineHeight + styledText.topMargin + styledText.bottomMargin; +// } +// int totalHeight = 0; +// int width = styledText.getWrapWidth(); +// for (int i = 0; i < lineCount; i++) { +// LineSizeInfo line = getLineSize(i); +// int height = line.height; +// if (line.needsRecalculateHeight()) { +// if (width > 0) { +// int length = content.getLine(i).length(); +// height = ((length * averageCharWidth / width) + 1) * defaultLineHeight; +// } else { +// height = defaultLineHeight; +// } +// } +// totalHeight += height; +// } +// return totalHeight + styledText.topMargin + styledText.bottomMargin; +//} +//boolean hasLink(int offset) { +// if (offset == -1) return false; +// int lineIndex = content.getLineAtOffset(offset); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// String line = content.getLine(lineIndex); +// StyledTextEvent event = styledText.getLineStyleData(lineOffset, line); +// if (event != null) { +// StyleRange[] styles = event.styles; +// if (styles != null) { +// int[] ranges = event.ranges; +// if (ranges != null) { +// for (int i = 0; i < ranges.length; i+=2) { +// if (ranges[i] <= offset && offset < ranges[i] + ranges[i+1] && styles[i >> 1].underline && styles[i >> 1].underlineStyle == SWT.UNDERLINE_LINK) { +// return true; +// } +// } +// } else { +// for (StyleRange style : styles) { +// if (style.start <= offset && offset < style.start + style.length && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) { +// return true; +// } +// } +// } +// } +// } else { +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// int index = getRangeIndex(offset, -1, rangeCount); +// if (index >= rangeCount) return false; +// int rangeStart = ranges[index]; +// int rangeLength = ranges[index + 1]; +// StyleRange rangeStyle = styles[index >> 1]; +// if (rangeStart <= offset && offset < rangeStart + rangeLength && rangeStyle.underline && rangeStyle.underlineStyle == SWT.UNDERLINE_LINK) { +// return true; +// } +// } +// } +// return false; +//} +//int getLineAlignment(int index, int defaultAlignment) { +// if (lines == null) return defaultAlignment; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & ALIGNMENT) != 0) { +// return info.alignment; +// } +// return defaultAlignment; +//} +//Color getLineBackground(int index, Color defaultBackground) { +// if (lines == null) return defaultBackground; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & BACKGROUND) != 0) { +// return info.background; +// } +// return defaultBackground; +//} +//Bullet getLineBullet (int index, Bullet defaultBullet) { +// if (bullets == null) return defaultBullet; +// if (bulletsIndices != null) return defaultBullet; +// for (Bullet bullet : bullets) { +// if (bullet.indexOf(index) != -1) return bullet; +// } +// return defaultBullet; +//} +//int getLineHeight() { +// return ascent + descent; +//} +//int getLineHeight(int lineIndex) { +// return getLineHeight(lineIndex, true); +//} +//int getLineHeight(int lineIndex, boolean exact) { +// LineSizeInfo line = getLineSize(lineIndex); +// if (line.needsRecalculateHeight()) { +// // here we are in "variable line height", the call of calculate which uses TextLayout is very slow +// // so use the average line height of all calculated lines when many heights are needed e.g. for scrolling. +// if (isVariableHeight(lineIndex)) { +// if (exact) { +// calculate(lineIndex, 1); +// } else { +// return Math.round(averageLineHeight); +// } +// } else { +// line.height = getLineHeight() + getLineSpacing(lineIndex) + getLineVerticalIndent(lineIndex); +// } +// } +// return line.height; +//} +///** +// * Returns true if the given line can use the default line height and false +// * otherwise. +// * +// * @param lineIndex +// * line index +// * @return true if the given line can use the default line height and false +// * otherwise. +// */ +//private boolean isVariableHeight(int lineIndex) { +// if (styledText.isWordWrap()) { +// // In word wrap mode, the line height must be recomputed with TextLayout +// return true; +// } +// StyleRange[] styles = getStylesForLine(lineIndex); +// if (styles != null) { +// for (StyleRange style : styles) { +// if (style.isVariableHeight()) { +// // style is variable height +// return true; +// } +// } +// } +// return false; +//} +///** +// * returns true if the given line index defines custom line spacing and false +// * otherwise. +// * +// * @param lineIndex +// * the line index. +// * @return true if the given line index defines custom line spacing and false +// * otherwise. +// */ +//private int getLineSpacing(int lineIndex) { +// if (styledText.lineSpacing > 0) { +// return styledText.lineSpacing; +// } else if (lineSpacingProvider != null) { +// Integer lineSpacing = lineSpacingProvider.getLineSpacing(lineIndex); +// if (lineSpacing != null) { +// return lineSpacing; +// } +// } +// return 0; +//} +///** +// * Returns styles range for the given line index and null otherwise. +// * +// * @param lineIndex +// * the line index. +// * @return styles range for the given line index and null otherwise. +// */ +//private StyleRange[] getStylesForLine(int lineIndex) { +// int start = styledText.getOffsetAtLine(lineIndex); +// int length = styledText.getLine(lineIndex).length(); +// return getStyleRanges(start, length, false); +//} +//int getLineIndent(int index, int defaultIndent) { +// if (lines == null) return defaultIndent; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & INDENT) != 0) { +// return info.indent; +// } +// return defaultIndent; +//} +//int getLineVerticalIndent(int index) { +// if (lines == null) return 0; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & VERTICAL_INDENT) != 0) { +// return info.verticalIndent; +// } +// return 0; +//} +//int getLineWrapIndent(int index, int defaultWrapIndent) { +// if (lines == null) return defaultWrapIndent; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & WRAP_INDENT) != 0) { +// return info.wrapIndent; +// } +// return defaultWrapIndent; +//} +//boolean getLineJustify(int index, boolean defaultJustify) { +// if (lines == null) return defaultJustify; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & JUSTIFY) != 0) { +// return info.justify; +// } +// return defaultJustify; +//} +//int[] getLineTabStops(int index, int[] defaultTabStops) { +// if (lines == null) return defaultTabStops; +// LineInfo info = lines[index]; +// if (info != null && (info.flags & TABSTOPS) != 0) { +// return info.tabStops; +// } +// return defaultTabStops; +//} +//StyledTextLineSpacingProvider getLineSpacingProvider() { +// return lineSpacingProvider; +//} +//int getRangeIndex(int offset, int low, int high) { +// if (styleCount == 0) return 0; +// if (ranges != null) { +// while (high - low > 2) { +// int index = ((high + low) / 2) / 2 * 2; +// int end = ranges[index] + ranges[index + 1]; +// if (end > offset) { +// high = index; +// } else { +// low = index; +// } +// } +// } else { +// while (high - low > 1) { +// int index = ((high + low) / 2); +// int end = styles[index].start + styles[index].length; +// if (end > offset) { +// high = index; +// } else { +// low = index; +// } +// } +// } +// return high; +//} +//int[] getRanges(int start, int length) { +// if (length == 0) return null; +// int[] newRanges; +// int end = start + length - 1; +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// int rangeStart = getRangeIndex(start, -1, rangeCount); +// if (rangeStart >= rangeCount) return null; +// if (ranges[rangeStart] > end) return null; +// int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount)); +// if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2); +// newRanges = new int[rangeEnd - rangeStart + 2]; +// System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length); +// } else { +// int rangeStart = getRangeIndex(start, -1, styleCount); +// if (rangeStart >= styleCount) return null; +// if (styles[rangeStart].start > end) return null; +// int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); +// if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1); +// newRanges = new int[(rangeEnd - rangeStart + 1) << 1]; +// for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) { +// StyleRange style = styles[i]; +// newRanges[j] = style.start; +// newRanges[j + 1] = style.length; +// } +// } +// if (start > newRanges[0]) { +// newRanges[1] = newRanges[0] + newRanges[1] - start; +// newRanges[0] = start; +// } +// if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) { +// newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1; +// } +// return newRanges; +//} +//StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { +// if (length == 0) return null; +// StyleRange[] newStyles; +// int end = start + length - 1; +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// int rangeStart = getRangeIndex(start, -1, rangeCount); +// if (rangeStart >= rangeCount) return null; +// if (ranges[rangeStart] > end) return null; +// int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount)); +// if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2); +// newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1]; +// if (includeRanges) { +// for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) { +// newStyles[j] = (StyleRange)styles[i >> 1].clone(); +// newStyles[j].start = ranges[i]; +// newStyles[j].length = ranges[i + 1]; +// } +// } else { +// System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length); +// } +// } else { +// int rangeStart = getRangeIndex(start, -1, styleCount); +// if (rangeStart >= styleCount) return null; +// if (styles[rangeStart].start > end) return null; +// int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); +// if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1); +// newStyles = new StyleRange[rangeEnd - rangeStart + 1]; +// System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length); +// } +// if (includeRanges || ranges == null) { +// StyleRange style = newStyles[0]; +// if (start > style.start) { +// newStyles[0] = style = (StyleRange)style.clone(); +// style.length = style.start + style.length - start; +// style.start = start; +// } +// style = newStyles[newStyles.length - 1]; +// if (end < style.start + style.length - 1) { +// newStyles[newStyles.length - 1] = style = (StyleRange)style.clone(); +// style.length = end - style.start + 1; +// } +// } +// return newStyles; +//} +//StyleRange getStyleRange(StyleRange style) { +// if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) hasLinks = true; +// if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style; +// StyleRange clone = (StyleRange)style.clone(); +// clone.start = clone.length = 0; +// clone.fontStyle = SWT.NORMAL; +// if (clone.font == null) clone.font = getFont(style.fontStyle); +// return clone; +//} +//TextLayout getTextLayout(int lineIndex) { +// if (lineSpacingProvider == null) { +// return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing); +// } +// // Compute line spacing for the given line index. +// int newLineSpacing = styledText.lineSpacing; +// Integer spacing = lineSpacingProvider.getLineSpacing(lineIndex); +// if (spacing != null && spacing.intValue() >= 0) { +// newLineSpacing = spacing; +// } +// // Check if line spacing has not changed +// if (isSameLineSpacing(lineIndex, newLineSpacing)) { +// return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), newLineSpacing); +// } +// // Get text layout with original StyledText line spacing. +// TextLayout layout = getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), +// styledText.lineSpacing); +// if (layout.getSpacing() != newLineSpacing) { +// layout.setSpacing(newLineSpacing); +// if (lineSpacingComputing) { +// return layout; +// } +// try { +// /* Call of resetCache, setCaretLocation, redraw call getTextLayout method +// * To avoid having stack overflow, lineSpacingComputing flag is used to call +// * resetCache, setCaretLocation, redraw methods only at the end of the compute of all lines spacing. +// */ +// lineSpacingComputing = true; +// styledText.resetCache(lineIndex, 1); +// styledText.setCaretLocations(); +// styledText.redraw(); +// } finally { +// lineSpacingComputing = false; +// } +// } +// return layout; +//} +//boolean isSameLineSpacing(int lineIndex, int newLineSpacing) { +// if (layouts == null) { +// return false; +// } +// int layoutIndex = lineIndex - topIndex; +// if (0 <= layoutIndex && layoutIndex < layouts.length) { +// TextLayout layout = layouts[layoutIndex]; +// return layout != null && !layout.isDisposed() && layout.getSpacing() == newLineSpacing; +// } +// return false; +//} +// +//private static final class StyleEntry { +// public final int start; +// public final int end; +// public final TextStyle style; +// +// public StyleEntry(TextStyle style, int start, int end) { +// this.style = style; +// this.start = start; +// this.end = end; +// } +//} +// +//TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) { +// TextLayout layout = null; +// if (styledText != null) { +// int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0; +// if (layouts == null || topIndex != this.topIndex) { +// TextLayout[] newLayouts = new TextLayout[CACHE_SIZE]; +// if (layouts != null) { +// for (int i = 0; i < layouts.length; i++) { +// if (layouts[i] != null) { +// int layoutIndex = (i + this.topIndex) - topIndex; +// if (0 <= layoutIndex && layoutIndex < newLayouts.length) { +// newLayouts[layoutIndex] = layouts[i]; +// } else { +// layouts[i].dispose(); +// } +// } +// } +// } +// if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) { +// int delta = topIndex - this.topIndex; +// if (delta > 0) { +// if (delta < bullets.length) { +// System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta); +// System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta); +// } +// int startIndex = Math.max(0, bullets.length - delta); +// for (int i = startIndex; i < bullets.length; i++) bullets[i] = null; +// } else { +// if (-delta < bullets.length) { +// System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta); +// System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta); +// } +// int endIndex = Math.min(bullets.length, -delta); +// for (int i = 0; i < endIndex; i++) bullets[i] = null; +// } +// } +// this.topIndex = topIndex; +// layouts = newLayouts; +// } +// if (layouts != null) { +// int layoutIndex = lineIndex - topIndex; +// if (0 <= layoutIndex && layoutIndex < layouts.length) { +// layout = layouts[layoutIndex]; +// if (layout != null) { +// // Bug 520374: lineIndex can be >= linesSize.length +// if(lineIndex < lineSizes.length && getLineSize(lineIndex).canLayout()) { +// return layout; +// } +// } else { +// layout = layouts[layoutIndex] = new TextLayout(device); +// } +// } +// } +// } +// if (layout == null) layout = new TextLayout(device); +// String line = content.getLine(lineIndex); +// int lineOffset = content.getOffsetAtLine(lineIndex); +// int[] segments = null; +// char[] segmentChars = null; +// int indent = 0; +// int wrapIndent = 0; +// int verticalIndent = 0; +// int alignment = SWT.LEFT; +// int textDirection = orientation; +// boolean justify = false; +// int[] tabs = {tabWidth}; +// Bullet bullet = null; +// int[] ranges = null; +// StyleRange[] styles = null; +// int rangeStart = 0, styleCount = 0; +// StyledTextEvent event = null; +// if (styledText != null) { +// event = styledText.getBidiSegments(lineOffset, line); +// if (event != null) { +// segments = event.segments; +// segmentChars = event.segmentsChars; +// } +// event = styledText.getLineStyleData(lineOffset, line); +// indent = styledText.indent; +// wrapIndent = styledText.wrapIndent; +// alignment = styledText.alignment; +// if (styledText.isAutoDirection()) { +// textDirection = SWT.AUTO_TEXT_DIRECTION; +// } else if ((styledText.getStyle() & SWT.FLIP_TEXT_DIRECTION) != 0) { +// textDirection = orientation == SWT.RIGHT_TO_LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT; +// } +// justify = styledText.justify; +// if (styledText.tabs != null) tabs = styledText.tabs; +// } +// if (event != null) { +// indent = event.indent; +// verticalIndent = event.verticalIndent; +// wrapIndent = event.wrapIndent; +// alignment = event.alignment; +// justify = event.justify; +// bullet = event.bullet; +// ranges = event.ranges; +// styles = event.styles; +// if (event.tabStops != null) tabs = event.tabStops; +// if (styles != null) { +// styleCount = styles.length; +// if (styledText.isFixedLineHeight()) { +// for (int i = 0; i < styleCount; i++) { +// if (styles[i].isVariableHeight()) { +// styledText.hasStyleWithVariableHeight = true; +// styledText.verticalScrollOffset = -1; +// styledText.redraw(); +// break; +// } +// } +// } +// } +// if (bullets == null || bulletsIndices == null) { +// bullets = new Bullet[CACHE_SIZE]; +// bulletsIndices = new int[CACHE_SIZE]; +// } +// int index = lineIndex - topIndex; +// if (0 <= index && index < CACHE_SIZE) { +// bullets[index] = bullet; +// bulletsIndices[index] = event.bulletIndex; +// } +// } else { +// if (lines != null) { +// LineInfo info = lines[lineIndex]; +// if (info != null) { +// if ((info.flags & INDENT) != 0) indent = info.indent; +// if ((info.flags & VERTICAL_INDENT) != 0) verticalIndent = info.verticalIndent; +// if ((info.flags & WRAP_INDENT) != 0) wrapIndent = info.wrapIndent; +// if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment; +// if ((info.flags & JUSTIFY) != 0) justify = info.justify; +// if ((info.flags & SEGMENTS) != 0) segments = info.segments; +// if ((info.flags & SEGMENT_CHARS) != 0) segmentChars = info.segmentsChars; +// if ((info.flags & TABSTOPS) != 0) tabs = info.tabStops; +// } +// } +// if (bulletsIndices != null) { +// bullets = null; +// bulletsIndices = null; +// } +// if (bullets != null) { +// for (Bullet b : bullets) { +// if (b.indexOf(lineIndex) != -1) { +// bullet = b; +// break; +// } +// } +// } +// ranges = this.ranges; +// styles = this.styles; +// styleCount = this.styleCount; +// if (ranges != null) { +// rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1); +// } else { +// rangeStart = getRangeIndex(lineOffset, -1, styleCount); +// } +// } +// if (bullet != null) { +// StyleRange style = bullet.style; +// GlyphMetrics metrics = style.metrics; +// indent += metrics.width; +// } +// +// // prepare styles, as it may change the line content, do it before calling layout.setText() +// // This needs to happen early to handle the case of GlyphMetrics on \t. +// // The root cause is that TextLayout doesn't return the right value for the bounds when +// // GlyphMetrics are applied on \t. A better fix could be implemented directly in (all 3) +// // TextLayout classes. +// List styleEntries = new ArrayList<>(); +// int lastOffset = 0; +// int length = line.length(); +// if (styles != null) { +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// for (int i = rangeStart; i < rangeCount; i += 2) { +// int start, end; +// if (lineOffset > ranges[i]) { +// start = 0; +// end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]); +// } else { +// start = ranges[i] - lineOffset; +// end = Math.min(length, start + ranges[i + 1]); +// } +// if (start >= length) break; +// if (lastOffset < start) { +// styleEntries.add(new StyleEntry(null, lastOffset, start - 1)); +// } +// TextStyle style = getStyleRange(styles[i >> 1]); +// int endIndex = Math.max(start, Math.min(length, end + 1)); +// if (style.metrics != null && line.substring(start, endIndex).contains("\t")) { +// line = +// line.substring(0, start) + +// line.substring(start, endIndex).replace('\t', ' ') + +// (end < line.length() ? line.substring(end + 1, line.length()) : ""); +// } +// styleEntries.add(new StyleEntry(style, start, end)); +// lastOffset = Math.max(lastOffset, end); +// } +// } else { +// for (int i = rangeStart; i < styleCount; i++) { +// int start, end; +// if (lineOffset > styles[i].start) { +// start = 0; +// end = Math.min (length, styles[i].length - lineOffset + styles[i].start); +// } else { +// start = styles[i].start - lineOffset; +// end = Math.min(length, start + styles[i].length); +// } +// if (start >= length) break; +// if (lastOffset < start) { +// styleEntries.add(new StyleEntry(null, lastOffset, start - 1)); +// } +// TextStyle style = getStyleRange(styles[i]); +// int endIndex = Math.max(start, Math.min(length, end + 1)); +// if (style.metrics != null && line.substring(start, endIndex).contains("\t")) { +// line = +// line.substring(0, start) + +// line.substring(start, endIndex).replace('\t', ' ') + +// (end < line.length() ? line.substring(end + 1, line.length()) : ""); +// } +// styleEntries.add(new StyleEntry(style, start, end)); +// lastOffset = Math.max(lastOffset, end); +// } +// } +// } +// if (lastOffset < length) styleEntries.add(new StyleEntry(null, lastOffset, length)); +// +// layout.setFont(regularFont); +// layout.setAscent(ascent); +// layout.setDescent(descent); +// layout.setFixedLineMetrics(fixedLineMetrics); +// layout.setText(line); +// layout.setOrientation(orientation); +// layout.setSegments(segments); +// layout.setSegmentsChars(segmentChars); +// layout.setWidth(width); +// layout.setSpacing(lineSpacing); +// layout.setTabs(tabs); +// layout.setDefaultTabWidth(tabLength); +// layout.setIndent(indent); +// layout.setVerticalIndent(verticalIndent); +// layout.setWrapIndent(wrapIndent); +// layout.setAlignment(alignment); +// layout.setJustify(justify); +// layout.setTextDirection(textDirection); +// // apply styles, must be done after layout.setText() +// for (StyleEntry styleEntry : styleEntries) { +// layout.setStyle(styleEntry.style, styleEntry.start, styleEntry.end); +// } +// +// if (styledText != null && styledText.ime != null) { +// IME ime = styledText.ime; +// int compositionOffset = ime.getCompositionOffset(); +// if (compositionOffset != -1 && compositionOffset <= content.getCharCount()) { +// int commitCount = ime.getCommitCount(); +// int compositionLength = ime.getText().length(); +// if (compositionLength != commitCount) { +// int compositionLine = content.getLineAtOffset(compositionOffset); +// if (compositionLine == lineIndex) { +// int[] imeRanges = ime.getRanges(); +// TextStyle[] imeStyles = ime.getStyles(); +// if (imeRanges.length > 0) { +// for (int i = 0; i < imeStyles.length; i++) { +// int start = imeRanges[i*2] - lineOffset; +// int end = imeRanges[i*2+1] - lineOffset; +// TextStyle imeStyle = imeStyles[i], userStyle; +// for (int j = start; j <= end; j++) { +// if (!(0 <= j && j < length)) break; +// userStyle = layout.getStyle(cap(layout, j)); +// if (userStyle == null && j > 0) userStyle = layout.getStyle(cap(layout, j - 1)); +// if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(cap(layout, j + 1)); +// if (userStyle == null) { +// layout.setStyle(imeStyle, j, j); +// } else { +// TextStyle newStyle = new TextStyle(imeStyle); +// if (newStyle.font == null) newStyle.font = userStyle.font; +// if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground; +// if (newStyle.background == null) newStyle.background = userStyle.background; +// layout.setStyle(newStyle, j, j); +// } +// } +// } +// } else { +// int start = compositionOffset - lineOffset; +// int end = start + compositionLength - 1; +// TextStyle userStyle = layout.getStyle(cap(layout, start)); +// if (userStyle == null) { +// if (start > 0) userStyle = layout.getStyle(cap(layout, start - 1)); +// if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(cap(layout, end + 1)); +// if (userStyle != null) { +// TextStyle newStyle = new TextStyle(); +// newStyle.font = userStyle.font; +// newStyle.foreground = userStyle.foreground; +// newStyle.background = userStyle.background; +// layout.setStyle(newStyle, start, end); +// } +// } +// } +// } +// } +// } +// } +// +// if (styledText != null && styledText.isFixedLineHeight()) { +// int index = -1; +// int lineCount = layout.getLineCount(); +// int height = getLineHeight(); +// for (int i = 0; i < lineCount; i++) { +// int lineHeight = layout.getLineBounds(i).height; +// if (lineHeight > height) { +// height = lineHeight; +// index = i; +// } +// } +// if (index != -1) { +// FontMetrics metrics = layout.getLineMetrics(index); +// ascent = metrics.getAscent() + metrics.getLeading(); +// descent = metrics.getDescent(); +// if (layouts != null) { +// for (TextLayout l : layouts) { +// if (l != null && l != layout) { +// l.setAscent(ascent); +// l.setDescent(descent); +// } +// } +// } +// styledText.calculateScrollBars(); +// if (styledText.verticalScrollOffset != 0) { +// int topIndex = styledText.topIndex; +// int topIndexY = styledText.topIndexY; +// int lineHeight = getLineHeight(); +// int newVerticalScrollOffset; +// if (topIndexY >= 0) { +// newVerticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY; +// } else { +// newVerticalScrollOffset = topIndex * lineHeight - topIndexY; +// } +// styledText.scrollVertical(newVerticalScrollOffset - styledText.verticalScrollOffset, true); +// } +// if (styledText.isBidiCaret()) styledText.createCaretBitmaps(); +// styledText.caretDirection = SWT.NULL; +// styledText.setCaretLocations(); +// styledText.redraw(); +// } +// } +// return layout; +//} +//int getWidth() { +// return maxWidth; +//} +//void reset() { +// if (layouts != null) { +// for (TextLayout layout : layouts) { +// if (layout != null) layout.dispose(); +// } +// layouts = null; +// } +// topIndex = -1; +// stylesSetCount = styleCount = lineCount = 0; +// ranges = null; +// styles = null; +// stylesSet = null; +// lines = null; +// lineSizes = null; +// bullets = null; +// bulletsIndices = null; +// redrawLines = null; +// hasLinks = false; +//} +//void reset(int startLine, int lineCount) { +// int endLine = startLine + lineCount; +// if (startLine < 0 || endLine > lineSizes.length) return; +// SortedSet lines = new TreeSet<>(); +// for (int i = startLine; i < endLine; i++) { +// lines.add(Integer.valueOf(i)); +// } +// reset(lines); +//} +//void reset(Set lines) { +// if (lines == null || lines.isEmpty()) return; +// int resetLineCount = 0; +// for (Integer line : lines) { +// if (line >= 0 || line < lineCount) { +// resetLineCount++; +// getLineSize(line.intValue()).resetSize(); +// } +// } +// if (linesInAverageLineHeight > resetLineCount) { +// linesInAverageLineHeight -= resetLineCount; +// } else { +// linesInAverageLineHeight = 0; +// averageLineHeight = 0.0f; +// } +// if (lines.contains(Integer.valueOf(maxWidthLineIndex))) { +// maxWidth = 0; +// maxWidthLineIndex = -1; +// if (resetLineCount != this.lineCount) { +// for (int i = 0; i < this.lineCount; i++) { +// LineSizeInfo lineSize = getLineSize(i); +// if (lineSize.width > maxWidth) { +// maxWidth = lineSize.width; +// maxWidthLineIndex = i; +// } +// } +// } +// } +//} +//void setContent(StyledTextContent content) { +// reset(); +// this.content = content; +// lineCount = content.getLineCount(); +// lineSizes = new LineSizeInfo[lineCount]; +// maxWidth = 0; +// maxWidthLineIndex = -1; +// reset(0, lineCount); +//} +// +///** +// * See {@link TextLayout#setFixedLineMetrics} +// * +// * @since 3.125 +// */ +//public void setFixedLineMetrics(FontMetrics metrics) { +// fixedLineMetrics = metrics; +//} +// +//void setFont(Font font, int tabs) { +// TextLayout layout = new TextLayout(device); +// layout.setFont(regularFont); +// tabLength = tabs; +// if (font != null) { +// if (boldFont != null) boldFont.dispose(); +// if (italicFont != null) italicFont.dispose(); +// if (boldItalicFont != null) boldItalicFont.dispose(); +// boldFont = italicFont = boldItalicFont = null; +// regularFont = font; +// layout.setText(" "); +// layout.setFont(font); +// layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0); +// layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1); +// layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2); +// layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3); +// FontMetrics metrics = layout.getLineMetrics(0); +// ascent = metrics.getAscent() + metrics.getLeading(); +// descent = metrics.getDescent(); +// boldFont.dispose(); +// italicFont.dispose(); +// boldItalicFont.dispose(); +// boldFont = italicFont = boldItalicFont = null; +// } +// layout.dispose(); +// layout = new TextLayout(device); +// layout.setFont(regularFont); +// StringBuilder tabBuffer = new StringBuilder(tabs); +// for (int i = 0; i < tabs; i++) { +// tabBuffer.append(' '); +// } +// layout.setText(tabBuffer.toString()); +// tabWidth = layout.getBounds().width; +// layout.dispose(); +// if (styledText != null) { +// GC gc = new GC(styledText); +// averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth(); +// fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$ +// gc.dispose(); +// } +//} +//void setLineAlignment(int startLine, int count, int alignment) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= ALIGNMENT; +// lines[i].alignment = alignment; +// } +//} +//void setLineBackground(int startLine, int count, Color background) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= BACKGROUND; +// lines[i].background = background; +// } +//} +//void setLineBullet(int startLine, int count, Bullet bullet) { +// if (bulletsIndices != null) { +// bulletsIndices = null; +// bullets = null; +// } +// if (bullets == null) { +// if (bullet == null) return; +// bullets = new Bullet[1]; +// bullets[0] = bullet; +// } +// int index = 0; +// while (index < bullets.length) { +// if (bullet == bullets[index]) break; +// index++; +// } +// if (bullet != null) { +// if (index == bullets.length) { +// Bullet[] newBulletsList = new Bullet[bullets.length + 1]; +// System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length); +// newBulletsList[index] = bullet; +// bullets = newBulletsList; +// } +// bullet.addIndices(startLine, count); +// } else { +// updateBullets(startLine, count, 0, false); +// styledText.redrawLinesBullet(redrawLines); +// redrawLines = null; +// } +//} +//void setLineIndent(int startLine, int count, int indent) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= INDENT; +// lines[i].indent = indent; +// } +//} +//void setLineVerticalIndent(int lineIndex, int verticalLineIndent) { +// if (lines == null) +// lines = new LineInfo[lineCount]; +// if (lines[lineIndex] == null) { +// lines[lineIndex] = new LineInfo(); +// } +// lines[lineIndex].flags |= VERTICAL_INDENT; +// int delta = verticalLineIndent - lines[lineIndex].verticalIndent; +// lines[lineIndex].verticalIndent = verticalLineIndent; +// LineSizeInfo info = getLineSize(lineIndex); +// if (!info.needsRecalculateHeight()) { +// info.height += delta; +// } +//} +//void setLineWrapIndent(int startLine, int count, int wrapIndent) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= WRAP_INDENT; +// lines[i].wrapIndent = wrapIndent; +// } +//} +//void setLineJustify(int startLine, int count, boolean justify) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= JUSTIFY; +// lines[i].justify = justify; +// } +//} +//void setLineSegments(int startLine, int count, int[] segments) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= SEGMENTS; +// lines[i].segments = segments; +// } +//} +//void setLineSegmentChars(int startLine, int count, char[] segmentChars) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= SEGMENT_CHARS; +// lines[i].segmentsChars = segmentChars; +// } +//} +//void setLineTabStops(int startLine, int count, int[] tabStops) { +// if (lines == null) lines = new LineInfo[lineCount]; +// for (int i = startLine; i < startLine + count; i++) { +// if (lines[i] == null) { +// lines[i] = new LineInfo(); +// } +// lines[i].flags |= TABSTOPS; +// lines[i].tabStops = tabStops; +// } +//} +//void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) { +// this.lineSpacingProvider = lineSpacingProvider; +//} +//void setStyleRanges (int[] newRanges, StyleRange[] newStyles) { +// if (newStyles == null) { +// stylesSetCount = styleCount = 0; +// ranges = null; +// styles = null; +// stylesSet = null; +// hasLinks = false; +// return; +// } +// if (newRanges == null && COMPACT_STYLES) { +// newRanges = new int[newStyles.length << 1]; +// StyleRange[] tmpStyles = new StyleRange[newStyles.length]; +// if (stylesSet == null) stylesSet = new StyleRange[4]; +// for (int i = 0, j = 0; i < newStyles.length; i++) { +// StyleRange newStyle = newStyles[i]; +// newRanges[j++] = newStyle.start; +// newRanges[j++] = newStyle.length; +// int index = 0; +// while (index < stylesSetCount) { +// if (stylesSet[index].similarTo(newStyle)) break; +// index++; +// } +// if (index == stylesSetCount) { +// if (stylesSetCount == stylesSet.length) { +// StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4]; +// System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount); +// stylesSet = tmpStylesSet; +// } +// stylesSet[stylesSetCount++] = newStyle; +// } +// tmpStyles[i] = stylesSet[index]; +// } +// newStyles = tmpStyles; +// } +// +// if (styleCount == 0) { +// if (newRanges != null) { +// ranges = new int[newRanges.length]; +// System.arraycopy(newRanges, 0, ranges, 0, ranges.length); +// } +// styles = new StyleRange[newStyles.length]; +// System.arraycopy(newStyles, 0, styles, 0, styles.length); +// styleCount = newStyles.length; +// return; +// } +// if (newRanges != null && ranges == null) { +// ranges = new int[styles.length << 1]; +// for (int i = 0, j = 0; i < styleCount; i++) { +// ranges[j++] = styles[i].start; +// ranges[j++] = styles[i].length; +// } +// } +// if (newRanges == null && ranges != null) { +// newRanges = new int[newStyles.length << 1]; +// for (int i = 0, j = 0; i < newStyles.length; i++) { +// newRanges[j++] = newStyles[i].start; +// newRanges[j++] = newStyles[i].length; +// } +// } +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// int start = newRanges[0]; +// int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd; +// boolean insert = modifyStart == rangeCount; +// if (!insert) { +// int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1]; +// modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); +// insert = modifyStart == modifyEnd && ranges[modifyStart] >= end; +// } +// if (insert) { +// addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart); +// return; +// } +// modifyEnd = modifyStart; +// int[] mergeRanges = new int[6]; +// StyleRange[] mergeStyles = new StyleRange[3]; +// for (int i = 0; i < newRanges.length; i += 2) { +// int newStart = newRanges[i]; +// int newEnd = newStart + newRanges[i + 1]; +// if (newStart == newEnd) continue; +// int modifyLast = 0, mergeCount = 0; +// while (modifyEnd < rangeCount) { +// if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2; +// if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break; +// modifyEnd += 2; +// } +// if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) { +// mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1]; +// mergeRanges[mergeCount] = ranges[modifyStart]; +// mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart]; +// mergeCount += 2; +// } +// mergeStyles[mergeCount >> 1] = newStyles[i >> 1]; +// mergeRanges[mergeCount] = newStart; +// mergeRanges[mergeCount + 1] = newRanges[i + 1]; +// mergeCount += 2; +// if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) { +// mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1]; +// mergeRanges[mergeCount] = newEnd; +// mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd; +// mergeCount += 2; +// modifyLast = 2; +// } +// int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); +// rangeCount += grow; +// modifyStart = modifyEnd += grow; +// } +// } else { +// int start = newStyles[0].start; +// int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd; +// boolean insert = modifyStart == styleCount; +// if (!insert) { +// int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length; +// modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); +// insert = modifyStart == modifyEnd && styles[modifyStart].start >= end; +// } +// if (insert) { +// addMerge(newStyles, newStyles.length, modifyStart, modifyStart); +// return; +// } +// modifyEnd = modifyStart; +// StyleRange[] mergeStyles = new StyleRange[3]; +// for (StyleRange newStyle : newStyles) { +// StyleRange style; +// int newStart = newStyle.start; +// int newEnd = newStart + newStyle.length; +// if (newStart == newEnd) continue; +// int modifyLast = 0, mergeCount = 0; +// while (modifyEnd < styleCount) { +// if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++; +// if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break; +// modifyEnd++; +// } +// style = styles[modifyStart]; +// if (style.start < newStart && newStart < style.start + style.length) { +// style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); +// style.length = newStart - style.start; +// } +// mergeStyles[mergeCount++] = newStyle; +// if (modifyEnd < styleCount) { +// style = styles[modifyEnd]; +// if (style.start < newEnd && newEnd < style.start + style.length) { +// style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); +// style.length += style.start - newEnd; +// style.start = newEnd; +// modifyLast = 1; +// } +// } +// int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); +// modifyStart = modifyEnd += grow; +// } +// } +//} +//void textChanging(TextChangingEvent event) { +// int start = event.start; +// int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount; +// int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount; +// +// updateRanges(start, replaceCharCount, newCharCount); +// +// int startLine = content.getLineAtOffset(start); +// if (replaceCharCount == content.getCharCount()) lines = null; +// if (replaceLineCount == lineCount) { +// lineCount = newLineCount; +// lineSizes = new LineSizeInfo[lineCount]; +// reset(0, lineCount); +// } else { +// int startIndex = startLine + replaceLineCount + 1; +// int endIndex = startLine + newLineCount + 1; +// if(lineCount < startLine) { +// SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startLine: " + lineCount + ":" + startLine); +// } +// if(lineCount < startIndex) { +// SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startIndex: " + lineCount + ":" + startIndex); +// } +// int delta = newLineCount - replaceLineCount; +// if (lineCount + delta > lineSizes.length) { +// LineSizeInfo[] newLineSizes = new LineSizeInfo[lineCount + delta + GROW]; +// System.arraycopy(lineSizes, 0, newLineSizes, 0, lineCount); +// lineSizes = newLineSizes; +// } +// if (lines != null) { +// if (lineCount + delta > lines.length) { +// LineInfo[] newLines = new LineInfo[lineCount + delta + GROW]; +// System.arraycopy(lines, 0, newLines, 0, lineCount); +// lines = newLines; +// } +// } +// System.arraycopy(lineSizes, startIndex, lineSizes, endIndex, lineCount - startIndex); +// for (int i = startLine; i < endIndex; i++) { +// lineSizes[i] = null; +// } +// for (int i = lineCount + delta; i < lineCount; i++) { +// lineSizes[i] = null; +// } +// if (layouts != null) { +// int layoutStartLine = startLine - topIndex; +// int layoutEndLine = layoutStartLine + replaceLineCount + 1; +// for (int i = layoutStartLine; i < layoutEndLine; i++) { +// if (0 <= i && i < layouts.length) { +// if (layouts[i] != null) layouts[i].dispose(); +// layouts[i] = null; +// if (bullets != null && bulletsIndices != null) bullets[i] = null; +// } +// } +// if (delta > 0) { +// for (int i = layouts.length - 1; i >= layoutEndLine; i--) { +// if (0 <= i && i < layouts.length) { +// endIndex = i + delta; +// if (0 <= endIndex && endIndex < layouts.length) { +// layouts[endIndex] = layouts[i]; +// layouts[i] = null; +// if (bullets != null && bulletsIndices != null) { +// bullets[endIndex] = bullets[i]; +// bulletsIndices[endIndex] = bulletsIndices[i]; +// bullets[i] = null; +// } +// } else { +// if (layouts[i] != null) layouts[i].dispose(); +// layouts[i] = null; +// if (bullets != null && bulletsIndices != null) bullets[i] = null; +// } +// } +// } +// } else if (delta < 0) { +// for (int i = layoutEndLine; i < layouts.length; i++) { +// if (0 <= i && i < layouts.length) { +// endIndex = i + delta; +// if (0 <= endIndex && endIndex < layouts.length) { +// layouts[endIndex] = layouts[i]; +// layouts[i] = null; +// if (bullets != null && bulletsIndices != null) { +// bullets[endIndex] = bullets[i]; +// bulletsIndices[endIndex] = bulletsIndices[i]; +// bullets[i] = null; +// } +// } else { +// if (layouts[i] != null) layouts[i].dispose(); +// layouts[i] = null; +// if (bullets != null && bulletsIndices != null) bullets[i] = null; +// } +// } +// } +// } +// } +// if (replaceLineCount != 0 || newLineCount != 0) { +// int startLineOffset = content.getOffsetAtLine(startLine); +// if (startLineOffset != start) startLine++; +// updateBullets(startLine, replaceLineCount, newLineCount, true); +// if (lines != null) { +// startIndex = startLine + replaceLineCount; +// endIndex = startLine + newLineCount; +// System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex); +// for (int i = startLine; i < endIndex; i++) { +// lines[i] = null; +// } +// for (int i = lineCount + delta; i < lineCount; i++) { +// lines[i] = null; +// } +// } +// } +// lineCount += delta; +// if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) { +// maxWidth = 0; +// maxWidthLineIndex = -1; +// for (int i = 0; i < lineCount; i++) { +// LineSizeInfo lineSize = getLineSize(i); +// if (lineSize.width > maxWidth) { +// maxWidth = lineSize.width; +// maxWidthLineIndex = i; +// } +// } +// } +// } +//} +//void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) { +// if (bullets == null) return; +// if (bulletsIndices != null) return; +// for (Bullet bullet : bullets) { +// int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update); +// if (lines != null) { +// if (redrawLines == null) { +// redrawLines = lines; +// } else { +// int[] newRedrawBullets = new int[redrawLines.length + lines.length]; +// System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length); +// System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length); +// redrawLines = newRedrawBullets; +// } +// } +// } +// int removed = 0; +// for (Bullet bullet : bullets) { +// if (bullet.size() == 0) removed++; +// } +// if (removed > 0) { +// if (removed == bullets.length) { +// bullets = null; +// } else { +// Bullet[] newBulletsList = new Bullet[bullets.length - removed]; +// for (int i = 0, j = 0; i < bullets.length; i++) { +// Bullet bullet = bullets[i]; +// if (bullet.size() > 0) newBulletsList[j++] = bullet; +// } +// bullets = newBulletsList; +// } +// } +//} +//void updateRanges(int start, int replaceCharCount, int newCharCount) { +// if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return; +// if (ranges != null) { +// int rangeCount = styleCount << 1; +// int modifyStart = getRangeIndex(start, -1, rangeCount); +// if (modifyStart == rangeCount) return; +// int end = start + replaceCharCount; +// int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); +// int offset = newCharCount - replaceCharCount; +// if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { +// if (newCharCount == 0) { +// ranges[modifyStart + 1] -= replaceCharCount; +// modifyEnd += 2; +// } else { +// if (rangeCount + 2 > ranges.length) { +// int[] newRanges = new int[ranges.length + (GROW << 1)]; +// System.arraycopy(ranges, 0, newRanges, 0, rangeCount); +// ranges = newRanges; +// StyleRange[] newStyles = new StyleRange[styles.length + GROW]; +// System.arraycopy(styles, 0, newStyles, 0, styleCount); +// styles = newStyles; +// } +// System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2)); +// System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1)); +// ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end; +// ranges[modifyStart + 2] = start + newCharCount; +// ranges[modifyStart + 1] = start - ranges[modifyStart]; +// styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1]; +// rangeCount += 2; +// styleCount++; +// modifyEnd += 4; +// } +// if (offset != 0) { +// for (int i = modifyEnd; i < rangeCount; i += 2) { +// ranges[i] += offset; +// } +// } +// } else { +// if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) { +// ranges[modifyStart + 1] = start - ranges[modifyStart]; +// modifyStart += 2; +// } +// if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { +// ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end; +// ranges[modifyEnd] = end; +// } +// if (offset != 0) { +// for (int i = modifyEnd; i < rangeCount; i += 2) { +// ranges[i] += offset; +// } +// } +// System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd); +// System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1)); +// styleCount -= (modifyEnd - modifyStart) >> 1; +// } +// } else { +// int modifyStart = getRangeIndex(start, -1, styleCount); +// if (modifyStart == styleCount) return; +// int end = start + replaceCharCount; +// int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); +// int offset = newCharCount - replaceCharCount; +// if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) { +// if (newCharCount == 0) { +// styles[modifyStart].length -= replaceCharCount; +// modifyEnd++; +// } else { +// if (styleCount + 1 > styles.length) { +// StyleRange[] newStyles = new StyleRange[styles.length + GROW]; +// System.arraycopy(styles, 0, newStyles, 0, styleCount); +// styles = newStyles; +// } +// System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1)); +// styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone(); +// styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end; +// styles[modifyStart + 1].start = start + newCharCount; +// styles[modifyStart].length = start - styles[modifyStart].start; +// styleCount++; +// modifyEnd += 2; +// } +// if (offset != 0) { +// for (int i = modifyEnd; i < styleCount; i++) { +// styles[i].start += offset; +// } +// } +// } else { +// if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) { +// styles[modifyStart].length = start - styles[modifyStart].start; +// modifyStart++; +// } +// if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) { +// styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end; +// styles[modifyEnd].start = end; +// } +// if (offset != 0) { +// for (int i = modifyEnd; i < styleCount; i++) { +// styles[i].start += offset; +// } +// } +// System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd); +// styleCount -= modifyEnd - modifyStart; +// } +// } +//} +// +//public boolean hasVerticalIndent() { +// return Arrays.stream(lines).filter(Objects::nonNull) // +// .mapToInt(line -> line.verticalIndent) // +// .anyMatch(n -> n != 0); +//} +// +// } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java index b5400430724..e6f5fdcbfc3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java @@ -13,9 +13,6 @@ *******************************************************************************/ package org.eclipse.swt.custom; -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; - /** * The base class encapsulating the logic used to write styled content as * a rich format (HTML, RTF, maybe more). It contains the common parts: @@ -30,247 +27,252 @@ * the stream like they are rendered by the widget. In addition, the * widget font name and size is used for the whole text.

    */ +// TODO (visjee) SWING abstract class StyledTextWriterBase extends TextWriter { - final StyledText styledText; - /** - * Creates a writer that processed content starting at offset "start" - * in the document. {@code start} and {@code length} can be set to specify - * partial lines. - * - * @param start start offset of content to write, 0 based from beginning of document - * @param length length of content to write - * @param styledText the widget to produce the RTF from - */ - public StyledTextWriterBase(StyledText styledText, int start, int length) { + public StyledTextWriterBase(int start, int length) { super(start, length); - this.styledText = styledText; - } - - /** - * Appends the specified segment of "string" to the output data. - * Copy from {@code start} up to, but excluding, {@code end}. - * - * @param string string to copy a segment from. Must not contain line breaks. - * Line breaks should be written using {@link #writeLineDelimiter()} - * @param start start offset of segment. 0 based. - * @param end end offset of segment - */ - void writeEscaped(String string, int start, int end) { - String textToWrite = string.substring(start, end); - write(escapeText(textToWrite)); - } - - /** - * Appends the specified line text to the output data. Lines will be formatted - * using the styles queried from the LineStyleListener, if set, or those set - * directly in the widget. - * - * @param line line text to write. Must not contain line breaks - * Line breaks should be written using {@link #writeLineDelimiter(String)} - * @param lineOffset offset of the line. 0 based from the start of the - * widget document. Any text occurring before the start offset or after the - * end offset specified during object creation is ignored. - * - * @throws SWTException {@code ERROR_IO} when the writer is closed. - */ - @Override - public void writeLine(String line, int lineOffset) { - if (isClosed()) { - SWT.error(SWT.ERROR_IO); - } - - int lineIndex = styledText.content.getLineAtOffset(lineOffset); - int lineAlignment; - int lineIndent; - boolean lineJustify; - int verticalIndent; - int[] ranges; - StyleRange[] styles; - - StyledTextEvent event = styledText.getLineStyleData(lineOffset, line); - if (event != null) { - verticalIndent = event.verticalIndent; - lineAlignment = event.alignment; - lineIndent = event.indent; - lineJustify = event.justify; - ranges = event.ranges; - styles = event.styles; - } else { - verticalIndent = styledText.renderer.getLineVerticalIndent(lineIndex); - lineAlignment = styledText.renderer.getLineAlignment(lineIndex, styledText.alignment); - lineIndent = styledText.renderer.getLineIndent(lineIndex, styledText.indent); - lineJustify = styledText.renderer.getLineJustify(lineIndex, styledText.justify); - ranges = styledText.renderer.getRanges(lineOffset, line.length()); - styles = styledText.renderer.getStyleRanges(lineOffset, line.length(), false); - } - - if (styles == null) { - styles = new StyleRange[0]; - } - - event = styledText.getLineBackgroundData(lineOffset, line); - Color lineBackground = (event != null && event.lineBackground != null) - ? event.lineBackground - : styledText.renderer.getLineBackground(lineIndex, null); - - writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, verticalIndent, lineAlignment, lineJustify); - } - - /** - * Appends the specified line text to the output data. - * - *

    Use the colors and font styles specified in {@code styles} and {@code lineBackground}. - * Formatting is written to reflect the text rendering by the text widget. - * Style background colors take precedence over the line background color.

    - * - * @param line line text to write as RTF. Must not contain line breaks - * Line breaks should be written using writeLineDelimiter() - * @param lineOffset offset of the line. 0 based from the start of the - * widget document. Any text occurring before the start offset or after the - * end offset specified during object creation is ignored. - * @param styles styles to use for formatting. Must not be null. - * @param lineBackground line background color to use for formatting. - * May be null. - */ - void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, - Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { - - int lineLength = line.length(); - int startOffset = getStart(); - int writeOffset = startOffset - lineOffset; - if (writeOffset >= lineLength) { - return; - } - int lineIndex = Math.max(0, writeOffset); - - String atLineEnd = writeLineStart(lineBackground, indent, verticalIndent, alignment, justify); - - int endOffset = startOffset + super.getCharCount(); - - // We are already at the end, should not write an empty paragraph - if (lineOffset >= endOffset) { - return; - } - - int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); - - int outTextLen = 0; // collect the length of the text we output (unescaped) - for (int i = 0; i < styles.length; i++) { - StyleRange style = styles[i]; - int start, end; - if (ranges != null) { - start = ranges[i << 1] - lineOffset; - end = start + ranges[(i << 1) + 1]; - } else { - start = style.start - lineOffset; - end = start + style.length; - } - // skip over partial first line - if (end < writeOffset) { - continue; - } - // style starts beyond line end or write end - if (start >= lineEndOffset) { - break; - } - // write any unstyled text - if (lineIndex < start) { - // copy to start of style - // style starting beyond end of write range or end of line - // is guarded against above. - writeEscaped(line, lineIndex, start); - outTextLen += start - lineIndex; - lineIndex = start; - } - // write styled text - String atSpanEnd = writeSpanStart(style); - - // copy to end of style or end of write range or end of line - int copyEnd = Math.min(end, lineEndOffset); - // guard against invalid styles and let style processing continue - copyEnd = Math.max(copyEnd, lineIndex); - writeEscaped(line, lineIndex, copyEnd); - outTextLen += copyEnd - lineIndex; - - writeSpanEnd(atSpanEnd); - - lineIndex = copyEnd; - } - - // write the unstyled text at the end of the line - if (lineIndex < lineEndOffset) { - writeEscaped(line, lineIndex, lineEndOffset); - outTextLen += lineEndOffset - lineIndex; - } - - if (outTextLen == 0) { - writeEmptyLine(); - } - - writeLineEnd(atLineEnd); - } - - /** - * Writes the part that only shows once, at the beginning of the output data. - */ - abstract void writeHeader(); - - /** - * Takes plain text and returns the same text escaped using the rules of the output format. - * @param text the text to escape - * @return the escaped text - */ - abstract String escapeText(String text); - - /** - * Invoked at the beginning of each line in the original widget. - * - *

    It should output whatever tags are appropriate to start a new line in the output format.
    - * It will return the text that has to be output at the end of the line.

    - * - * @return the text to append at the end of the line - */ - abstract String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify); - - /** - * Invoked at the end of of each line in the original widget. - * - *

    It receives whatever text {@link #writeLineStart(Color,int,int,int,boolean)} returned - * and it will output it. A class might override it to do more.

    - * - * @param prepared the leftover text prepared by {@code writeLineStart} - */ - void writeLineEnd(String prepared) { - write(prepared); - } - - /** - * Invoked at the end of each line, writeLineEnd, if there was no text output. - * - *

    This is needed for HTML, which does not render empty paragraphs.

    - */ - abstract void writeEmptyLine(); - - /** - * Invoked at the beginning of each styled span fragment in the original widget. - * - *

    It should output whatever tags are appropriate to start a formatted span in the output format.
    - * It will return the text that has to be output at the end of the span (to close it).

    - * - * @return the text to append at the end of the styled span - */ - abstract String writeSpanStart(StyleRange style); - - /** - * Invoked at the end of of each styled span fragment in the original widget. - * - *

    It receives whatever text {@link #writeSpanStart(StyleRange)} returned - * and it will output it. A class might override it to do more.

    - * - * @param prepared the leftover text prepared by {@code writeSpanStart} - */ - void writeSpanEnd(String prepared) { - write(prepared); } +// final StyledText styledText; +// +// /** +// * Creates a writer that processed content starting at offset "start" +// * in the document. {@code start} and {@code length} can be set to specify +// * partial lines. +// * +// * @param start start offset of content to write, 0 based from beginning of document +// * @param length length of content to write +// * @param styledText the widget to produce the RTF from +// */ +// public StyledTextWriterBase(StyledText styledText, int start, int length) { +// super(start, length); +// this.styledText = styledText; +// } +// +// /** +// * Appends the specified segment of "string" to the output data. +// * Copy from {@code start} up to, but excluding, {@code end}. +// * +// * @param string string to copy a segment from. Must not contain line breaks. +// * Line breaks should be written using {@link #writeLineDelimiter()} +// * @param start start offset of segment. 0 based. +// * @param end end offset of segment +// */ +// void writeEscaped(String string, int start, int end) { +// String textToWrite = string.substring(start, end); +// write(escapeText(textToWrite)); +// } +// +// /** +// * Appends the specified line text to the output data. Lines will be formatted +// * using the styles queried from the LineStyleListener, if set, or those set +// * directly in the widget. +// * +// * @param line line text to write. Must not contain line breaks +// * Line breaks should be written using {@link #writeLineDelimiter(String)} +// * @param lineOffset offset of the line. 0 based from the start of the +// * widget document. Any text occurring before the start offset or after the +// * end offset specified during object creation is ignored. +// * +// * @throws SWTException {@code ERROR_IO} when the writer is closed. +// */ +// @Override +// public void writeLine(String line, int lineOffset) { +// if (isClosed()) { +// SWT.error(SWT.ERROR_IO); +// } +// +// int lineIndex = styledText.content.getLineAtOffset(lineOffset); +// int lineAlignment; +// int lineIndent; +// boolean lineJustify; +// int verticalIndent; +// int[] ranges; +// StyleRange[] styles; +// +// StyledTextEvent event = styledText.getLineStyleData(lineOffset, line); +// if (event != null) { +// verticalIndent = event.verticalIndent; +// lineAlignment = event.alignment; +// lineIndent = event.indent; +// lineJustify = event.justify; +// ranges = event.ranges; +// styles = event.styles; +// } else { +// verticalIndent = styledText.renderer.getLineVerticalIndent(lineIndex); +// lineAlignment = styledText.renderer.getLineAlignment(lineIndex, styledText.alignment); +// lineIndent = styledText.renderer.getLineIndent(lineIndex, styledText.indent); +// lineJustify = styledText.renderer.getLineJustify(lineIndex, styledText.justify); +// ranges = styledText.renderer.getRanges(lineOffset, line.length()); +// styles = styledText.renderer.getStyleRanges(lineOffset, line.length(), false); +// } +// +// if (styles == null) { +// styles = new StyleRange[0]; +// } +// +// event = styledText.getLineBackgroundData(lineOffset, line); +// Color lineBackground = (event != null && event.lineBackground != null) +// ? event.lineBackground +// : styledText.renderer.getLineBackground(lineIndex, null); +// +// writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, verticalIndent, lineAlignment, lineJustify); +// } +// +// /** +// * Appends the specified line text to the output data. +// * +// *

    Use the colors and font styles specified in {@code styles} and {@code lineBackground}. +// * Formatting is written to reflect the text rendering by the text widget. +// * Style background colors take precedence over the line background color.

    +// * +// * @param line line text to write as RTF. Must not contain line breaks +// * Line breaks should be written using writeLineDelimiter() +// * @param lineOffset offset of the line. 0 based from the start of the +// * widget document. Any text occurring before the start offset or after the +// * end offset specified during object creation is ignored. +// * @param styles styles to use for formatting. Must not be null. +// * @param lineBackground line background color to use for formatting. +// * May be null. +// */ +// void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, +// Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { +// +// int lineLength = line.length(); +// int startOffset = getStart(); +// int writeOffset = startOffset - lineOffset; +// if (writeOffset >= lineLength) { +// return; +// } +// int lineIndex = Math.max(0, writeOffset); +// +// String atLineEnd = writeLineStart(lineBackground, indent, verticalIndent, alignment, justify); +// +// int endOffset = startOffset + super.getCharCount(); +// +// // We are already at the end, should not write an empty paragraph +// if (lineOffset >= endOffset) { +// return; +// } +// +// int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); +// +// int outTextLen = 0; // collect the length of the text we output (unescaped) +// for (int i = 0; i < styles.length; i++) { +// StyleRange style = styles[i]; +// int start, end; +// if (ranges != null) { +// start = ranges[i << 1] - lineOffset; +// end = start + ranges[(i << 1) + 1]; +// } else { +// start = style.start - lineOffset; +// end = start + style.length; +// } +// // skip over partial first line +// if (end < writeOffset) { +// continue; +// } +// // style starts beyond line end or write end +// if (start >= lineEndOffset) { +// break; +// } +// // write any unstyled text +// if (lineIndex < start) { +// // copy to start of style +// // style starting beyond end of write range or end of line +// // is guarded against above. +// writeEscaped(line, lineIndex, start); +// outTextLen += start - lineIndex; +// lineIndex = start; +// } +// // write styled text +// String atSpanEnd = writeSpanStart(style); +// +// // copy to end of style or end of write range or end of line +// int copyEnd = Math.min(end, lineEndOffset); +// // guard against invalid styles and let style processing continue +// copyEnd = Math.max(copyEnd, lineIndex); +// writeEscaped(line, lineIndex, copyEnd); +// outTextLen += copyEnd - lineIndex; +// +// writeSpanEnd(atSpanEnd); +// +// lineIndex = copyEnd; +// } +// +// // write the unstyled text at the end of the line +// if (lineIndex < lineEndOffset) { +// writeEscaped(line, lineIndex, lineEndOffset); +// outTextLen += lineEndOffset - lineIndex; +// } +// +// if (outTextLen == 0) { +// writeEmptyLine(); +// } +// +// writeLineEnd(atLineEnd); +// } +// +// /** +// * Writes the part that only shows once, at the beginning of the output data. +// */ +// abstract void writeHeader(); +// +// /** +// * Takes plain text and returns the same text escaped using the rules of the output format. +// * @param text the text to escape +// * @return the escaped text +// */ +// abstract String escapeText(String text); +// +// /** +// * Invoked at the beginning of each line in the original widget. +// * +// *

    It should output whatever tags are appropriate to start a new line in the output format.
    +// * It will return the text that has to be output at the end of the line.

    +// * +// * @return the text to append at the end of the line +// */ +// abstract String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify); +// +// /** +// * Invoked at the end of of each line in the original widget. +// * +// *

    It receives whatever text {@link #writeLineStart(Color,int,int,int,boolean)} returned +// * and it will output it. A class might override it to do more.

    +// * +// * @param prepared the leftover text prepared by {@code writeLineStart} +// */ +// void writeLineEnd(String prepared) { +// write(prepared); +// } +// +// /** +// * Invoked at the end of each line, writeLineEnd, if there was no text output. +// * +// *

    This is needed for HTML, which does not render empty paragraphs.

    +// */ +// abstract void writeEmptyLine(); +// +// /** +// * Invoked at the beginning of each styled span fragment in the original widget. +// * +// *

    It should output whatever tags are appropriate to start a formatted span in the output format.
    +// * It will return the text that has to be output at the end of the span (to close it).

    +// * +// * @return the text to append at the end of the styled span +// */ +// abstract String writeSpanStart(StyleRange style); +// +// /** +// * Invoked at the end of of each styled span fragment in the original widget. +// * +// *

    It receives whatever text {@link #writeSpanStart(StyleRange)} returned +// * and it will output it. A class might override it to do more.

    +// * +// * @param prepared the leftover text prepared by {@code writeSpanStart} +// */ +// void writeSpanEnd(String prepared) { +// write(prepared); +// } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java new file mode 100644 index 00000000000..8ac13558d3b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java @@ -0,0 +1,8121 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + + +import java.util.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.accessibility.*; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.printing.*; +import org.eclipse.swt.widgets.*; + +/** + * A StyledText is an editable user interface object that displays lines + * of text. The following style attributes can be defined for the text: + *
      + *
    • foreground color + *
    • background color + *
    • font style (bold, italic, bold-italic, regular) + *
    • underline + *
    • strikeout + *
    + *

    + * In addition to text style attributes, the background color of a line may + * be specified. + *

    + * There are two ways to use this widget when specifying text style information. + * You may use the API that is defined for StyledText or you may define your own + * LineStyleListener. If you define your own listener, you will be responsible + * for maintaining the text style information for the widget. IMPORTANT: You may + * not define your own listener and use the StyledText API. The following + * StyledText API is not supported if you have defined a LineStyleListener: + *

      + *
    • getStyleRangeAtOffset(int) + *
    • getStyleRanges() + *
    • replaceStyleRanges(int,int,StyleRange[]) + *
    • setStyleRange(StyleRange) + *
    • setStyleRanges(StyleRange[]) + *
    + *

    + * There are two ways to use this widget when specifying line background colors. + * You may use the API that is defined for StyledText or you may define your own + * LineBackgroundListener. If you define your own listener, you will be responsible + * for maintaining the line background color information for the widget. + * IMPORTANT: You may not define your own listener and use the StyledText API. + * The following StyledText API is not supported if you have defined a + * LineBackgroundListener: + *

      + *
    • getLineBackground(int) + *
    • setLineBackground(int,int,Color) + *
    + *

    + * The content implementation for this widget may also be user-defined. To do so, + * you must implement the StyledTextContent interface and use the StyledText API + * setContent(StyledTextContent) to initialize the widget. + *

    + *

    + *
    Styles:
    FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP + *
    Events:
    ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class StyledText extends Canvas { + static final char TAB = '\t'; + static final String PlatformLineDelimiter = System.getProperty("line.separator"); + static final int BIDI_CARET_WIDTH = 3; + static final int DEFAULT_WIDTH = 64; + static final int DEFAULT_HEIGHT = 64; + static final int V_SCROLL_RATE = 50; + static final int H_SCROLL_RATE = 10; + + static final int ExtendedModify = 3000; + static final int LineGetBackground = 3001; + static final int LineGetStyle = 3002; + static final int TextChanging = 3003; + static final int TextSet = 3004; + static final int VerifyKey = 3005; + static final int TextChanged = 3006; + static final int LineGetSegments = 3007; + static final int PaintObject = 3008; + + static final int PREVIOUS_OFFSET_TRAILING = 0; + static final int OFFSET_LEADING = 1; + + Color selectionBackground; // selection background color + Color selectionForeground; // selection foreground color + StyledTextContent content; // native content (default or user specified) + StyledTextRenderer renderer; + Listener listener; + TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent + int verticalScrollOffset = 0; // pixel based + int horizontalScrollOffset = 0; // pixel based + int topIndex = 0; // top visible line + int topIndexY; + int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback + int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated + int tabLength = 4; // number of characters in a tab + int leftMargin; + int topMargin; + int rightMargin; + int bottomMargin; + int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 + int caretOffset = 0; + int caretAlignment; + Point selection = new Point(0, 0); // x and y are start and end caret offsets of selection + Point clipboardSelection; // x and y are start and end caret offsets of previous selection + int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text + Point doubleClickSelection; // selection after last mouse double click + boolean editable = true; + boolean wordWrap = false; + boolean doubleClickEnabled = true; // see getDoubleClickEnabled + boolean overwrite = false; // insert/overwrite edit mode + int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. + Hashtable keyActionMap = new Hashtable(); + Color background = null; // workaround for bug 4791 + Color foreground = null; // + Clipboard clipboard; + boolean mouseDown = false; + boolean mouseDoubleClick = false; // true=a double click ocurred. Don't do mouse swipe selection. + int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left) + int autoScrollDistance = 0; + int lastTextChangeStart; // cache data of the + int lastTextChangeNewLineCount; // last text changing + int lastTextChangeNewCharCount; // event for use in the + int lastTextChangeReplaceLineCount; // text changed handler + int lastTextChangeReplaceCharCount; + int lastLineBottom; // the bottom pixel of the last line been replaced + boolean isMirrored; + boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color + Image leftCaretBitmap = null; + Image rightCaretBitmap = null; + int caretDirection = SWT.NULL; + Caret defaultCaret = null; + boolean updateCaretDirection = true; + boolean fixedLineHeight; + boolean dragDetect, dragging; + + int alignment; + boolean justify; + int indent; + int lineSpacing; + + final static boolean IS_CARBON, IS_GTK, IS_MOTIF; + static { + String platform = SWT.getPlatform(); + IS_CARBON = "carbon".equals(platform); + IS_GTK = "gtk".equals(platform); + IS_MOTIF = "motif".equals(platform); + } + + /** + * The Printing class implements printing of a range of text. + * An instance of Printing is returned in the + * StyledText#print(Printer) API. The run() method may be + * invoked from any thread. + */ + static class Printing implements Runnable { + final static int LEFT = 0; // left aligned header/footer segment + final static int CENTER = 1; // centered header/footer segment + final static int RIGHT = 2; // right aligned header/footer segment + + Printer printer; + StyledTextRenderer printerRenderer; + StyledTextPrintOptions printOptions; + Rectangle clientArea; + FontData fontData; + Font printerFont; + Hashtable resources; + int tabLength; + GC gc; // printer GC + int pageWidth; // width of a printer page in pixels + int startPage; // first page to print + int endPage; // last page to print + int startLine; // first (wrapped) line to print + int endLine; // last (wrapped) line to print + boolean singleLine; // widget single line mode + Point selection = null; // selected text + boolean mirrored; // indicates the printing gc should be mirrored + int lineSpacing; + + /** + * Creates an instance of Printing. + * Copies the widget content and rendering data that needs + * to be requested from listeners. + *

    + * @param parent StyledText widget to print. + * @param printer printer device to print on. + * @param printOptions print options + */ + Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { + this.printer = printer; + this.printOptions = printOptions; + this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0; + singleLine = styledText.isSingleLine(); + startPage = 1; + endPage = Integer.MAX_VALUE; + PrinterData data = printer.getPrinterData(); + if (data.scope == PrinterData.PAGE_RANGE) { + startPage = data.startPage; + endPage = data.endPage; + if (endPage < startPage) { + int temp = endPage; + endPage = startPage; + startPage = temp; + } + } else if (data.scope == PrinterData.SELECTION) { + selection = styledText.getSelectionRange(); + } + printerRenderer = new StyledTextRenderer(printer, null); + printerRenderer.setContent(copyContent(styledText.getContent())); + cacheLineData(styledText); + + } + /** + * Caches all line data that needs to be requested from a listener. + *

    + * @param printerContent StyledTextContent to request + * line data for. + */ + void cacheLineData(StyledText styledText) { + StyledTextRenderer renderer = styledText.renderer; + renderer.copyInto(printerRenderer); + fontData = styledText.getFont().getFontData()[0]; + tabLength = styledText.tabLength; + int lineCount = printerRenderer.lineCount; + if (styledText.isListening(LineGetBackground) || (styledText.isBidi() && styledText.isListening(LineGetSegments)) || styledText.isListening(LineGetStyle)) { + StyledTextContent content = printerRenderer.content; + for (int i = 0; i < lineCount; i++) { + String line = content.getLine(i); + int lineOffset = content.getOffsetAtLine(i); + StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line); + if (event != null && event.lineBackground != null) { + printerRenderer.setLineBackground(i, 1, event.lineBackground); + } + if (styledText.isBidi()) { + int[] segments = styledText.getBidiSegments(lineOffset, line); + printerRenderer.setLineSegments(i, 1, segments); + } + event = styledText.getLineStyleData(lineOffset, line); + if (event != null) { + printerRenderer.setLineIndent(i, 1, event.indent); + printerRenderer.setLineAlignment(i, 1, event.alignment); + printerRenderer.setLineJustify(i, 1, event.justify); + printerRenderer.setLineBullet(i, 1, event.bullet); + StyleRange[] styles = event.styles; + if (styles != null && styles.length > 0) { + printerRenderer.setStyleRanges(event.ranges, styles); + } + } + } + } + Point screenDPI = styledText.getDisplay().getDPI(); + Point printerDPI = printer.getDPI(); + resources = new Hashtable (); + for (int i = 0; i < lineCount; i++) { + Color color = printerRenderer.getLineBackground(i, null); + if (color != null) { + if (printOptions.printLineBackground) { + Color printerColor = (Color)resources.get(color); + if (printerColor == null) { + printerColor = new Color (printer, color.getRGB()); + resources.put(color, printerColor); + } + printerRenderer.setLineBackground(i, 1, printerColor); + } else { + printerRenderer.setLineBackground(i, 1, null); + } + } + int indent = printerRenderer.getLineIndent(i, 0); + if (indent != 0) { + printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x); + } + } + StyleRange[] styles = printerRenderer.styles; + for (int i = 0; i < printerRenderer.styleCount; i++) { + StyleRange style = styles[i]; + Font font = style.font; + if (style.font != null) { + Font printerFont = (Font)resources.get(font); + if (printerFont == null) { + printerFont = new Font (printer, font.getFontData()); + resources.put(font, printerFont); + } + style.font = printerFont; + } + Color color = style.foreground; + if (color != null) { + Color printerColor = (Color)resources.get(color); + if (printOptions.printTextForeground) { + if (printerColor == null) { + printerColor = new Color (printer, color.getRGB()); + resources.put(color, printerColor); + } + style.foreground = printerColor; + } else { + style.foreground = null; + } + } + color = style.background; + if (color != null) { + Color printerColor = (Color)resources.get(color); + if (printOptions.printTextBackground) { + if (printerColor == null) { + printerColor = new Color (printer, color.getRGB()); + resources.put(color, printerColor); + } + style.background = printerColor; + } else { + style.background = null; + } + } + if (!printOptions.printTextFontStyle) { + style.fontStyle = SWT.NORMAL; + } + style.rise = style.rise * printerDPI.y / screenDPI.y; + GlyphMetrics metrics = style.metrics; + if (metrics != null) { + metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y; + metrics.descent = metrics.descent * printerDPI.y / screenDPI.y; + metrics.width = metrics.width * printerDPI.x / screenDPI.x; + } + } + lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y; + } + /** + * Copies the text of the specified StyledTextContent. + *

    + * @param original the StyledTextContent to copy. + */ + StyledTextContent copyContent(StyledTextContent original) { + StyledTextContent printerContent = new DefaultContent(); + int insertOffset = 0; + for (int i = 0; i < original.getLineCount(); i++) { + int insertEndOffset; + if (i < original.getLineCount() - 1) { + insertEndOffset = original.getOffsetAtLine(i + 1); + } else { + insertEndOffset = original.getCharCount(); + } + printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset)); + insertOffset = insertEndOffset; + } + return printerContent; + } + /** + * Disposes of the resources and the PrintRenderer. + */ + void dispose() { + if (gc != null) { + gc.dispose(); + gc = null; + } + if (resources != null) { + Enumeration enumeration = resources.elements(); + while (enumeration.hasMoreElements()) { + Resource resource = (Resource) enumeration.nextElement(); + resource.dispose(); + } + resources = null; + } + if (printerFont != null) { + printerFont.dispose(); + printerFont = null; + } + if (printerRenderer != null) { + printerRenderer.dispose(); + printerRenderer = null; + } + } + void init() { + Rectangle trim = printer.computeTrim(0, 0, 0, 0); + Point dpi = printer.getDPI(); + + printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL); + clientArea = printer.getClientArea(); + pageWidth = clientArea.width; + // one inch margin around text + clientArea.x = dpi.x + trim.x; + clientArea.y = dpi.y + trim.y; + clientArea.width -= (clientArea.x + trim.width); + clientArea.height -= (clientArea.y + trim.height); + + int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; + gc = new GC(printer, style); + gc.setFont(printerFont); + printerRenderer.setFont(printerFont, tabLength); + int lineHeight = printerRenderer.getLineHeight(); + if (printOptions.header != null) { + clientArea.y += lineHeight * 2; + clientArea.height -= lineHeight * 2; + } + if (printOptions.footer != null) { + clientArea.height -= lineHeight * 2; + } + + // TODO not wrapped + StyledTextContent content = printerRenderer.content; + startLine = 0; + endLine = singleLine ? 0 : content.getLineCount() - 1; + PrinterData data = printer.getPrinterData(); + if (data.scope == PrinterData.PAGE_RANGE) { + int pageSize = clientArea.height / lineHeight;//WRONG + startLine = (startPage - 1) * pageSize; + } else if (data.scope == PrinterData.SELECTION) { + startLine = content.getLineAtOffset(selection.x); + if (selection.y > 0) { + endLine = content.getLineAtOffset(selection.x + selection.y - 1); + } else { + endLine = startLine - 1; + } + } + } + /** + * Prints the lines in the specified page range. + */ + void print() { + Color background = gc.getBackground(); + Color foreground = gc.getForeground(); + int paintY = clientArea.y; + int paintX = clientArea.x; + int page = startPage; + int pageBottom = clientArea.y + clientArea.height; + int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT); + + + for (int i = startLine; i <= endLine && page <= endPage; i++) { + if (paintY == clientArea.y) { + printer.startPage(); + printDecoration(page, true); + } + TextLayout layout = printerRenderer.getTextLayout(i, orientation, clientArea.width, lineSpacing); + Color lineBackground = printerRenderer.getLineBackground(i, background); + int paragraphBottom = paintY + layout.getBounds().height; + if (paragraphBottom <= pageBottom) { + //normal case, the whole paragraph fits in the current page + printLine(paintX, paintY, gc, foreground, lineBackground, layout); + paintY = paragraphBottom; + } else { + int lineCount = layout.getLineCount(); + while (paragraphBottom > pageBottom && lineCount > 0) { + lineCount--; + paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing(); + } + if (lineCount == 0) { + //the whole paragraph goes to the next page + printDecoration(page, false); + printer.endPage(); + page++; + if (page <= endPage) { + printer.startPage(); + printDecoration(page, true); + paintY = clientArea.y; + printLine(paintX, paintY, gc, foreground, lineBackground, layout); + paintY += layout.getBounds().height; + } + } else { + //draw paragraph top in the current page and paragraph bottom in the next + int height = paragraphBottom - paintY; + gc.setClipping(paintX, paintY, clientArea.width, height); + printLine(paintX, paintY, gc, foreground, lineBackground, layout); + printDecoration(page, false); + printer.endPage(); + page++; + if (page <= endPage) { + printer.startPage(); + printDecoration(page, true); + paintY = clientArea.y - height; + int layoutHeight = layout.getBounds().height; + gc.setClipping(paintX, clientArea.y, clientArea.width, layoutHeight - height); + printLine(paintX, paintY, gc, foreground, lineBackground, layout); + paintY += layoutHeight; + } + gc.setClipping((Rectangle)null); + } + } + printerRenderer.disposeTextLayout(layout); + } + if (paintY > clientArea.y) { + // close partial page + printDecoration(page, false); + printer.endPage(); + } + } + /** + * Print header or footer decorations. + * + * @param page page number to print, if specified in the StyledTextPrintOptions header or footer. + * @param header true = print the header, false = print the footer + */ + void printDecoration(int page, boolean header) { + String text = header ? printOptions.header : printOptions.footer; + if (text == null) return; + int lastSegmentIndex = 0; + int segmentCount = 3; + for (int i = 0; i < segmentCount; i++) { + int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); + String segment; + if (segmentIndex == -1) { + segment = text.substring(lastSegmentIndex); + printDecorationSegment(segment, i, page, header); + break; + } else { + segment = text.substring(lastSegmentIndex, segmentIndex); + printDecorationSegment(segment, i, page, header); + lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); + } + } + } + /** + * Print one segment of a header or footer decoration. + * Headers and footers have three different segments. + * One each for left aligned, centered, and right aligned text. + * + * @param segment decoration segment to print + * @param alignment alignment of the segment. 0=left, 1=center, 2=right + * @param page page number to print, if specified in the decoration segment. + * @param header true = print the header, false = print the footer + */ + void printDecorationSegment(String segment, int alignment, int page, boolean header) { + int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); + if (pageIndex != -1) { + int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); + StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex)); + buffer.append (page); + buffer.append (segment.substring(pageIndex + pageTagLength)); + segment = buffer.toString(); + } + if (segment.length() > 0) { + TextLayout layout = new TextLayout(printer); + layout.setText(segment); + layout.setFont(printerFont); + int segmentWidth = layout.getBounds().width; + int segmentHeight = printerRenderer.getLineHeight(); + int drawX = 0, drawY; + if (alignment == LEFT) { + drawX = clientArea.x; + } else if (alignment == CENTER) { + drawX = (pageWidth - segmentWidth) / 2; + } else if (alignment == RIGHT) { + drawX = clientArea.x + clientArea.width - segmentWidth; + } + if (header) { + drawY = clientArea.y - segmentHeight * 2; + } else { + drawY = clientArea.y + clientArea.height + segmentHeight; + } + layout.draw(gc, drawX, drawY); + layout.dispose(); + } + } + void printLine(int paintX, int paintY, GC gc, Color foreground, Color background, TextLayout layout) { + if (background != null) { + Rectangle rect = layout.getBounds(); + gc.setBackground(background); + gc.fillRectangle(paintX, paintY, rect.width, rect.height); + +// int lineCount = layout.getLineCount(); +// for (int i = 0; i < lineCount; i++) { +// Rectangle rect = layout.getLineBounds(i); +// rect.x += paintX; +// rect.y += paintY + layout.getSpacing(); +// rect.width = width;//layout bounds +// gc.fillRectangle(rect); +// } + } + gc.setForeground(foreground); + layout.draw(gc, paintX, paintY); + } + /** + * Starts a print job and prints the pages specified in the constructor. + */ + public void run() { + String jobName = printOptions.jobName; + if (jobName == null) { + jobName = "Printing"; + } + if (printer.startJob(jobName)) { + init(); + print(); + dispose(); + printer.endJob(); + } + } + } + /** + * The RTFWriter class is used to write widget content as + * rich text. The implementation complies with the RTF specification + * version 1.5. + *

    + * toString() is guaranteed to return a valid RTF string only after + * close() has been called. + *

    + * Whole and partial lines and line breaks can be written. Lines will be + * formatted using the styles queried from the LineStyleListener, if + * set, or those set directly in the widget. All styles are applied to + * the RTF stream like they are rendered by the widget. In addition, the + * widget font name and size is used for the whole text. + *

    + */ + class RTFWriter extends TextWriter { + static final int DEFAULT_FOREGROUND = 0; + static final int DEFAULT_BACKGROUND = 1; + Vector colorTable, fontTable; + boolean WriteUnicode; + + /** + * Creates a RTF writer that writes content starting at offset "start" + * in the document. start and lengthcan be set to specify partial + * lines. + * + * @param start start offset of content to write, 0 based from + * beginning of document + * @param length length of content to write + */ + public RTFWriter(int start, int length) { + super(start, length); + colorTable = new Vector(); + fontTable = new Vector(); + colorTable.addElement(getForeground()); + colorTable.addElement(getBackground()); + fontTable.addElement(getFont()); + setUnicode(); + } + /** + * Closes the RTF writer. Once closed no more content can be written. + * NOTE: toString() does not return a valid RTF string until + * close() has been called. + */ + public void close() { + if (!isClosed()) { + writeHeader(); + write("\n}}\0"); + super.close(); + } + } + /** + * Returns the index of the specified color in the RTF color table. + * + * @param color the color + * @param defaultIndex return value if color is null + * @return the index of the specified color in the RTF color table + * or "defaultIndex" if "color" is null. + */ + int getColorIndex(Color color, int defaultIndex) { + if (color == null) return defaultIndex; + int index = colorTable.indexOf(color); + if (index == -1) { + index = colorTable.size(); + colorTable.addElement(color); + } + return index; + } + /** + * Returns the index of the specified color in the RTF color table. + * + * @param color the color + * @param defaultIndex return value if color is null + * @return the index of the specified color in the RTF color table + * or "defaultIndex" if "color" is null. + */ + int getFontIndex(Font font) { + int index = fontTable.indexOf(font); + if (index == -1) { + index = fontTable.size(); + fontTable.addElement(font); + } + return index; + } + /** + * Determines if Unicode RTF should be written. + * Don't write Unicode RTF on Windows 95/98/ME or NT. + */ + void setUnicode() { + final String Win95 = "windows 95"; + final String Win98 = "windows 98"; + final String WinME = "windows me"; + final String WinNT = "windows nt"; + String osName = System.getProperty("os.name").toLowerCase(); + String osVersion = System.getProperty("os.version"); + int majorVersion = 0; + + if (osName.startsWith(WinNT) && osVersion != null) { + int majorIndex = osVersion.indexOf('.'); + if (majorIndex != -1) { + osVersion = osVersion.substring(0, majorIndex); + try { + majorVersion = Integer.parseInt(osVersion); + } catch (NumberFormatException exception) { + // ignore exception. version number remains unknown. + // will write without Unicode + } + } + } + WriteUnicode = !osName.startsWith(Win95) && + !osName.startsWith(Win98) && + !osName.startsWith(WinME) && + (!osName.startsWith(WinNT) || majorVersion > 4); + } + /** + * Appends the specified segment of "string" to the RTF data. + * Copy from start up to, but excluding, end. + * + * @param string string to copy a segment from. Must not contain + * line breaks. Line breaks should be written using writeLineDelimiter() + * @param start start offset of segment. 0 based. + * @param end end offset of segment + */ + void write(String string, int start, int end) { + for (int index = start; index < end; index++) { + char ch = string.charAt(index); + if (ch > 0xFF && WriteUnicode) { + // write the sub string from the last escaped character + // to the current one. Fixes bug 21698. + if (index > start) { + write(string.substring(start, index)); + } + write("\\u"); + write(Integer.toString((short) ch)); + write(' '); // control word delimiter + start = index + 1; + } else if (ch == '}' || ch == '{' || ch == '\\') { + // write the sub string from the last escaped character + // to the current one. Fixes bug 21698. + if (index > start) { + write(string.substring(start, index)); + } + write('\\'); + write(ch); + start = index + 1; + } + } + // write from the last escaped character to the end. + // Fixes bug 21698. + if (start < end) { + write(string.substring(start, end)); + } + } + /** + * Writes the RTF header including font table and color table. + */ + void writeHeader() { + StringBuffer header = new StringBuffer(); + FontData fontData = getFont().getFontData()[0]; + header.append("{\\rtf1\\ansi"); + // specify code page, necessary for copy to work in bidi + // systems that don't support Unicode RTF. + String cpg = System.getProperty("file.encoding").toLowerCase(); + if (cpg.startsWith("cp") || cpg.startsWith("ms")) { + cpg = cpg.substring(2, cpg.length()); + header.append("\\ansicpg"); + header.append(cpg); + } + header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); + header.append(fontData.getName()); + header.append(";"); + for (int i = 1; i < fontTable.size(); i++) { + header.append("\\f"); + header.append(i); + header.append(" "); + FontData fd = ((Font)fontTable.elementAt(i)).getFontData()[0]; + header.append(fd.getName()); + header.append(";"); + } + header.append("}}\n{\\colortbl"); + for (int i = 0; i < colorTable.size(); i++) { + Color color = (Color) colorTable.elementAt(i); + header.append("\\red"); + header.append(color.getRed()); + header.append("\\green"); + header.append(color.getGreen()); + header.append("\\blue"); + header.append(color.getBlue()); + header.append(";"); + } + // some RTF readers ignore the deff0 font tag. Explicitly + // set the font for the whole document to work around this. + header.append("}\n{\\f0\\fs"); + // font size is specified in half points + header.append(fontData.getHeight() * 2); + header.append(" "); + write(header.toString(), 0); + } + /** + * Appends the specified line text to the RTF data. Lines will be formatted + * using the styles queried from the LineStyleListener, if set, or those set + * directly in the widget. + * + * @param line line text to write as RTF. Must not contain line breaks + * Line breaks should be written using writeLineDelimiter() + * @param lineOffset offset of the line. 0 based from the start of the + * widget document. Any text occurring before the start offset or after the + * end offset specified during object creation is ignored. + * @exception SWTException
      + *
    • ERROR_IO when the writer is closed.
    • + *
    + */ + public void writeLine(String line, int lineOffset) { + if (isClosed()) { + SWT.error(SWT.ERROR_IO); + } + int lineIndex = content.getLineAtOffset(lineOffset); + int lineAlignment, lineIndent; + boolean lineJustify; + int[] ranges; + StyleRange[] styles; + StyledTextEvent event = getLineStyleData(lineOffset, line); + if (event != null) { + lineAlignment = event.alignment; + lineIndent = event.indent; + lineJustify = event.justify; + ranges = event.ranges; + styles = event.styles; + } else { + lineAlignment = renderer.getLineAlignment(lineIndex, alignment); + lineIndent = renderer.getLineIndent(lineIndex, indent); + lineJustify = renderer.getLineJustify(lineIndex, justify); + ranges = renderer.getRanges(lineOffset, line.length()); + styles = renderer.getStyleRanges(lineOffset, line.length(), false); + } + if (styles == null) styles = new StyleRange[0]; + Color lineBackground = renderer.getLineBackground(lineIndex, null); + event = getLineBackgroundData(lineOffset, line); + if (event != null && event.lineBackground != null) lineBackground = event.lineBackground; + writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, lineAlignment, lineJustify); + } + /** + * Appends the specified line delmimiter to the RTF data. + * + * @param lineDelimiter line delimiter to write as RTF. + * @exception SWTException
      + *
    • ERROR_IO when the writer is closed.
    • + *
    + */ + public void writeLineDelimiter(String lineDelimiter) { + if (isClosed()) { + SWT.error(SWT.ERROR_IO); + } + write(lineDelimiter, 0, lineDelimiter.length()); + write("\\par "); + } + /** + * Appends the specified line text to the RTF data. + *

    + * Use the colors and font styles specified in "styles" and "lineBackground". + * Formatting is written to reflect the text rendering by the text widget. + * Style background colors take precedence over the line background color. + * Background colors are written using the \highlight tag (vs. the \cb tag). + *

    + * + * @param line line text to write as RTF. Must not contain line breaks + * Line breaks should be written using writeLineDelimiter() + * @param lineOffset offset of the line. 0 based from the start of the + * widget document. Any text occurring before the start offset or after the + * end offset specified during object creation is ignored. + * @param styles styles to use for formatting. Must not be null. + * @param lineBackground line background color to use for formatting. + * May be null. + */ + void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, boolean justify) { + int lineLength = line.length(); + int startOffset = getStart(); + int writeOffset = startOffset - lineOffset; + if (writeOffset >= lineLength) return; + int lineIndex = Math.max(0, writeOffset); + + write("\\fi"); + write(indent); + switch (alignment) { + case SWT.LEFT: write("\\ql"); break; + case SWT.CENTER: write("\\qc"); break; + case SWT.RIGHT: write("\\qr"); break; + } + if (justify) write("\\qj"); + write(" "); + + if (lineBackground != null) { + write("{\\highlight"); + write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); + write(" "); + } + int endOffset = startOffset + super.getCharCount(); + int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); + for (int i = 0; i < styles.length; i++) { + StyleRange style = styles[i]; + int start, end; + if (ranges != null) { + start = ranges[i << 1] - lineOffset; + end = start + ranges[(i << 1) + 1]; + } else { + start = style.start - lineOffset; + end = start + style.length; + } + // skip over partial first line + if (end < writeOffset) { + continue; + } + // style starts beyond line end or RTF write end + if (start >= lineEndOffset) { + break; + } + // write any unstyled text + if (lineIndex < start) { + // copy to start of style + // style starting betond end of write range or end of line + // is guarded against above. + write(line, lineIndex, start); + lineIndex = start; + } + // write styled text + write("{\\cf"); + write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); + int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); + if (colorIndex != DEFAULT_BACKGROUND) { + write("\\highlight"); + write(colorIndex); + } + Font font = style.font; + if (font != null) { + int fontIndex = getFontIndex(font); + write("\\f"); + write(fontIndex); + FontData fontData = font.getFontData()[0]; + write("\\fs"); + write(fontData.getHeight() * 2); + } else { + if ((style.fontStyle & SWT.BOLD) != 0) { + write("\\b"); + } + if ((style.fontStyle & SWT.ITALIC) != 0) { + write("\\i"); + } + } + if (style.underline) { + write("\\ul"); + } + if (style.strikeout) { + write("\\strike"); + } + write(" "); + // copy to end of style or end of write range or end of line + int copyEnd = Math.min(end, lineEndOffset); + // guard against invalid styles and let style processing continue + copyEnd = Math.max(copyEnd, lineIndex); + write(line, lineIndex, copyEnd); + if (font == null) { + if ((style.fontStyle & SWT.BOLD) != 0) { + write("\\b0"); + } + if ((style.fontStyle & SWT.ITALIC) != 0) { + write("\\i0"); + } + } + if (style.underline) { + write("\\ul0"); + } + if (style.strikeout) { + write("\\strike0"); + } + write("}"); + lineIndex = copyEnd; + } + // write unstyled text at the end of the line + if (lineIndex < lineEndOffset) { + write(line, lineIndex, lineEndOffset); + } + if (lineBackground != null) write("}"); + } + } + /** + * The TextWriter class is used to write widget content to + * a string. Whole and partial lines and line breaks can be written. To write + * partial lines, specify the start and length of the desired segment + * during object creation. + *

    + * NOTE: toString() is guaranteed to return a valid string only after close() + * has been called. + *

    + */ + class TextWriter { + private StringBuffer buffer; + private int startOffset; // offset of first character that will be written + private int endOffset; // offset of last character that will be written. + // 0 based from the beginning of the widget text. + private boolean isClosed = false; + + /** + * Creates a writer that writes content starting at offset "start" + * in the document. start and length can be set to specify partial lines. + * + * @param start start offset of content to write, 0 based from beginning of document + * @param length length of content to write + */ + public TextWriter(int start, int length) { + buffer = new StringBuffer(length); + startOffset = start; + endOffset = start + length; + } + /** + * Closes the writer. Once closed no more content can be written. + * NOTE: toString() is not guaranteed to return a valid string unless + * the writer is closed. + */ + public void close() { + if (!isClosed) { + isClosed = true; + } + } + /** + * Returns the number of characters to write. + * @return the integer number of characters to write + */ + public int getCharCount() { + return endOffset - startOffset; + } + /** + * Returns the offset where writing starts. 0 based from the start of + * the widget text. Used to write partial lines. + * @return the integer offset where writing starts + */ + public int getStart() { + return startOffset; + } + /** + * Returns whether the writer is closed. + * @return a boolean specifying whether or not the writer is closed + */ + public boolean isClosed() { + return isClosed; + } + /** + * Returns the string. close() must be called before toString() + * is guaranteed to return a valid string. + * + * @return the string + */ + public String toString() { + return buffer.toString(); + } + /** + * Appends the given string to the data. + */ + void write(String string) { + buffer.append(string); + } + /** + * Inserts the given string to the data at the specified offset. + *

    + * Do nothing if "offset" is < 0 or > getCharCount() + *

    + * + * @param string text to insert + * @param offset offset in the existing data to insert "string" at. + */ + void write(String string, int offset) { + if (offset < 0 || offset > buffer.length()) { + return; + } + buffer.insert(offset, string); + } + /** + * Appends the given int to the data. + */ + void write(int i) { + buffer.append(i); + } + /** + * Appends the given character to the data. + */ + void write(char i) { + buffer.append(i); + } + /** + * Appends the specified line text to the data. + * + * @param line line text to write. Must not contain line breaks + * Line breaks should be written using writeLineDelimiter() + * @param lineOffset offset of the line. 0 based from the start of the + * widget document. Any text occurring before the start offset or after the + * end offset specified during object creation is ignored. + * @exception SWTException
      + *
    • ERROR_IO when the writer is closed.
    • + *
    + */ + public void writeLine(String line, int lineOffset) { + if (isClosed) { + SWT.error(SWT.ERROR_IO); + } + int writeOffset = startOffset - lineOffset; + int lineLength = line.length(); + int lineIndex; + if (writeOffset >= lineLength) { + return; // whole line is outside write range + } else if (writeOffset > 0) { + lineIndex = writeOffset; // line starts before write start + } else { + lineIndex = 0; + } + int copyEnd = Math.min(lineLength, endOffset - lineOffset); + if (lineIndex < copyEnd) { + write(line.substring(lineIndex, copyEnd)); + } + } + /** + * Appends the specified line delmimiter to the data. + * + * @param lineDelimiter line delimiter to write + * @exception SWTException
      + *
    • ERROR_IO when the writer is closed.
    • + *
    + */ + public void writeLineDelimiter(String lineDelimiter) { + if (isClosed) { + SWT.error(SWT.ERROR_IO); + } + write(lineDelimiter); + } + } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + * + * @see SWT#FULL_SELECTION + * @see SWT#MULTI + * @see SWT#READ_ONLY + * @see SWT#SINGLE + * @see SWT#WRAP + * @see #getStyle + */ +public StyledText(Composite parent, int style) { + super(parent, checkStyle(style)); + // set the fg in the OS to ensure that these are the same as StyledText, necessary + // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses + super.setForeground(getForeground()); + Display display = getDisplay(); + isMirrored = (super.getStyle() & SWT.MIRRORED) != 0; + fixedLineHeight = true; + if ((style & SWT.READ_ONLY) != 0) { + setEditable(false); + } + leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0; + if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) { + leftMargin = topMargin = rightMargin = bottomMargin = 2; + } + alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if (alignment == 0) alignment = SWT.LEFT; + clipboard = new Clipboard(display); + installDefaultContent(); + renderer = new StyledTextRenderer(getDisplay(), this); + renderer.setContent(content); + renderer.setFont(getFont(), tabLength); + defaultCaret = new Caret(this, SWT.NULL); + if ((style & SWT.WRAP) != 0) { + setWordWrap(true); + } + if (isBidiCaret()) { + createCaretBitmaps(); + Runnable runnable = new Runnable() { + public void run() { + int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT; + if (direction == caretDirection) return; + if (getCaret() != defaultCaret) return; + Point newCaretPos = getPointAtOffset(caretOffset); + setCaretLocation(newCaretPos, direction); + } + }; + BidiUtil.addLanguageListener(handle, runnable); + } + setCaret(defaultCaret); + calculateScrollBars(); + createKeyBindings(); + setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM)); + installListeners(); + initializeAccessible(); +} +/** + * Adds an extended modify listener. An ExtendedModify event is sent by the + * widget when the widget text has changed. + * + * @param extendedModifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { + checkWidget(); + if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + StyledTextListener typedListener = new StyledTextListener(extendedModifyListener); + addListener(ExtendedModify, typedListener); +} +/** + * Adds a bidirectional segment listener. + *

    + * A BidiSegmentEvent is sent + * whenever a line of text is measured or rendered. The user can + * specify text ranges in the line that should be treated as if they + * had a different direction than the surrounding text. + * This may be used when adjacent segments of right-to-left text should + * not be reordered relative to each other. + * E.g., Multiple Java string literals in a right-to-left language + * should generally remain in logical order to each other, that is, the + * way they are stored. + *

    + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + * @see BidiSegmentEvent + * @since 2.0 + */ +public void addBidiSegmentListener(BidiSegmentListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(LineGetSegments, new StyledTextListener(listener)); +} +/** + * Adds a line background listener. A LineGetBackground event is sent by the + * widget to determine the background color for a line. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addLineBackgroundListener(LineBackgroundListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (!isListening(LineGetBackground)) { + renderer.clearLineBackground(0, content.getLineCount()); + } + addListener(LineGetBackground, new StyledTextListener(listener)); +} +/** + * Adds a line style listener. A LineGetStyle event is sent by the widget to + * determine the styles for a line. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addLineStyleListener(LineStyleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (!isListening(LineGetStyle)) { + setStyleRanges(0, 0, null, null, true); + renderer.clearLineStyle(0, content.getLineCount()); + } + addListener(LineGetStyle, new StyledTextListener(listener)); +} +/** + * Adds a modify listener. A Modify event is sent by the widget when the widget text + * has changed. + * + * @param modifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addModifyListener(ModifyListener modifyListener) { + checkWidget(); + if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(SWT.Modify, new TypedListener(modifyListener)); +} +/** + * Adds a paint object listener. A paint object event is sent by the widget when an object + * needs to be drawn. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + * + * @since 3.2 + * + * @see PaintObjectListener + * @see PaintObjectEvent + */ +public void addPaintObjectListener(PaintObjectListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(PaintObject, new StyledTextListener(listener)); +} +/** + * Adds a selection listener. A Selection event is sent by the widget when the + * selection has changed. + *

    + * When widgetSelected is called, the event x and y fields contain + * the start and end caret indices of the selection. + * widgetDefaultSelected is not called for StyledTexts. + *

    + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(SWT.Selection, new TypedListener(listener)); +} +/** + * Adds a verify key listener. A VerifyKey event is sent by the widget when a key + * is pressed. The widget ignores the key press if the listener sets the doit field + * of the event to false. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addVerifyKeyListener(VerifyKeyListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(VerifyKey, new StyledTextListener(listener)); +} +/** + * Adds a verify listener. A Verify event is sent by the widget when the widget text + * is about to change. The listener can set the event text and the doit field to + * change the text that is set in the widget or to force the widget to ignore the + * text change. + * + * @param verifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addVerifyListener(VerifyListener verifyListener) { + checkWidget(); + if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + addListener(SWT.Verify, new TypedListener(verifyListener)); +} +/** + * Appends a string to the text at the end of the widget. + * + * @param string the string to be appended + * @see #replaceTextRange(int,int,String) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void append(String string) { + checkWidget(); + if (string == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + int lastChar = Math.max(getCharCount(), 0); + replaceTextRange(lastChar, 0, string); +} +/** + * Calculates the scroll bars + */ +void calculateScrollBars() { + ScrollBar horizontalBar = getHorizontalBar(); + ScrollBar verticalBar = getVerticalBar(); + setScrollBars(true); + if (verticalBar != null) { + verticalBar.setIncrement(getVerticalIncrement()); + } + if (horizontalBar != null) { + horizontalBar.setIncrement(getHorizontalIncrement()); + } +} +/** + * Calculates the top index based on the current vertical scroll offset. + * The top index is the index of the topmost fully visible line or the + * topmost partially visible line if no line is fully visible. + * The top index starts at 0. + */ +void calculateTopIndex(int delta) { + int oldTopIndex = topIndex; + int oldTopIndexY = topIndexY; + if (isFixedLineHeight()) { + int verticalIncrement = getVerticalIncrement(); + if (verticalIncrement == 0) { + return; + } + topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); + // Set top index to partially visible top line if no line is fully + // visible but at least some of the widget client area is visible. + // Fixes bug 15088. + if (topIndex > 0) { + if (clientAreaHeight > 0) { + int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; + int fullLineTopPixel = topIndex * verticalIncrement; + int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; + // set top index to partially visible line if no line fully fits in + // client area or if space is available but not used (the latter should + // never happen because we use claimBottomFreeSpace) + if (fullLineVisibleHeight < verticalIncrement) { + topIndex--; + } + } else if (topIndex >= content.getLineCount()) { + topIndex = content.getLineCount() - 1; + } + } + } else { + if (delta >= 0) { + delta -= topIndexY; + int lineIndex = topIndex; + int lineCount = content.getLineCount(); + while (lineIndex < lineCount) { + if (delta <= 0) break; + delta -= renderer.getLineHeight(lineIndex++); + } + if (lineIndex < lineCount && -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { + topIndex = lineIndex; + topIndexY = -delta; + } else { + topIndex = lineIndex - 1; + topIndexY = -renderer.getLineHeight(topIndex) - delta; + } + } else { + delta -= topIndexY; + int lineIndex = topIndex; + while (lineIndex > 0) { + int lineHeight = renderer.getLineHeight(lineIndex - 1); + if (delta + lineHeight > 0) break; + delta += lineHeight; + lineIndex--; + } + if (lineIndex == 0 || -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) { + topIndex = lineIndex; + topIndexY = - delta; + } else { + topIndex = lineIndex - 1; + topIndexY = - renderer.getLineHeight(topIndex) - delta; + } + } + } + if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) { + renderer.calculateClientArea(); + setScrollBars(false); + } +} +/** + * Hides the scroll bars if widget is created in single line mode. + */ +static int checkStyle(int style) { + if ((style & SWT.SINGLE) != 0) { + style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI); + } else { + style |= SWT.MULTI; + if ((style & SWT.WRAP) != 0) { + style &= ~SWT.H_SCROLL; + } + } + style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND; + return style; +} +/** + * Scrolls down the text to use new space made available by a resize or by + * deleted lines. + */ +void claimBottomFreeSpace() { + int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - clientAreaHeight); + if (newVerticalOffset < getVerticalScrollOffset()) { + scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true); + } + } else { + int bottomIndex = getPartialBottomIndex(); + int height = getLinePixel(bottomIndex + 1); + if (clientAreaHeight > height) { + scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true); + } + } +} +/** + * Scrolls text to the right to use new space made available by a resize. + */ +void claimRightFreeSpace() { + int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin)); + if (newHorizontalOffset < horizontalScrollOffset) { + // item is no longer drawn past the right border of the client area + // align the right end of the item with the right border of the + // client area (window is scrolled right). + scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); + } +} +/** + * Removes the widget selection. + * + * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. + */ +void clearSelection(boolean sendEvent) { + int selectionStart = selection.x; + int selectionEnd = selection.y; + resetSelection(); + // redraw old selection, if any + if (selectionEnd - selectionStart > 0) { + int length = content.getCharCount(); + // called internally to remove selection after text is removed + // therefore make sure redraw range is valid. + int redrawStart = Math.min(selectionStart, length); + int redrawEnd = Math.min(selectionEnd, length); + if (redrawEnd - redrawStart > 0) { + internalRedrawRange(redrawStart, redrawEnd - redrawStart); + } + if (sendEvent) { + sendSelectionEvent(); + } + } +} +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget(); + int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount(); + int width = 0; + int height = 0; + if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { + Display display = getDisplay(); + int maxHeight = display.getClientArea().height; + for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { + TextLayout layout = renderer.getTextLayout(lineIndex); + if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint); + Rectangle rect = layout.getBounds(); + height += rect.height; + width = Math.max(width, rect.width); + renderer.disposeTextLayout(layout); + if (isFixedLineHeight() && height > maxHeight) break; + } + if (isFixedLineHeight()) { + height = lineCount * renderer.getLineHeight(); + } + } + // Use default values if no text is defined. + if (width == 0) width = DEFAULT_WIDTH; + if (height == 0) height = DEFAULT_HEIGHT; + if (wHint != SWT.DEFAULT) width = wHint; + if (hHint != SWT.DEFAULT) height = hHint; + int wTrim = leftMargin + rightMargin + getCaretWidth(); + int hTrim = topMargin + bottomMargin; + Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim); + return new Point (rect.width, rect.height); +} +/** + * Copies the selected text to the DND.CLIPBOARD clipboard. + *

    + * The text will be put on the clipboard in plain text format and RTF format. + * The DND.CLIPBOARD clipboard is used for data that is + * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or + * by menu action. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void copy() { + checkWidget(); + copy(DND.CLIPBOARD); +} +/** + * Copies the selected text to the specified clipboard. The text will be put in the + * clipboard in plain text format and RTF format. + *

    + * The clipboardType is one of the clipboard constants defined in class + * DND. The DND.CLIPBOARD clipboard is + * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) + * or by menu action. The DND.SELECTION_CLIPBOARD + * clipboard is used for data that is transferred by selecting text and pasting + * with the middle mouse button. + *

    + * + * @param clipboardType indicates the type of clipboard + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void copy(int clipboardType) { + checkWidget(); + if (clipboardType != DND.CLIPBOARD && clipboardType != DND.SELECTION_CLIPBOARD) return; + int length = selection.y - selection.x; + if (length > 0) { + try { + setClipboardContent(selection.x, length, clipboardType); + } catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + } + } +} +/** + * Returns the alignment of the widget. + * + * @return the alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getLineAlignment(int) + * + * @since 3.2 + */ +public int getAlignment() { + checkWidget(); + return alignment; +} +int getAvailableHeightAbove(int height) { + int maxHeight = verticalScrollOffset; + if (maxHeight == -1) { + int lineIndex = topIndex - 1; + maxHeight = -topIndexY; + if (topIndexY > 0) { + maxHeight += renderer.getLineHeight(lineIndex--); + } + while (height > maxHeight && lineIndex >= 0) { + maxHeight += renderer.getLineHeight(lineIndex--); + } + } + return Math.min(height, maxHeight); +} +int getAvailableHeightBellow(int height) { + int partialBottomIndex = getPartialBottomIndex(); + int topY = getLinePixel(partialBottomIndex); + int lineHeight = renderer.getLineHeight(partialBottomIndex); + int availableHeight = 0; + int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; + if (topY + lineHeight > clientAreaHeight) { + availableHeight = lineHeight - (clientAreaHeight - topY); + } + int lineIndex = partialBottomIndex + 1; + int lineCount = content.getLineCount(); + while (height > availableHeight && lineIndex < lineCount) { + availableHeight += renderer.getLineHeight(lineIndex++); + } + return Math.min(height, availableHeight); +} +/** + * Returns a string that uses only the line delimiter specified by the + * StyledTextContent implementation. + *

    + * Returns only the first line if the widget has the SWT.SINGLE style. + *

    + * + * @param text the text that may have line delimiters that don't + * match the model line delimiter. Possible line delimiters + * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") + * @return the converted text that only uses the line delimiter + * specified by the model. Returns only the first line if the widget + * has the SWT.SINGLE style. + */ +String getModelDelimitedText(String text) { + int length = text.length(); + if (length == 0) { + return text; + } + int crIndex = 0; + int lfIndex = 0; + int i = 0; + StringBuffer convertedText = new StringBuffer(length); + String delimiter = getLineDelimiter(); + while (i < length) { + if (crIndex != -1) { + crIndex = text.indexOf(SWT.CR, i); + } + if (lfIndex != -1) { + lfIndex = text.indexOf(SWT.LF, i); + } + if (lfIndex == -1 && crIndex == -1) { // no more line breaks? + break; + } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { + convertedText.append(text.substring(i, crIndex)); + if (lfIndex == crIndex + 1) { // CR/LF combination? + i = lfIndex + 1; + } else { + i = crIndex + 1; + } + } else { // LF occurs before CR! + convertedText.append(text.substring(i, lfIndex)); + i = lfIndex + 1; + } + if (isSingleLine()) { + break; + } + convertedText.append(delimiter); + } + // copy remaining text if any and if not in single line mode or no + // text copied thus far (because there only is one line) + if (i < length && (!isSingleLine() || convertedText.length() == 0)) { + convertedText.append(text.substring(i)); + } + return convertedText.toString(); +} +/** + * Creates default key bindings. + */ +void createKeyBindings() { + int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT; + int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT; + + // Navigation + setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); + setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); + if (IS_CARBON) { + setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START); + setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END); + setKeyBinding(SWT.HOME, ST.TEXT_START); + setKeyBinding(SWT.END, ST.TEXT_END); + setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START); + setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END); + setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT); + setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS); + } else { + setKeyBinding(SWT.HOME, ST.LINE_START); + setKeyBinding(SWT.END, ST.LINE_END); + setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); + setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); + setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT); + setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS); + } + setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); + setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); + setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); + setKeyBinding(nextKey, ST.COLUMN_NEXT); + setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); + + // Selection + setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); + setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); + if (IS_CARBON) { + setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START); + setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END); + setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT); + setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS); + } else { + setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); + setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); + setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); + setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); + } + setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); + setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); + setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT); + setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); + + // Modification + // Cut, Copy, Paste + setKeyBinding('X' | SWT.MOD1, ST.CUT); + setKeyBinding('C' | SWT.MOD1, ST.COPY); + setKeyBinding('V' | SWT.MOD1, ST.PASTE); + if (IS_CARBON) { + setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT); + setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS); + setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT); + } else { + // Cut, Copy, Paste Wordstar style + setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); + setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); + setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); + } + setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); + setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); + setKeyBinding(SWT.DEL, ST.DELETE_NEXT); + setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS); + setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT); + + // Miscellaneous + setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); +} +/** + * Create the bitmaps to use for the caret in bidi mode. This + * method only needs to be called upon widget creation and when the + * font changes (the caret bitmap height needs to match font height). + */ +void createCaretBitmaps() { + int caretWidth = BIDI_CARET_WIDTH; + Display display = getDisplay(); + if (leftCaretBitmap != null) { + if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) { + defaultCaret.setImage(null); + } + leftCaretBitmap.dispose(); + } + int lineHeight = renderer.getLineHeight(); + leftCaretBitmap = new Image(display, caretWidth, lineHeight); + GC gc = new GC (leftCaretBitmap); + gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + gc.fillRectangle(0, 0, caretWidth, lineHeight); + gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); + gc.drawLine(0,0,0,lineHeight); + gc.drawLine(0,0,caretWidth-1,0); + gc.drawLine(0,1,1,1); + gc.dispose(); + + if (rightCaretBitmap != null) { + if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) { + defaultCaret.setImage(null); + } + rightCaretBitmap.dispose(); + } + rightCaretBitmap = new Image(display, caretWidth, lineHeight); + gc = new GC (rightCaretBitmap); + gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + gc.fillRectangle(0, 0, caretWidth, lineHeight); + gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); + gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); + gc.drawLine(0,0,caretWidth-1,0); + gc.drawLine(caretWidth-1,1,1,1); + gc.dispose(); +} +/** + * Moves the selected text to the clipboard. The text will be put in the + * clipboard in plain text format and RTF format. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void cut(){ + checkWidget(); + int length = selection.y - selection.x; + if (length > 0) { + try { + setClipboardContent(selection.x, length, DND.CLIPBOARD); + } catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + // Abort cut operation if copy to clipboard fails. + // Fixes bug 21030. + return; + } + doDelete(); + } +} +boolean detectDrag(int x, int y, int button) { + if (!isListening(SWT.DragDetect)) return false; + if (IS_MOTIF) { + if (button != 2) return false; + } else { + if (button != 1) return false; + } + if (selection.x == selection.y) return false; + int offset = getOffsetAtPoint(x, y); + return offset > selection.x && offset < selection.y; +} +/** + * A mouse move event has occurred. See if we should start autoscrolling. If + * the move position is outside of the client area, initiate autoscrolling. + * Otherwise, we've moved back into the widget so end autoscrolling. + */ +void doAutoScroll(Event event) { + if (event.y > clientAreaHeight) { + doAutoScroll(SWT.DOWN, event.y - clientAreaHeight); + } else if (event.y < 0) { + doAutoScroll(SWT.UP, -event.y); + } else if (event.x < leftMargin && !wordWrap) { + doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x); + } else if (event.x > clientAreaWidth - leftMargin - rightMargin && !wordWrap) { + doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - leftMargin - rightMargin)); + } else { + endAutoScroll(); + } +} +/** + * Initiates autoscrolling. + * + * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS + */ +void doAutoScroll(int direction, int distance) { + autoScrollDistance = distance; + // If we're already autoscrolling in the given direction do nothing + if (autoScrollDirection == direction) { + return; + } + + Runnable timer = null; + final Display display = getDisplay(); + // Set a timer that will simulate the user pressing and holding + // down a cursor key (i.e., arrowUp, arrowDown). + if (direction == SWT.UP) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.UP) { + doSelectionPageUp(autoScrollDistance); + display.timerExec(V_SCROLL_RATE, this); + } + } + }; + autoScrollDirection = direction; + display.timerExec(V_SCROLL_RATE, timer); + } else if (direction == SWT.DOWN) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.DOWN) { + doSelectionPageDown(autoScrollDistance); + display.timerExec(V_SCROLL_RATE, this); + } + } + }; + autoScrollDirection = direction; + display.timerExec(V_SCROLL_RATE, timer); + } else if (direction == ST.COLUMN_NEXT) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == ST.COLUMN_NEXT) { + doVisualNext(); + setMouseWordSelectionAnchor(); + doMouseSelection(); + display.timerExec(H_SCROLL_RATE, this); + } + } + }; + autoScrollDirection = direction; + display.timerExec(H_SCROLL_RATE, timer); + } else if (direction == ST.COLUMN_PREVIOUS) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == ST.COLUMN_PREVIOUS) { + doVisualPrevious(); + setMouseWordSelectionAnchor(); + doMouseSelection(); + display.timerExec(H_SCROLL_RATE, this); + } + } + }; + autoScrollDirection = direction; + display.timerExec(H_SCROLL_RATE, timer); + } +} +/** + * Deletes the previous character. Delete the selected text if any. + * Move the caret in front of the deleted text. + */ +void doBackspace() { + Event event = new Event(); + event.text = ""; + if (selection.x != selection.y) { + event.start = selection.x; + event.end = selection.y; + sendKeyEvent(event); + } else if (caretOffset > 0) { + int lineIndex = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(lineIndex); + if (caretOffset == lineOffset) { + lineOffset = content.getOffsetAtLine(lineIndex - 1); + event.start = lineOffset + content.getLine(lineIndex - 1).length(); + event.end = caretOffset; + } else { + TextLayout layout = renderer.getTextLayout(lineIndex); + int start = layout.getPreviousOffset(caretOffset - lineOffset, SWT.MOVEMENT_CHAR); + renderer.disposeTextLayout(layout); + event.start = start + lineOffset; + event.end = caretOffset; + } + sendKeyEvent(event); + } +} +/** + * Replaces the selection with the character or insert the character at the + * current caret position if no selection exists. + *

    + * If a carriage return was typed replace it with the line break character + * used by the widget on this platform. + *

    + * + * @param key the character typed by the user + */ +void doContent(char key) { + if (textLimit > 0 && + content.getCharCount() - (selection.y - selection.x) >= textLimit) { + return; + } + Event event = new Event(); + event.start = selection.x; + event.end = selection.y; + // replace a CR line break with the widget line break + // CR does not make sense on Windows since most (all?) applications + // don't recognize CR as a line break. + if (key == SWT.CR || key == SWT.LF) { + if (!isSingleLine()) { + event.text = getLineDelimiter(); + } + } else if (selection.x == selection.y && overwrite && key != TAB) { + // no selection and overwrite mode is on and the typed key is not a + // tab character (tabs are always inserted without overwriting)? + int lineIndex = content.getLineAtOffset(event.end); + int lineOffset = content.getOffsetAtLine(lineIndex); + String line = content.getLine(lineIndex); + // replace character at caret offset if the caret is not at the + // end of the line + if (event.end < lineOffset + line.length()) { + event.end++; + } + event.text = new String(new char[] {key}); + } else { + event.text = new String(new char[] {key}); + } + if (event.text != null) { + sendKeyEvent(event); + } +} +/** + * Moves the caret after the last character of the widget content. + */ +void doContentEnd() { + // place caret at end of first line if receiver is in single + // line mode. fixes 4820. + if (isSingleLine()) { + doLineEnd(); + } else { + int length = content.getCharCount(); + if (caretOffset < length) { + caretOffset = length; + showCaret(); + } + } +} +/** + * Moves the caret in front of the first character of the widget content. + */ +void doContentStart() { + if (caretOffset > 0) { + caretOffset = 0; + showCaret(); + } +} +/** + * Moves the caret to the start of the selection if a selection exists. + * Otherwise, if no selection exists move the cursor according to the + * cursor selection rules. + * + * @see #doSelectionCursorPrevious + */ +void doCursorPrevious() { + if (selection.y - selection.x > 0) { + caretOffset = selection.x; + caretAlignment = OFFSET_LEADING; + showCaret(); + } else { + doSelectionCursorPrevious(); + } +} +/** + * Moves the caret to the end of the selection if a selection exists. + * Otherwise, if no selection exists move the cursor according to the + * cursor selection rules. + * + * @see #doSelectionCursorNext + */ +void doCursorNext() { + if (selection.y - selection.x > 0) { + caretOffset = selection.y; + caretAlignment = PREVIOUS_OFFSET_TRAILING; + showCaret(); + } else { + doSelectionCursorNext(); + } +} +/** + * Deletes the next character. Delete the selected text if any. + */ +void doDelete() { + Event event = new Event(); + event.text = ""; + if (selection.x != selection.y) { + event.start = selection.x; + event.end = selection.y; + sendKeyEvent(event); + } else if (caretOffset < content.getCharCount()) { + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + int lineLength = content.getLine(line).length(); + if (caretOffset == lineOffset + lineLength) { + event.start = caretOffset; + event.end = content.getOffsetAtLine(line + 1); + } else { + event.start = caretOffset; + event.end = getClusterNext(caretOffset, line); + } + sendKeyEvent(event); + } +} +/** + * Deletes the next word. + */ +void doDeleteWordNext() { + if (selection.x != selection.y) { + // if a selection exists, treat the as if + // only the delete key was pressed + doDelete(); + } else { + Event event = new Event(); + event.text = ""; + event.start = caretOffset; + event.end = getWordEnd(caretOffset); + sendKeyEvent(event); + } +} +/** + * Deletes the previous word. + */ +void doDeleteWordPrevious() { + if (selection.x != selection.y) { + // if a selection exists, treat as if + // only the backspace key was pressed + doBackspace(); + } else { + Event event = new Event(); + event.text = ""; + event.start = getWordStart(caretOffset); + event.end = caretOffset; + sendKeyEvent(event); + } +} +/** + * Moves the caret one line down and to the same character offset relative + * to the beginning of the line. Move the caret to the end of the new line + * if the new line is shorter than the character offset. + * + * @return index of the new line relative to the first line in the document + */ +void doLineDown(boolean select) { + int caretLine = getCaretLine(); + int lineCount = content.getLineCount(); + int y = 0; + boolean lastLine = false; + if (wordWrap) { + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + TextLayout layout = renderer.getTextLayout(caretLine); + int lineIndex = getVisualLineIndex(layout, offsetInLine); + int layoutLineCount = layout.getLineCount(); + if (lineIndex == layoutLineCount - 1) { + lastLine = caretLine == lineCount - 1; + caretLine++; + } else { + y = layout.getLineBounds(lineIndex + 1).y; + } + renderer.disposeTextLayout(layout); + } else { + lastLine = caretLine == lineCount - 1; + caretLine++; + } + if (lastLine) { + if (select) caretOffset = content.getCharCount(); + } else { + caretOffset = getOffsetAtPoint(columnX, y, caretLine); + } + int oldColumnX = columnX; + int oldHScrollOffset = horizontalScrollOffset; + if (select) { + setMouseWordSelectionAnchor(); + // select first and then scroll to reduce flash when key + // repeat scrolls lots of lines + doSelection(ST.COLUMN_NEXT); + } + showCaret(); + int hScrollChange = oldHScrollOffset - horizontalScrollOffset; + columnX = oldColumnX + hScrollChange; +} +/** + * Moves the caret to the end of the line. + */ +void doLineEnd() { + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int lineEndOffset; + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(caretLine); + int offsetInLine = caretOffset - lineOffset; + int lineIndex = getVisualLineIndex(layout, offsetInLine); + int[] offsets = layout.getLineOffsets(); + lineEndOffset = lineOffset + offsets[lineIndex + 1]; + renderer.disposeTextLayout(layout); + } else { + int lineLength = content.getLine(caretLine).length(); + lineEndOffset = lineOffset + lineLength; + } + if (caretOffset < lineEndOffset) { + caretOffset = lineEndOffset; + caretAlignment = PREVIOUS_OFFSET_TRAILING; + showCaret(); + } +} +/** + * Moves the caret to the beginning of the line. + */ +void doLineStart() { + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(caretLine); + int offsetInLine = caretOffset - lineOffset; + int lineIndex = getVisualLineIndex(layout, offsetInLine); + int[] offsets = layout.getLineOffsets(); + lineOffset += offsets[lineIndex]; + renderer.disposeTextLayout(layout); + } + if (caretOffset > lineOffset) { + caretOffset = lineOffset; + caretAlignment = OFFSET_LEADING; + showCaret(); + } +} +/** + * Moves the caret one line up and to the same character offset relative + * to the beginning of the line. Move the caret to the end of the new line + * if the new line is shorter than the character offset. + * + * @return index of the new line relative to the first line in the document + */ +void doLineUp(boolean select) { + int caretLine = getCaretLine(), y = 0; + boolean firstLine = false; + if (wordWrap) { + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + TextLayout layout = renderer.getTextLayout(caretLine); + int lineIndex = getVisualLineIndex(layout, offsetInLine); + if (lineIndex == 0) { + firstLine = caretLine == 0; + if (!firstLine) { + caretLine--; + y = renderer.getLineHeight(caretLine) - 1; + } + } else { + y = layout.getLineBounds(lineIndex - 1).y; + } + renderer.disposeTextLayout(layout); + } else { + firstLine = caretLine == 0; + caretLine--; + } + if (firstLine) { + if (select) caretOffset = 0; + } else { + caretOffset = getOffsetAtPoint(columnX, y, caretLine); + } + int oldColumnX = columnX; + int oldHScrollOffset = horizontalScrollOffset; + if (select) setMouseWordSelectionAnchor(); + showCaret(); + if (select) doSelection(ST.COLUMN_PREVIOUS); + int hScrollChange = oldHScrollOffset - horizontalScrollOffset; + columnX = oldColumnX + hScrollChange; +} +/** + * Moves the caret to the specified location. + * + * @param x x location of the new caret position + * @param y y location of the new caret position + * @param select the location change is a selection operation. + * include the line delimiter in the selection + */ +void doMouseLocationChange(int x, int y, boolean select) { + int line = getLineIndex(y); + + updateCaretDirection = true; + // allow caret to be placed below first line only if receiver is + // not in single line mode. fixes 4820. + if (line < 0 || (isSingleLine() && line > 0)) { + return; + } + int oldCaretAlignment = caretAlignment; + int newCaretOffset = getOffsetAtPoint(x, y); + + if (mouseDoubleClick) { + // double click word select the previous/next word. fixes bug 15610 + newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); + } + + int newCaretLine = content.getLineAtOffset(newCaretOffset); + + // Is the mouse within the left client area border or on + // a different line? If not the autoscroll selection + // could be incorrectly reset. Fixes 1GKM3XS + if (0 <= y && y < clientAreaHeight && + (0 <= x && x < clientAreaWidth || wordWrap || + newCaretLine != content.getLineAtOffset(caretOffset))) { + if (newCaretOffset != caretOffset || caretAlignment != oldCaretAlignment) { + caretOffset = newCaretOffset; + if (select) doMouseSelection(); + showCaret(); + } + } + if (!select) { + caretOffset = newCaretOffset; + clearSelection(true); + } +} +/** + * Updates the selection based on the caret position + */ +void doMouseSelection() { + if (caretOffset <= selection.x || + (caretOffset > selection.x && + caretOffset < selection.y && selectionAnchor == selection.x)) { + doSelection(ST.COLUMN_PREVIOUS); + } else { + doSelection(ST.COLUMN_NEXT); + } +} +/** + * Returns the offset of the word at the specified offset. + * If the current selection extends from high index to low index + * (i.e., right to left, or caret is at left border of selecton on + * non-bidi platforms) the start offset of the word preceeding the + * selection is returned. If the current selection extends from + * low index to high index the end offset of the word following + * the selection is returned. + * + * @param x mouse x location + * @param newCaretOffset caret offset of the mouse cursor location + * @param line line index of the mouse cursor location + */ +int doMouseWordSelect(int x, int newCaretOffset, int line) { + // flip selection anchor based on word selection direction from + // base double click. Always do this here (and don't rely on doAutoScroll) + // because auto scroll only does not cover all possible mouse selections + // (e.g., mouse x < 0 && mouse y > caret line y) + if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) { + selectionAnchor = doubleClickSelection.y; + } else if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) { + selectionAnchor = doubleClickSelection.x; + } + if (0 <= x && x < clientAreaWidth) { + int wordOffset; + // find the previous/next word + if (caretOffset == selection.x) { + wordOffset = getWordStart(newCaretOffset); + } else { + wordOffset = getWordEndNoSpaces(newCaretOffset); + } + // mouse word select only on same line mouse cursor is on + if (content.getLineAtOffset(wordOffset) == line) { + newCaretOffset = wordOffset; + } + } + return newCaretOffset; +} +/** + * Scrolls one page down so that the last line (truncated or whole) + * of the current page becomes the fully visible top line. + *

    + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the end + * of the text where a full page scroll is not possible. In this case + * the caret is moved after the last character. + *

    + * + * @param select whether or not to select the page + */ +void doPageDown(boolean select, int height) { + if (isSingleLine()) return; + int oldColumnX = columnX; + int oldHScrollOffset = horizontalScrollOffset; + if (isFixedLineHeight()) { + int lineCount = content.getLineCount(); + int caretLine = getCaretLine(); + if (caretLine < lineCount - 1) { + int lineHeight = renderer.getLineHeight(); + int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; + int scrollLines = Math.min(lineCount - caretLine - 1, lines); + // ensure that scrollLines never gets negative and at least one + // line is scrolled. fixes bug 5602. + scrollLines = Math.max(1, scrollLines); + caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines)); + if (select) { + doSelection(ST.COLUMN_NEXT); + } + // scroll one page down or to the bottom + int verticalMaximum = lineCount * getVerticalIncrement(); + int pageSize = clientAreaHeight; + int verticalScrollOffset = getVerticalScrollOffset(); + int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); + if (scrollOffset + pageSize > verticalMaximum) { + scrollOffset = verticalMaximum - pageSize; + } + if (scrollOffset > verticalScrollOffset) { + scrollVertical(scrollOffset - verticalScrollOffset, true); + } + } + } else { + int lineCount = content.getLineCount(); + int caretLine = getCaretLine(); + int lineIndex, lineHeight; + if (height == -1) { + lineIndex = getPartialBottomIndex(); + int topY = getLinePixel(lineIndex); + lineHeight = renderer.getLineHeight(lineIndex); + height = topY; + if (topY + lineHeight <= clientAreaHeight) { + height += lineHeight; + } else { + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(lineIndex); + int y = clientAreaHeight - topY; + for (int i = 0; i < layout.getLineCount(); i++) { + Rectangle bounds = layout.getLineBounds(i); + if (bounds.contains(bounds.x, y)) { + height += bounds.y; + break; + } + } + renderer.disposeTextLayout(layout); + } + } + } else { + lineIndex = getLineIndex(height); + int topLineY = getLinePixel(lineIndex); + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(lineIndex); + int y = height - topLineY; + for (int i = 0; i < layout.getLineCount(); i++) { + Rectangle bounds = layout.getLineBounds(i); + if (bounds.contains(bounds.x, y)) { + height = topLineY + bounds.y + bounds.height; + break; + } + } + renderer.disposeTextLayout(layout); + } else { + height = topLineY + renderer.getLineHeight(lineIndex); + } + } + int caretHeight = height; + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(caretLine); + int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); + lineIndex = getVisualLineIndex(layout, offsetInLine); + caretHeight += layout.getLineBounds(lineIndex).y; + renderer.disposeTextLayout(layout); + } + lineIndex = caretLine; + lineHeight = renderer.getLineHeight(lineIndex); + while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) { + caretHeight -= lineHeight; + lineHeight = renderer.getLineHeight(++lineIndex); + } + caretOffset = getOffsetAtPoint(columnX, caretHeight, lineIndex); + if (select) doSelection(ST.COLUMN_NEXT); + height = getAvailableHeightBellow(height); + scrollVertical(height, true); + if (height == 0) setCaretLocation(); + } + showCaret(); + int hScrollChange = oldHScrollOffset - horizontalScrollOffset; + columnX = oldColumnX + hScrollChange; +} +/** + * Moves the cursor to the end of the last fully visible line. + */ +void doPageEnd() { + // go to end of line if in single line mode. fixes 5673 + if (isSingleLine()) { + doLineEnd(); + } else { + int bottomOffset; + if (wordWrap) { + int lineIndex = getPartialBottomIndex(); + TextLayout layout = renderer.getTextLayout(lineIndex); + int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex); + int index = layout.getLineCount() - 1; + while (index >= 0) { + Rectangle bounds = layout.getLineBounds(index); + if (y >= bounds.y + bounds.height) break; + index--; + } + if (index == -1 && lineIndex > 0) { + bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); + } else { + bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); + } + renderer.disposeTextLayout(layout); + } else { + int lineIndex = getBottomIndex(); + bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length(); + } + if (caretOffset < bottomOffset) { + caretOffset = bottomOffset; + caretAlignment = OFFSET_LEADING; + showCaret(); + } + } +} +/** + * Moves the cursor to the beginning of the first fully visible line. + */ +void doPageStart() { + int topOffset; + if (wordWrap) { + int y, lineIndex; + if (topIndexY > 0) { + lineIndex = topIndex - 1; + y = renderer.getLineHeight(lineIndex) - topIndexY; + } else { + lineIndex = topIndex; + y = -topIndexY; + } + TextLayout layout = renderer.getTextLayout(lineIndex); + int index = 0; + int lineCount = layout.getLineCount(); + while (index < lineCount) { + Rectangle bounds = layout.getLineBounds(index); + if (y <= bounds.y) break; + index++; + } + if (index == lineCount) { + topOffset = content.getOffsetAtLine(lineIndex + 1); + } else { + topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; + } + renderer.disposeTextLayout(layout); + } else { + topOffset = content.getOffsetAtLine(topIndex); + } + if (caretOffset > topOffset) { + caretOffset = topOffset; + caretAlignment = OFFSET_LEADING; + showCaret(); + } +} +/** + * Scrolls one page up so that the first line (truncated or whole) + * of the current page becomes the fully visible last line. + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the beginning + * of the text where a full page scroll is not possible. In this case the + * caret is moved in front of the first character. + */ +void doPageUp(boolean select, int height) { + if (isSingleLine()) return; + int oldHScrollOffset = horizontalScrollOffset; + int oldColumnX = columnX; + if (isFixedLineHeight()) { + int caretLine = getCaretLine(); + if (caretLine > 0) { + int lineHeight = renderer.getLineHeight(); + int lines = (height == -1 ? clientAreaHeight : height) / lineHeight; + int scrollLines = Math.max(1, Math.min(caretLine, lines)); + caretLine -= scrollLines; + caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine)); + if (select) { + doSelection(ST.COLUMN_PREVIOUS); + } + int verticalScrollOffset = getVerticalScrollOffset(); + int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); + if (scrollOffset < verticalScrollOffset) { + scrollVertical(scrollOffset - verticalScrollOffset, true); + } + } + } else { + int caretLine = getCaretLine(); + int lineHeight, lineIndex; + if (height == -1) { + if (topIndexY == 0) { + height = clientAreaHeight; + } else { + int y; + if (topIndex > 0) { + lineIndex = topIndex - 1; + lineHeight = renderer.getLineHeight(lineIndex); + height = clientAreaHeight - topIndexY; + y = lineHeight - topIndexY; + } else { + lineIndex = topIndex; + lineHeight = renderer.getLineHeight(lineIndex); + height = clientAreaHeight - (lineHeight + topIndexY); + y = -topIndexY; + } + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(lineIndex); + for (int i = 0; i < layout.getLineCount(); i++) { + Rectangle bounds = layout.getLineBounds(i); + if (bounds.contains(bounds.x, y)) { + height += lineHeight - (bounds.y + bounds.height); + break; + } + } + renderer.disposeTextLayout(layout); + } + } + } else { + lineIndex = getLineIndex(clientAreaHeight - height); + int topLineY = getLinePixel(lineIndex); + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(lineIndex); + int y = topLineY; + for (int i = 0; i < layout.getLineCount(); i++) { + Rectangle bounds = layout.getLineBounds(i); + if (bounds.contains(bounds.x, y)) { + height = clientAreaHeight - (topLineY + bounds.y); + break; + } + } + renderer.disposeTextLayout(layout); + } else { + height = clientAreaHeight - topLineY; + } + } + int caretHeight = height; + if (wordWrap) { + TextLayout layout = renderer.getTextLayout(caretLine); + int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine); + lineIndex = getVisualLineIndex(layout, offsetInLine); + caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y; + renderer.disposeTextLayout(layout); + } + lineIndex = caretLine; + lineHeight = renderer.getLineHeight(lineIndex); + while (caretHeight - lineHeight >= 0 && lineIndex > 0) { + caretHeight -= lineHeight; + lineHeight = renderer.getLineHeight(--lineIndex); + } + lineHeight = renderer.getLineHeight(lineIndex); + caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); + if (select) doSelection(ST.COLUMN_PREVIOUS); + height = getAvailableHeightAbove(height); + scrollVertical(-height, true); + if (height == 0) setCaretLocation(); + } + showCaret(); + int hScrollChange = oldHScrollOffset - horizontalScrollOffset; + columnX = oldColumnX + hScrollChange; +} +/** + * Updates the selection to extend to the current caret position. + */ +void doSelection(int direction) { + int redrawStart = -1; + int redrawEnd = -1; + if (selectionAnchor == -1) { + selectionAnchor = selection.x; + } + if (direction == ST.COLUMN_PREVIOUS) { + if (caretOffset < selection.x) { + // grow selection + redrawEnd = selection.x; + redrawStart = selection.x = caretOffset; + // check if selection has reversed direction + if (selection.y != selectionAnchor) { + redrawEnd = selection.y; + selection.y = selectionAnchor; + } + // test whether selection actually changed. Fixes 1G71EO1 + } else if (selectionAnchor == selection.x && caretOffset < selection.y) { + // caret moved towards selection anchor (left side of selection). + // shrink selection + redrawEnd = selection.y; + redrawStart = selection.y = caretOffset; + } + } else { + if (caretOffset > selection.y) { + // grow selection + redrawStart = selection.y; + redrawEnd = selection.y = caretOffset; + // check if selection has reversed direction + if (selection.x != selectionAnchor) { + redrawStart = selection.x; + selection.x = selectionAnchor; + } + // test whether selection actually changed. Fixes 1G71EO1 + } else if (selectionAnchor == selection.y && caretOffset > selection.x) { + // caret moved towards selection anchor (right side of selection). + // shrink selection + redrawStart = selection.x; + redrawEnd = selection.x = caretOffset; + } + } + if (redrawStart != -1 && redrawEnd != -1) { + internalRedrawRange(redrawStart, redrawEnd - redrawStart); + sendSelectionEvent(); + } +} +/** + * Moves the caret to the next character or to the beginning of the + * next line if the cursor is at the end of a line. + */ +void doSelectionCursorNext() { + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + if (offsetInLine < content.getLine(caretLine).length()) { + TextLayout layout = renderer.getTextLayout(caretLine); + offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); + int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; + renderer.disposeTextLayout(layout); + caretOffset = offsetInLine + lineOffset; + caretAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; + showCaret(); + } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { + caretLine++; + caretOffset = content.getOffsetAtLine(caretLine); + caretAlignment = PREVIOUS_OFFSET_TRAILING; + showCaret(); + } +} +/** + * Moves the caret to the previous character or to the end of the previous + * line if the cursor is at the beginning of a line. + */ +void doSelectionCursorPrevious() { + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + caretAlignment = OFFSET_LEADING; + if (offsetInLine > 0) { + caretOffset = getClusterPrevious(caretOffset, caretLine); + showCaret(); + } else if (caretLine > 0) { + caretLine--; + lineOffset = content.getOffsetAtLine(caretLine); + caretOffset = lineOffset + content.getLine(caretLine).length(); + showCaret(); + } +} +/** + * Moves the caret one line down and to the same character offset relative + * to the beginning of the line. Moves the caret to the end of the new line + * if the new line is shorter than the character offset. + * Moves the caret to the end of the text if the caret already is on the + * last line. + * Adjusts the selection according to the caret change. This can either add + * to or subtract from the old selection, depending on the previous selection + * direction. + */ +void doSelectionLineDown() { + int oldColumnX = columnX = getPointAtOffset(caretOffset).x; + doLineDown(true); + columnX = oldColumnX; +} +/** + * Moves the caret one line up and to the same character offset relative + * to the beginning of the line. Moves the caret to the end of the new line + * if the new line is shorter than the character offset. + * Moves the caret to the beginning of the document if it is already on the + * first line. + * Adjusts the selection according to the caret change. This can either add + * to or subtract from the old selection, depending on the previous selection + * direction. + */ +void doSelectionLineUp() { + int oldColumnX = columnX = getPointAtOffset(caretOffset).x; + doLineUp(true); + columnX = oldColumnX; +} +/** + * Scrolls one page down so that the last line (truncated or whole) + * of the current page becomes the fully visible top line. + *

    + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the end + * of the text where a full page scroll is not possible. In this case + * the caret is moved after the last character. + *

    + * Adjusts the selection according to the caret change. This can either add + * to or subtract from the old selection, depending on the previous selection + * direction. + *

    + */ +void doSelectionPageDown(int pixels) { + int oldColumnX = columnX = getPointAtOffset(caretOffset).x; + doPageDown(true, pixels); + columnX = oldColumnX; +} +/** + * Scrolls one page up so that the first line (truncated or whole) + * of the current page becomes the fully visible last line. + *

    + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the beginning + * of the text where a full page scroll is not possible. In this case the + * caret is moved in front of the first character. + *

    + * Adjusts the selection according to the caret change. This can either add + * to or subtract from the old selection, depending on the previous selection + * direction. + *

    + */ +void doSelectionPageUp(int pixels) { + int oldColumnX = columnX = getPointAtOffset(caretOffset).x; + doPageUp(true, pixels); + columnX = oldColumnX; +} +/** + * Moves the caret to the end of the next word . + */ +void doSelectionWordNext() { + int newCaretOffset = getWordEnd(caretOffset); + // Force symmetrical movement for word next and previous. Fixes 14536 + caretAlignment = OFFSET_LEADING; + // don't change caret position if in single line mode and the cursor + // would be on a different line. fixes 5673 + if (!isSingleLine() || + content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) { + caretOffset = newCaretOffset; + showCaret(); + } +} +/** + * Moves the caret to the start of the previous word. + */ +void doSelectionWordPrevious() { + caretAlignment = OFFSET_LEADING; + caretOffset = getWordStart(caretOffset); + int caretLine = content.getLineAtOffset(caretOffset); + // word previous always comes from bottom line. when + // wrapping lines, stay on bottom line when on line boundary + if (wordWrap && caretLine < content.getLineCount() - 1 && + caretOffset == content.getOffsetAtLine(caretLine + 1)) { + caretLine++; + } + showCaret(); +} +/** + * Moves the caret one character to the left. Do not go to the previous line. + * When in a bidi locale and at a R2L character the caret is moved to the + * beginning of the R2L segment (visually right) and then one character to the + * left (visually left because it's now in a L2R segment). + */ +void doVisualPrevious() { + caretOffset = getClusterPrevious(caretOffset, getCaretLine()); + showCaret(); +} +/** + * Moves the caret one character to the right. Do not go to the next line. + * When in a bidi locale and at a R2L character the caret is moved to the + * end of the R2L segment (visually left) and then one character to the + * right (visually right because it's now in a L2R segment). + */ +void doVisualNext() { + caretOffset = getClusterNext(caretOffset, getCaretLine()); + showCaret(); +} +/** + * Moves the caret to the end of the next word. + * If a selection exists, move the caret to the end of the selection + * and remove the selection. + */ +void doWordNext() { + if (selection.y - selection.x > 0) { + caretOffset = selection.y; + showCaret(); + } else { + doSelectionWordNext(); + } +} +/** + * Moves the caret to the start of the previous word. + * If a selection exists, move the caret to the start of the selection + * and remove the selection. + */ +void doWordPrevious() { + if (selection.y - selection.x > 0) { + caretOffset = selection.x; + showCaret(); + } else { + doSelectionWordPrevious(); + } +} +/** + * Ends the autoscroll process. + */ +void endAutoScroll() { + autoScrollDirection = SWT.NULL; +} +public Color getBackground() { + checkWidget(); + if (background == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); + } + return background; +} +/** + * Returns the baseline, in pixels. + * + * Note: this API should not be used if a StyleRange attribute causes lines to + * have different heights (i.e. different fonts, rise, etc). + * + * @return baseline the baseline + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 3.0 + * + * @see #getBaseline(int) + */ +public int getBaseline() { + checkWidget(); + return renderer.getBaseline(); +} +/** + * Returns the baseline at the given offset, in pixels. + * + * @param offset the offset + * + * @return baseline the baseline + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • + *
    + * + * @since 3.2 + */ +public int getBaseline(int offset) { + checkWidget(); + if (!(0 <= offset && offset <= content.getCharCount())) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (isFixedLineHeight()) { + return renderer.getBaseline(); + } + int lineIndex = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + FontMetrics metrics = layout.getLineMetrics(lineInParagraph); + renderer.disposeTextLayout(layout); + return metrics.getAscent() + metrics.getLeading(); +} +/** + * Gets the BIDI coloring mode. When true the BIDI text display + * algorithm is applied to segments of text that are the same + * color. + * + * @return the current coloring mode + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @deprecated use BidiSegmentListener instead. + */ +public boolean getBidiColoring() { + checkWidget(); + return bidiColoring; +} +/** + * Returns the index of the last fully visible line. + * + * @return index of the last fully visible line. + */ +int getBottomIndex() { + int bottomIndex; + if (isFixedLineHeight()) { + int lineCount = 1; + int lineHeight = renderer.getLineHeight(); + if (lineHeight != 0) { + // calculate the number of lines that are fully visible + int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset(); + lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight; + } + bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); + } else { + int clientAreaHeight = this.clientAreaHeight - bottomMargin; + bottomIndex = getLineIndex(clientAreaHeight); + if (bottomIndex > 0) { + int linePixel = getLinePixel(bottomIndex); + int lineHeight = renderer.getLineHeight(bottomIndex); + if (linePixel + lineHeight > clientAreaHeight) { + if (getLinePixel(bottomIndex - 1) >= topMargin) { + bottomIndex--; + } + } + } + } + return bottomIndex; +} +Rectangle getBoundsAtOffset(int offset) { + int lineIndex = content.getLineAtOffset(offset); + String line = content.getLine(lineIndex); + Rectangle bounds; + if (line.length() != 0) { + int offsetInLine = offset - content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + bounds = layout.getBounds(offsetInLine, offsetInLine); + renderer.disposeTextLayout(layout); + } else { + bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); + } + bounds.x += leftMargin - horizontalScrollOffset; + bounds.y += getLinePixel(lineIndex); + return bounds; +} + +/** + * Returns the caret position relative to the start of the text. + * + * @return the caret position relative to the start of the text. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getCaretOffset() { + checkWidget(); + return caretOffset; +} +/** + * Returns the caret width. + * + * @return the caret width, 0 if caret is null. + */ +int getCaretWidth() { + Caret caret = getCaret(); + if (caret == null) return 0; + return caret.getSize().x; +} +Object getClipboardContent(int clipboardType) { + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + return clipboard.getContents(plainTextTransfer, clipboardType); +} +int getClusterNext(int offset, int lineIndex) { + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + offset -= lineOffset; + offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER); + offset += lineOffset; + renderer.disposeTextLayout(layout); + return offset; +} +int getClusterPrevious(int offset, int lineIndex) { + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + offset -= lineOffset; + offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER); + offset += lineOffset; + renderer.disposeTextLayout(layout); + return offset; +} +/** + * Returns the content implementation that is used for text storage + * or null if no user defined content implementation has been set. + * + * @return content implementation that is used for text storage or null + * if no user defined content implementation has been set. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public StyledTextContent getContent() { + checkWidget(); + return content; +} +/** + * Returns whether the widget implements double click mouse behavior. + * + * @return true if double clicking a word selects the word, false if double clicks + * have the same effect as regular mouse clicks + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getDoubleClickEnabled() { + checkWidget(); + return doubleClickEnabled; +} +/** + * Returns whether the widget content can be edited. + * + * @return true if content can be edited, false otherwise + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getEditable() { + checkWidget(); + return editable; +} +public Color getForeground() { + checkWidget(); + if (foreground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); + } + return foreground; +} +/** + * Returns the horizontal scroll increment. + * + * @return horizontal scroll increment. + */ +int getHorizontalIncrement() { + GC gc = new GC(this); + int increment = gc.getFontMetrics().getAverageCharWidth(); + gc.dispose(); + return increment; +} +/** + * Returns the horizontal scroll offset relative to the start of the line. + * + * @return horizontal scroll offset relative to the start of the line, + * measured in character increments starting at 0, if > 0 the content is scrolled + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getHorizontalIndex() { + checkWidget(); + return horizontalScrollOffset / getHorizontalIncrement(); +} +/** + * Returns the horizontal scroll offset relative to the start of the line. + * + * @return the horizontal scroll offset relative to the start of the line, + * measured in pixel starting at 0, if > 0 the content is scrolled. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getHorizontalPixel() { + checkWidget(); + return horizontalScrollOffset; +} +/** + * Returns the line indentation of the widget. + * + * @return the line indentation + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getLineIndent(int) + * + * @since 3.2 + */ +public int getIndent() { + checkWidget(); + return indent; +} +/** + * Returns whether the widget justifies lines. + * + * @return whether lines are justified + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getLineJustify(int) + * + * @since 3.2 + */ +public boolean getJustify() { + checkWidget(); + return justify; +} +/** + * Returns the action assigned to the key. + * Returns SWT.NULL if there is no action associated with the key. + * + * @param key a key code defined in SWT.java or a character. + * Optionally ORd with a state mask. Preferred state masks are one or more of + * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform + * differences. However, there may be cases where using the specific state masks + * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. + * @return one of the predefined actions defined in ST.java or SWT.NULL + * if there is no action associated with the key. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getKeyBinding(int key) { + checkWidget(); + Integer action = (Integer) keyActionMap.get(new Integer(key)); + return action == null ? SWT.NULL : action.intValue(); +} +/** + * Gets the number of characters. + * + * @return number of characters in the widget + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getCharCount() { + checkWidget(); + return content.getCharCount(); +} +/** + * Returns the alignment of the line at the given index. + * + * @param index the index of the line + * + * @return the line alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • + *
    + * + * @see #getAlignment() + * + * @since 3.2 + */ +public int getLineAlignment(int index) { + checkWidget(); + if (index < 0 || index > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return renderer.getLineAlignment(index, alignment); +} +/** + * Returns the line at the specified offset in the text + * where 0 <= offset <= getCharCount() so that getLineAtOffset(getCharCount()) + * returns the line of the insert location. + * + * @param offset offset relative to the start of the content. + * 0 <= offset <= getCharCount() + * @return line at the specified offset in the text + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • + *
    + */ +public int getLineAtOffset(int offset) { + checkWidget(); + if (offset < 0 || offset > getCharCount()) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getLineAtOffset(offset); +} +/** + * Returns the background color of the line at the given index. + * Returns null if a LineBackgroundListener has been set or if no background + * color has been specified for the line. Should not be called if a + * LineBackgroundListener has been set since the listener maintains the + * line background colors. + * + * @param index the index of the line + * @return the background color of the line at the given index. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • + *
    + */ +public Color getLineBackground(int index) { + checkWidget(); + if (index < 0 || index > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return isListening(LineGetBackground) ? null : renderer.getLineBackground(index, null); +} +/** + * Returns the bullet of the line at the given index. + * + * @param index the index of the line + * + * @return the line bullet + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • + *
    + * + * @since 3.2 + */ +public Bullet getLineBullet(int index) { + checkWidget(); + if (index < 0 || index > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null); +} +/** + * Returns the line background data for the given line or null if + * there is none. + * + * @param lineOffset offset of the line start relative to the start + * of the content. + * @param line line to get line background data for + * @return line background data for the given line. + */ +StyledTextEvent getLineBackgroundData(int lineOffset, String line) { + return sendLineEvent(LineGetBackground, lineOffset, line); +} +/** + * Gets the number of text lines. + * + * @return the number of lines in the widget + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getLineCount() { + checkWidget(); + return content.getLineCount(); +} +/** + * Returns the number of lines that can be completely displayed in the + * widget client area. + * + * @return number of lines that can be completely displayed in the widget + * client area. + */ +int getLineCountWhole() { + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + return lineHeight != 0 ? clientAreaHeight / lineHeight : 1; + } + return getBottomIndex() - topIndex + 1; +} +/** + * Returns the line delimiter used for entering new lines by key down + * or paste operation. + * + * @return line delimiter used for entering new lines by key down + * or paste operation. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getLineDelimiter() { + checkWidget(); + return content.getLineDelimiter(); +} +/** + * Returns the line height. + *

    + * Note: this API should not be used if a StyleRange attribute causes lines to + * have different heights (i.e. different fonts, rise, etc). + *

    + * + * @return line height in pixel. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @see #getLineHeight(int) + */ +public int getLineHeight() { + checkWidget(); + return renderer.getLineHeight(); +} +/** + * Returns the line height at the given offset. + * + * @param offset the offset + * + * @return line height in pixels + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • + *
    + * + * @since 3.2 + */ +public int getLineHeight(int offset) { + checkWidget(); + if (!(0 <= offset && offset <= content.getCharCount())) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (isFixedLineHeight()) { + return renderer.getLineHeight(); + } + int lineIndex = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + int height = layout.getLineBounds(lineInParagraph).height; + renderer.disposeTextLayout(layout); + return height; +} +/** + * Returns the indentation of the line at the given index. + * + * @param index the index of the line + * + * @return the line indentation + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • + *
    + * + * @see #getIndent() + * + * @since 3.2 + */ +public int getLineIndent(int index) { + checkWidget(); + if (index < 0 || index > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return isListening(LineGetStyle) ? 0 : renderer.getLineIndent(index, indent); +} +/** + * Returns whether the line at the given index is justified. + * + * @param index the index of the line + * + * @return whether the line is justified + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the index is invalid
    • + *
    + * + * @see #getJustify() + * + * @since 3.2 + */ +public boolean getLineJustify(int index) { + checkWidget(); + if (index < 0 || index > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); +} +/** + * Returns the line spacing of the widget. + * + * @return the line spacing + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public int getLineSpacing() { + checkWidget(); + return lineSpacing; +} +/** + * Returns the line style data for the given line or null if there is + * none. + *

    + * If there is a LineStyleListener but it does not set any styles, + * the StyledTextEvent.styles field will be initialized to an empty + * array. + *

    + * + * @param lineOffset offset of the line start relative to the start of + * the content. + * @param line line to get line styles for + * @return line style data for the given line. Styles may start before + * line start and end after line end + */ +StyledTextEvent getLineStyleData(int lineOffset, String line) { + return sendLineEvent(LineGetStyle, lineOffset, line); +} +/** + * Returns the top pixel, relative to the client area, of a given line. + * Clamps out of ranges index. + * + * @param lineIndex the line index, the max value is lineCount. If + * lineIndex == lineCount it returns the bottom pixel of the last line. + * It means this function can be used to retrieve the bottom pixel of any line. + * + * @since 3.2 + */ +public int getLinePixel(int lineIndex) { + checkWidget(); + int lineCount = content.getLineCount(); + lineIndex = Math.max(0, Math.min(lineCount, lineIndex)); + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin; + } + if (lineIndex == topIndex) return topIndexY + topMargin; + int height = topIndexY; + if (lineIndex > topIndex) { + for (int i = topIndex; i < lineIndex; i++) { + height += renderer.getLineHeight(i); + } + } else { + for (int i = topIndex - 1; i >= lineIndex; i--) { + height -= renderer.getLineHeight(i); + } + } + return height + topMargin; +} +/** + * Returns the line index for a y, relative to the client area. + * The line index returned is always in the range 0..lineCount - 1. + * + * @since 3.2 + */ +public int getLineIndex(int y) { + checkWidget(); + y -= topMargin; + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + int lineIndex = (y + getVerticalScrollOffset()) / lineHeight; + int lineCount = content.getLineCount(); + lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex)); + return lineIndex; + } + if (y == topIndexY) return topIndex; + int line = topIndex; + if (y < topIndexY) { + while (y < topIndexY && line > 0) { + y += renderer.getLineHeight(--line); + } + } else { + int lineCount = content.getLineCount(); + int lineHeight = renderer.getLineHeight(line); + while (y - lineHeight >= topIndexY && line < lineCount - 1) { + y -= lineHeight; + lineHeight = renderer.getLineHeight(++line); + } + } + return line; +} +/** + * Returns the x, y location of the upper left corner of the character + * bounding box at the specified offset in the text. The point is + * relative to the upper left corner of the widget client area. + * + * @param offset offset relative to the start of the content. + * 0 <= offset <= getCharCount() + * @return x, y location of the upper left corner of the character + * bounding box at the specified offset in the text. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • + *
    + */ +public Point getLocationAtOffset(int offset) { + checkWidget(); + if (offset < 0 || offset > getCharCount()) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return getPointAtOffset(offset); +} +/** + * Returns the character offset of the first character of the given line. + * + * @param lineIndex index of the line, 0 based relative to the first + * line in the content. 0 <= lineIndex < getLineCount(), except + * lineIndex may always be 0 + * @return offset offset of the first character of the line, relative to + * the beginning of the document. The first character of the document is + * at offset 0. + * When there are not any lines, getOffsetAtLine(0) is a valid call that + * answers 0. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
    • + *
    + * @since 2.0 + */ +public int getOffsetAtLine(int lineIndex) { + checkWidget(); + if (lineIndex < 0 || + (lineIndex > 0 && lineIndex >= content.getLineCount())) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getOffsetAtLine(lineIndex); +} +/** + * Returns the offset of the character at the given location relative + * to the first character in the document. + *

    + * The return value reflects the character offset that the caret will + * be placed at if a mouse click occurred at the specified location. + * If the x coordinate of the location is beyond the center of a character + * the returned offset will be behind the character. + *

    + * + * @param point the origin of character bounding box relative to + * the origin of the widget client area. + * @return offset of the character at the given location relative + * to the first character in the document. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when point is null
    • + *
    • ERROR_INVALID_ARGUMENT when there is no character at the specified location
    • + *
    + */ +public int getOffsetAtLocation(Point point) { + checkWidget(); + if (point == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + // is y above first line or is x before first column? + if (point.y + getVerticalScrollOffset() < 0 || point.x + horizontalScrollOffset < 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + int bottomIndex = getLineIndex(clientAreaHeight); + int height = getLinePixel(bottomIndex) + renderer.getLineHeight(bottomIndex); + if (point.y > height) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + int lineIndex = getLineIndex(point.y); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + int[] trailing = new int[1]; + int x = point.x + horizontalScrollOffset - leftMargin ; + int y = point.y - getLinePixel(lineIndex); + int offsetInLine = layout.getOffset(x, y, trailing); + String line = content.getLine(lineIndex); + if (offsetInLine != line.length() - 1) { + offsetInLine = Math.min(line.length(), offsetInLine + trailing[0]); + } + Rectangle rect = layout.getLineBounds(layout.getLineIndex(offsetInLine)); + renderer.disposeTextLayout(layout); + if (x > rect.x + rect.width) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return lineOffset + offsetInLine; +} +int getOffsetAtPoint(int x, int y) { + int lineIndex = getLineIndex(y); + y -= getLinePixel(lineIndex); + return getOffsetAtPoint(x, y, lineIndex); +} +/** + * Returns the offset at the specified x location in the specified line. + * + * @param x x location of the mouse location + * @param line line the mouse location is in + * @return the offset at the specified x location in the specified line, + * relative to the beginning of the document + */ +int getOffsetAtPoint(int x, int y, int lineIndex) { + TextLayout layout = renderer.getTextLayout(lineIndex); + x += horizontalScrollOffset - leftMargin; + int[] trailing = new int[1]; + int offsetInLine = layout.getOffset(x, y, trailing); + caretAlignment = OFFSET_LEADING; + if (trailing[0] != 0) { + int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); + //TODO handle bidi text + int lineStart = layout.getLineOffsets()[lineInParagraph]; + if (offsetInLine + trailing[0] == lineStart) { + offsetInLine += trailing[0]; + caretAlignment = PREVIOUS_OFFSET_TRAILING; + } else { + String line = content.getLine(lineIndex); + int level; + int offset = offsetInLine; + while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; + if (offset == 0 && Character.isDigit(line.charAt(offset))) { + level = isMirrored() ? 1 : 0; + } else { + level = layout.getLevel(offset) & 0x1; + } + offsetInLine += trailing[0]; + int trailingLevel = layout.getLevel(offsetInLine) & 0x1; + if ((level ^ trailingLevel) != 0) { + caretAlignment = PREVIOUS_OFFSET_TRAILING; + } else { + caretAlignment = OFFSET_LEADING; + } + } + } + renderer.disposeTextLayout(layout); + return offsetInLine + content.getOffsetAtLine(lineIndex); +} +/** + * Returns the orientation of the receiver. + * + * @return the orientation style + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1.2 + */ +public int getOrientation () { + checkWidget(); + return isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT; +} +/** + * Returns the index of the last partially visible line. + * + * @return index of the last partially visible line. + */ +int getPartialBottomIndex() { + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); + return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; + } + return getLineIndex(clientAreaHeight - bottomMargin); +} +/** + * Returns the index of the first partially visible line. + * + * @return index of the first partially visible line. + */ +int getPartialTopIndex() { + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + return getVerticalScrollOffset() / lineHeight; + } + return topIndexY <= 0 ? topIndex : topIndex - 1; +} +/** + * Returns the content in the specified range using the platform line + * delimiter to separate lines. + * + * @param writer the TextWriter to write line text into + * @return the content in the specified range using the platform line + * delimiter to separate lines as written by the specified TextWriter. + */ +String getPlatformDelimitedText(TextWriter writer) { + int end = writer.getStart() + writer.getCharCount(); + int startLine = content.getLineAtOffset(writer.getStart()); + int endLine = content.getLineAtOffset(end); + String endLineText = content.getLine(endLine); + int endLineOffset = content.getOffsetAtLine(endLine); + + for (int i = startLine; i <= endLine; i++) { + writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); + if (i < endLine) { + writer.writeLineDelimiter(PlatformLineDelimiter); + } + } + if (end > endLineOffset + endLineText.length()) { + writer.writeLineDelimiter(PlatformLineDelimiter); + } + writer.close(); + return writer.toString(); +} +/** + * Returns all the ranges of text that have an associated StyleRange. + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * The ranges array contains start and length pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] with length ranges[n+1] uses the style + * at styles[n/2] returned by getStyleRanges(int, int, boolean). + *

    + * + * @return the ranges or an empty array if a LineStyleListener has been set. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + * + * @see #getStyleRanges(boolean) + */ +public int[] getRanges() { + checkWidget(); + if (!isListening(LineGetStyle)) { + int[] ranges = renderer.getRanges(0, content.getCharCount()); + if (ranges != null) return ranges; + } + return new int[0]; +} +/** + * Returns the ranges of text that have an associated StyleRange. + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * The ranges array contains start and length pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] with length ranges[n+1] uses the style + * at styles[n/2] returned by getStyleRanges(int, int, boolean). + *

    + * + * @param start the start offset of the style ranges to return + * @param length the number of style ranges to return + * + * @return the ranges or an empty array if a LineStyleListener has been set. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE if start or length are outside the widget content
    • + *
    + * + * @since 3.2 + * + * @see #getStyleRanges(int, int, boolean) + */ +public int[] getRanges(int start, int length) { + checkWidget(); + int contentLength = getCharCount(); + int end = start + length; + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (!isListening(LineGetStyle)) { + int[] ranges = renderer.getRanges(start, length); + if (ranges != null) return ranges; + } + return new int[0]; +} +/** + * Returns the selection. + *

    + * Text selections are specified in terms of caret positions. In a text + * widget that contains N characters, there are N+1 caret positions, + * ranging from 0..N + *

    + * + * @return start and end of the selection, x is the offset of the first + * selected character, y is the offset after the last selected character. + * The selection values returned are visual (i.e., x will always always be + * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection + * (e.g., caretOffset == start of selection implies that the selection is RtoL). + * @see #getSelectionRange + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelection() { + checkWidget(); + return new Point(selection.x, selection.y); +} +/** + * Returns the selection. + * + * @return start and length of the selection, x is the offset of the + * first selected character, relative to the first character of the + * widget content. y is the length of the selection. + * The selection values returned are visual (i.e., length will always always be + * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection + * (e.g., caretOffset == start of selection implies that the selection is RtoL). + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelectionRange() { + checkWidget(); + return new Point(selection.x, selection.y - selection.x); +} +/** + * Returns the receiver's selection background color. + * + * @return the selection background color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.1 + */ +public Color getSelectionBackground() { + checkWidget(); + if (selectionBackground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); + } + return selectionBackground; +} +/** + * Gets the number of selected characters. + * + * @return the number of selected characters. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionCount() { + checkWidget(); + return getSelectionRange().y; +} +/** + * Returns the receiver's selection foreground color. + * + * @return the selection foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.1 + */ +public Color getSelectionForeground() { + checkWidget(); + if (selectionForeground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); + } + return selectionForeground; +} +/** + * Returns the selected text. + * + * @return selected text, or an empty String if there is no selection. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getSelectionText() { + checkWidget(); + return content.getTextRange(selection.x, selection.y - selection.x); +} +public int getStyle() { + int style = super.getStyle(); + style &= ~(SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.MIRRORED); + if (isMirrored()) { + style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED; + } else { + style |= SWT.LEFT_TO_RIGHT; + } + return style; +} + +/** + * Returns the text segments that should be treated as if they + * had a different direction than the surrounding text. + * + * @param lineOffset offset of the first character in the line. + * 0 based from the beginning of the document. + * @param line text of the line to specify bidi segments for + * @return text segments that should be treated as if they had a + * different direction than the surrounding text. Only the start + * index of a segment is specified, relative to the start of the + * line. Always starts with 0 and ends with the line length. + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the segment indices returned + * by the listener do not start with 0, are not in ascending order, + * exceed the line length or have duplicates
    • + *
    + */ +int [] getBidiSegments(int lineOffset, String line) { + if (!isBidi()) return null; + if (!isListening(LineGetSegments)) { + return getBidiSegmentsCompatibility(line, lineOffset); + } + StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); + int lineLength = line.length(); + int[] segments; + if (event == null || event.segments == null || event.segments.length == 0) { + segments = new int[] {0, lineLength}; + } else { + int segmentCount = event.segments.length; + + // test segment index consistency + if (event.segments[0] != 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + for (int i = 1; i < segmentCount; i++) { + if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + } + // ensure that last segment index is line end offset + if (event.segments[segmentCount - 1] != lineLength) { + segments = new int[segmentCount + 1]; + System.arraycopy(event.segments, 0, segments, 0, segmentCount); + segments[segmentCount] = lineLength; + } else { + segments = event.segments; + } + } + return segments; +} +/** + * @see #getBidiSegments + * Supports deprecated setBidiColoring API. Remove when API is removed. + */ +int [] getBidiSegmentsCompatibility(String line, int lineOffset) { + int lineLength = line.length(); + if (!bidiColoring) { + return new int[] {0, lineLength}; + } + StyleRange [] styles = null; + StyledTextEvent event = getLineStyleData(lineOffset, line); + if (event != null) { + styles = event.styles; + } else { + styles = renderer.getStyleRanges(lineOffset, lineLength, true); + } + if (styles == null || styles.length == 0) { + return new int[] {0, lineLength}; + } + int k=0, count = 1; + while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) { + k++; + } + int[] offsets = new int[(styles.length - k) * 2 + 2]; + for (int i = k; i < styles.length; i++) { + StyleRange style = styles[i]; + int styleLineStart = Math.max(style.start - lineOffset, 0); + int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); + styleLineEnd = Math.min (styleLineEnd, line.length ()); + if (i > 0 && count > 1 && + ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || + (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && + style.similarTo(styles[i-1])) { + offsets[count-2] = Math.min(offsets[count-2], styleLineStart); + offsets[count-1] = Math.max(offsets[count-1], styleLineEnd); + } else { + if (styleLineStart > offsets[count - 1]) { + offsets[count] = styleLineStart; + count++; + } + offsets[count] = styleLineEnd; + count++; + } + } + // add offset for last non-colored segment in line, if any + if (lineLength > offsets[count-1]) { + offsets [count] = lineLength; + count++; + } + if (count == offsets.length) { + return offsets; + } + int [] result = new int [count]; + System.arraycopy (offsets, 0, result, 0, count); + return result; +} +/** + * Returns the style range at the given offset. + *

    + * Returns null if a LineStyleListener has been set or if a style is not set + * for the offset. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param offset the offset to return the style for. + * 0 <= offset < getCharCount() must be true. + * @return a StyleRange with start == offset and length == 1, indicating + * the style at the given offset. null if a LineStyleListener has been set + * or if a style is not set for the given offset. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the offset is invalid
    • + *
    + */ +public StyleRange getStyleRangeAtOffset(int offset) { + checkWidget(); + if (offset < 0 || offset >= getCharCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (!isListening(LineGetStyle)) { + StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true); + if (ranges != null) return ranges[0]; + } + return null; +} +/** + * Returns the styles. + *

    + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * Note: Because a StyleRange includes the start and length, the + * same instance cannot occur multiple times in the array of styles. + * If the same style attributes, such as font and color, occur in + * multiple StyleRanges, getStyleRanges(boolean) + * can be used to get the styles without the ranges. + *

    + * + * @return the styles or an empty array if a LineStyleListener has been set. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getStyleRanges(boolean) + */ +public StyleRange[] getStyleRanges() { + checkWidget(); + return getStyleRanges(0, content.getCharCount(), true); +} +/** + * Returns the styles. + *

    + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * Note: When includeRanges is true, the start and length + * fields of each StyleRange will be valid, however the StyleRange + * objects may need to be cloned. When includeRanges is + * false, getRanges(int, int) can be used to get the + * associated ranges. + *

    + * + * @param includeRanges whether the start and length field of the StyleRanges should be set. + * + * @return the styles or an empty array if a LineStyleListener has been set. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + * + * @see #getRanges(int, int) + * @see #setStyleRanges(int[], StyleRange[]) + */ +public StyleRange[] getStyleRanges(boolean includeRanges) { + checkWidget(); + return getStyleRanges(0, content.getCharCount(), includeRanges); +} +/** + * Returns the styles for the given text range. + *

    + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * Note: Because the StyleRange includes the start and length, the + * same instance cannot occur multiple times in the array of styles. + * If the same style attributes, such as font and color, occur in + * multiple StyleRanges, getStyleRanges(int, int, boolean) + * can be used to get the styles without the ranges. + *

    + * @param start the start offset of the style ranges to return + * @param length the number of style ranges to return + * + * @return the styles or an empty array if a LineStyleListener has + * been set. The returned styles will reflect the given range. The first + * returned StyleRange will have a starting offset >= start + * and the last returned StyleRange will have an ending + * offset <= start + length - 1 + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • + *
    + * + * @see #getStyleRanges(int, int, boolean) + * + * @since 3.0 + */ +public StyleRange[] getStyleRanges(int start, int length) { + checkWidget(); + return getStyleRanges(start, length, true); +} +/** + * Returns the styles for the given text range. + *

    + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * Note: When includeRanges is true, the start and length + * fields of each StyleRange will be valid, however the StyleRange + * objects may need to be cloned. When includeRanges is + * false, getRanges(int, int) can be used to get the + * associated ranges. + *

    + * + * @param start the start offset of the style ranges to return + * @param length the number of style ranges to return + * @param includeRanges whether the start and length field of the StyleRanges should be set. + * + * @return the styles or an empty array if a LineStyleListener has + * been set. The returned styles will reflect the given range. The first + * returned StyleRange will have a starting offset >= start + * and the last returned StyleRange will have an ending + * offset <= start + length - 1 + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • + *
    + * + * @since 3.2 + * + * @see #getRanges(int, int) + * @see #setStyleRanges(int[], StyleRange[]) + */ +public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { + checkWidget(); + int contentLength = getCharCount(); + int end = start + length; + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (!isListening(LineGetStyle)) { + StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges); + if (ranges != null) return ranges; + } + return new StyleRange[0]; +} +/** + * Returns the tab width measured in characters. + * + * @return tab width measured in characters + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTabs() { + checkWidget(); + return tabLength; +} +/** + * Returns a copy of the widget content. + * + * @return copy of the widget content + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText() { + checkWidget(); + return content.getTextRange(0, getCharCount()); +} +/** + * Returns the widget content between the two offsets. + * + * @param start offset of the first character in the returned String + * @param end offset of the last character in the returned String + * @return widget content starting at start and ending at end + * @see #getTextRange(int,int) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • + *
    + */ +public String getText(int start, int end) { + checkWidget(); + int contentLength = getCharCount(); + if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getTextRange(start, end - start + 1); +} +/** + * Returns the smallest bounding rectangle that includes the characters between two offsets. + * + * @param start offset of the first character included in the bounding box + * @param end offset of the last character included in the bounding box + * @return bounding box of the text between start and end + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • + *
    + * @since 3.1 + */ +public Rectangle getTextBounds(int start, int end) { + checkWidget(); + int contentLength = getCharCount(); + if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + int lineStart = content.getLineAtOffset(start); + int lineEnd = content.getLineAtOffset(end); + Rectangle rect; + int y = getLinePixel(lineStart); + int height = 0; + int left = 0x7fffffff, right = 0; + for (int i = lineStart; i <= lineEnd; i++) { + int lineOffset = content.getOffsetAtLine(i); + TextLayout layout = renderer.getTextLayout(i); + if (i == lineStart && i == lineEnd) { + rect = layout.getBounds(start - lineOffset, end - lineOffset); + } else if (i == lineStart) { + String line = content.getLine(i); + rect = layout.getBounds(start - lineOffset, line.length()); + } else if (i == lineEnd) { + rect = layout.getBounds(0, end - lineOffset); + } else { + rect = layout.getBounds(); + } + left = Math.min (left, rect.x); + right = Math.max (right, rect.x + rect.width); + height += rect.height; + renderer.disposeTextLayout(layout); + } + rect = new Rectangle (left, y, right-left, height); + rect.x += leftMargin - horizontalScrollOffset; + return rect; +} +/** + * Returns the widget content starting at start for length characters. + * + * @param start offset of the first character in the returned String + * @param length number of characters to return + * @return widget content starting at start and extending length characters. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or length are outside the widget content
    • + *
    + */ +public String getTextRange(int start, int length) { + checkWidget(); + int contentLength = getCharCount(); + int end = start + length; + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getTextRange(start, length); +} +/** + * Returns the maximum number of characters that the receiver is capable of holding. + * + * @return the text limit + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTextLimit() { + checkWidget(); + return textLimit; +} +/** + * Gets the top index. + *

    + * The top index is the index of the fully visible line that is currently + * at the top of the widget or the topmost partially visible line if no line is fully visible. + * The top index changes when the widget is scrolled. Indexing is zero based. + *

    + * + * @return the index of the top line + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopIndex() { + checkWidget(); + return topIndex; +} +/** + * Gets the top pixel. + *

    + * The top pixel is the pixel position of the line that is + * currently at the top of the widget. The text widget can be scrolled by pixels + * by dragging the scroll thumb so that a partial line may be displayed at the top + * the widget. The top pixel changes when the widget is scrolled. The top pixel + * does not include the widget trimming. + *

    + * + * @return pixel position of the top line + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopPixel() { + checkWidget(); + return getVerticalScrollOffset(); +} +/** + * Returns the vertical scroll increment. + * + * @return vertical scroll increment. + */ +int getVerticalIncrement() { + return renderer.getLineHeight(); +} +int getVerticalScrollOffset() { + if (verticalScrollOffset == -1) { + renderer.calculate(0, topIndex); + int height = 0; + for (int i = 0; i < topIndex; i++) { + height += renderer.getLineHeight(i); + } + height -= topIndexY; + verticalScrollOffset = height; + } + return verticalScrollOffset; +} +int getVisualLineIndex(TextLayout layout, int offsetInLine) { + int lineIndex = layout.getLineIndex(offsetInLine); + int[] offsets = layout.getLineOffsets(); + if (lineIndex != 0 && offsetInLine == offsets[lineIndex] && caretAlignment == PREVIOUS_OFFSET_TRAILING) { + lineIndex--; + } + return lineIndex; +} +int getCaretDirection() { + if (!isBidiCaret()) return SWT.DEFAULT; + if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection; + updateCaretDirection = false; + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + String line = content.getLine(caretLine); + int offset = caretOffset - lineOffset; + int lineLength = line.length(); + if (lineLength == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT; + if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; + if (offset == lineLength && offset > 0) offset--; + while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; + if (offset == 0 && Character.isDigit(line.charAt(offset))) { + return isMirrored() ? SWT.RIGHT : SWT.LEFT; + } + TextLayout layout = renderer.getTextLayout(caretLine); + int level = layout.getLevel(offset); + renderer.disposeTextLayout(layout); + return ((level & 1) != 0) ? SWT.RIGHT : SWT.LEFT; +} +/* + * Returns the index of the line the caret is on. + */ +int getCaretLine() { + return content.getLineAtOffset(caretOffset); +} +int getWrapWidth () { + if (wordWrap && !isSingleLine()) { + int width = clientAreaWidth - leftMargin - rightMargin; + return width > 0 ? width : 1; + } + return -1; +} +/** + * Returns the offset of the character after the word at the specified + * offset. + *

    + * There are two classes of words formed by a sequence of characters: + *

      + *
    • from 0-9 and A-z (ASCII 48-57 and 65-122) + *
    • every other character except line breaks + *
    + *

    + * Space characters ' ' (ASCII 20) are special as they are treated as + * part of the word leading up to the space character. Line breaks are + * treated as one word. + *

    + */ +int getWordEnd(int offset) { + if (offset >= getCharCount()) { + return offset; + } + int lineIndex = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(lineIndex); + int lineLength = content.getLine(lineIndex).length(); + if (offset == lineOffset + lineLength) { + offset = content.getOffsetAtLine(lineIndex + 1); + } else { + TextLayout layout = renderer.getTextLayout(lineIndex); + offset -= lineOffset; + offset = layout.getNextOffset(offset, SWT.MOVEMENT_WORD); + offset += lineOffset; + renderer.disposeTextLayout(layout); + } + return offset; +} +/** + * Returns the offset of the character after the word at the specified + * offset. + *

    + * There are two classes of words formed by a sequence of characters: + *

      + *
    • from 0-9 and A-z (ASCII 48-57 and 65-122) + *
    • every other character except line breaks + *
    + *

    + * Spaces are ignored and do not represent a word. Line breaks are treated + * as one word. + *

    + */ +int getWordEndNoSpaces(int offset) { + if (offset >= getCharCount()) { + return offset; + } + int line = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(line); + String lineText = content.getLine(line); + int lineLength = lineText.length(); + if (offset == lineOffset + lineLength) { + line++; + offset = content.getOffsetAtLine(line); + } else { + offset -= lineOffset; + char ch = lineText.charAt(offset); + boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); + while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && !Compatibility.isSpaceChar(ch)) { + offset++; + ch = lineText.charAt(offset); + } + if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && !Compatibility.isSpaceChar(ch)) { + offset++; + } + offset += lineOffset; + } + return offset; +} +/** + * Returns the start offset of the word at the specified offset. + * There are two classes of words formed by a sequence of characters: + *

    + *

      + *
    • from 0-9 and A-z (ASCII 48-57 and 65-122) + *
    • every other character except line breaks + *
    + *

    + * Space characters ' ' (ASCII 20) are special as they are treated as + * part of the word leading up to the space character. Line breaks are treated + * as one word. + *

    + */ +int getWordStart(int offset) { + if (offset <= 0) { + return offset; + } + int lineIndex = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(lineIndex); + if (offset == lineOffset) { + lineIndex--; + String lineText = content.getLine(lineIndex); + offset = content.getOffsetAtLine(lineIndex) + lineText.length(); + } else { + TextLayout layout = renderer.getTextLayout(lineIndex); + offset -= lineOffset; + offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_WORD); + offset += lineOffset; + renderer.disposeTextLayout(layout); + } + return offset; +} +/** + * Returns whether the widget wraps lines. + * + * @return true if widget wraps lines, false otherwise + * @since 2.0 + */ +public boolean getWordWrap() { + checkWidget(); + return wordWrap; +} +/** + * Returns the location of the given offset. + *

    + * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts). + *

    + * + * @return location of the character at the given offset in the line. + */ +Point getPointAtOffset(int offset) { + int lineIndex = content.getLineAtOffset(offset); + String line = content.getLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); + int offsetInLine = offset - lineOffset; + int lineLength = line.length(); + if (lineIndex < content.getLineCount() - 1) { + int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; + if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { + offsetInLine = lineLength; + } + } + Point point; + TextLayout layout = renderer.getTextLayout(lineIndex); + if (lineLength != 0 && offsetInLine <= lineLength) { + if (offsetInLine == lineLength) { + point = layout.getLocation(offsetInLine - 1, true); + } else { + switch (caretAlignment) { + case OFFSET_LEADING: + point = layout.getLocation(offsetInLine, false); + break; + case PREVIOUS_OFFSET_TRAILING: + default: + if (offsetInLine == 0) { + point = layout.getLocation(offsetInLine, false); + } else { + point = layout.getLocation(offsetInLine - 1, true); + } + break; + } + } + } else { + point = new Point(layout.getIndent(), 0); + } + renderer.disposeTextLayout(layout); + point.x += leftMargin - horizontalScrollOffset; + point.y += getLinePixel(lineIndex); + return point; +} +/** + * Inserts a string. The old selection is replaced with the new text. + * + * @param string the string + * @see #replaceTextRange(int,int,String) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when string is null
    • + *
    + */ +public void insert(String string) { + checkWidget(); + if (string == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + Point sel = getSelectionRange(); + replaceTextRange(sel.x, sel.y, string); +} +/** + * Creates content change listeners and set the default content model. + */ +void installDefaultContent() { + textChangeListener = new TextChangeListener() { + public void textChanging(TextChangingEvent event) { + handleTextChanging(event); + } + public void textChanged(TextChangedEvent event) { + handleTextChanged(event); + } + public void textSet(TextChangedEvent event) { + handleTextSet(event); + } + }; + content = new DefaultContent(); + content.addTextChangeListener(textChangeListener); +} +/** + * Adds event listeners + */ +void installListeners() { + ScrollBar verticalBar = getVerticalBar(); + ScrollBar horizontalBar = getHorizontalBar(); + + listener = new Listener() { + public void handleEvent(Event event) { + switch (event.type) { + case SWT.Dispose: handleDispose(event); break; + case SWT.DragDetect: handleDragDetect(event); break; + case SWT.KeyDown: handleKeyDown(event); break; + case SWT.KeyUp: handleKeyUp(event); break; + case SWT.MouseDown: handleMouseDown(event); break; + case SWT.MouseUp: handleMouseUp(event); break; + case SWT.MouseDoubleClick: handleMouseDoubleClick(event); break; + case SWT.MouseMove: handleMouseMove(event); break; + case SWT.Paint: handlePaint(event); break; + case SWT.Resize: handleResize(event); break; + case SWT.Traverse: handleTraverse(event); break; + } + } + }; + addListener(SWT.Dispose, listener); + // do not hook SWT.DragDetect until required + addListener(SWT.KeyDown, listener); + addListener(SWT.KeyUp, listener); + addListener(SWT.MouseDown, listener); + addListener(SWT.MouseUp, listener); + addListener(SWT.MouseDoubleClick, listener); + addListener(SWT.MouseMove, listener); + addListener(SWT.Paint, listener); + addListener(SWT.Resize, listener); + addListener(SWT.Traverse, listener); + if (verticalBar != null) { + verticalBar.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + handleVerticalScroll(event); + } + }); + } + if (horizontalBar != null) { + horizontalBar.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + handleHorizontalScroll(event); + } + }); + } +} +void internalRedrawRange(int start, int length) { + if (length <= 0) return; + int end = start + length; + int startLine = content.getLineAtOffset(start); + int endLine = content.getLineAtOffset(end); + int partialBottomIndex = getPartialBottomIndex(); + int partialTopIndex = getPartialTopIndex(); + if (startLine > partialBottomIndex || endLine < partialTopIndex) { + return; + } + if (partialTopIndex > startLine) { + startLine = partialTopIndex; + start = 0; + } else { + start -= content.getOffsetAtLine(startLine); + } + if (partialBottomIndex < endLine) { + endLine = partialBottomIndex + 1; + end = 0; + } else { + end -= content.getOffsetAtLine(endLine); + } + + TextLayout layout = renderer.getTextLayout(startLine); + int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); + int[] offsets = layout.getLineOffsets(); + int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); + + /* Redraw end of line before start line if wrapped and start offset is first char */ + if (wordWrap && startIndex > 0 && offsets[startIndex] == start) { + Rectangle rect = layout.getLineBounds(startIndex - 1); + rect.x = rect.width; + rect.width = clientAreaWidth - rightMargin - rect.x; + rect.x += lineX; + rect.y += startLineY; + super.redraw(rect.x, rect.y, rect.width, rect.height, false); + } + + if (startLine == endLine) { + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + if (startIndex == endIndex) { + /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ + Rectangle rect = layout.getBounds(start, end - 1); + rect.x += lineX; + rect.y += startLineY; + super.redraw(rect.x, rect.y, rect.width, rect.height, false); + renderer.disposeTextLayout(layout); + return; + } + } + + /* Redraw start line from the start offset to the end of client area */ + Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1); + if (startRect.height == 0) { + Rectangle bounds = layout.getLineBounds(startIndex); + startRect.x = bounds.width; + startRect.y = bounds.y; + startRect.height = bounds.height; + } + startRect.x += lineX; + startRect.y += startLineY; + startRect.width = clientAreaWidth - rightMargin - startRect.x; + super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false); + + /* Redraw end line from the begining of the line to the end offset */ + if (startLine != endLine) { + renderer.disposeTextLayout(layout); + layout = renderer.getTextLayout(endLine); + offsets = layout.getLineOffsets(); + } + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); + if (endRect.height == 0) { + Rectangle bounds = layout.getLineBounds(endIndex); + endRect.y = bounds.y; + endRect.height = bounds.height; + } + endRect.x += lineX; + endRect.y += getLinePixel(endLine); + super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false); + renderer.disposeTextLayout(layout); + + /* Redraw all lines in between start and end line */ + int y = startRect.y + startRect.height; + if (endRect.y > y) { + super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false); + } +} +/** + * Frees resources. + */ +void handleDispose(Event event) { + removeListener(SWT.Dispose, listener); + notifyListeners(SWT.Dispose, event); + event.type = SWT.None; + + clipboard.dispose(); + if (renderer != null) { + renderer.dispose(); + renderer = null; + } + if (content != null) { + content.removeTextChangeListener(textChangeListener); + content = null; + } + if (defaultCaret != null) { + defaultCaret.dispose(); + defaultCaret = null; + } + if (leftCaretBitmap != null) { + leftCaretBitmap.dispose(); + leftCaretBitmap = null; + } + if (rightCaretBitmap != null) { + rightCaretBitmap.dispose(); + rightCaretBitmap = null; + } + if (isBidiCaret()) { + BidiUtil.removeLanguageListener(handle); + } + selectionBackground = null; + selectionForeground = null; + textChangeListener = null; + selection = null; + doubleClickSelection = null; + keyActionMap = null; + background = null; + foreground = null; + clipboard = null; +} +void handleDragDetect(Event event) { + dragging = true; +} +/** + * Scrolls the widget horizontally. + */ +void handleHorizontalScroll(Event event) { + int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; + scrollHorizontal(scrollPixel, false); +} +/** + * If an action has been registered for the key stroke execute the action. + * Otherwise, if a character has been entered treat it as new content. + * + * @param event keyboard event + */ +void handleKey(Event event) { + int action; + caretAlignment = PREVIOUS_OFFSET_TRAILING; + if (event.keyCode != 0) { + // special key pressed (e.g., F1) + action = getKeyBinding(event.keyCode | event.stateMask); + } else { + // character key pressed + action = getKeyBinding(event.character | event.stateMask); + if (action == SWT.NULL) { + // see if we have a control character + if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) { + // get the character from the CTRL+char sequence, the control + // key subtracts 64 from the value of the key that it modifies + int c = event.character + 64; + action = getKeyBinding(c | event.stateMask); + } + } + } + if (action == SWT.NULL) { + boolean ignore = false; + + if (IS_CARBON) { + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Do not + // ignore COMMAND+ALT combinations since that key sequence + // produces characters on the mac. + ignore = (event.stateMask ^ SWT.COMMAND) == 0 || + (event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0; + } else if (IS_MOTIF) { + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Do not + // ignore ALT combinations since this key sequence + // produces characters on motif. + ignore = (event.stateMask ^ SWT.CTRL) == 0 || + (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; + } else { + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Don't + // ignore CTRL+ALT combinations since that is the Alt Gr + // key on some keyboards. See bug 20953. + ignore = (event.stateMask ^ SWT.ALT) == 0 || + (event.stateMask ^ SWT.CTRL) == 0 || + (event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 || + (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; + } + // -ignore anything below SPACE except for line delimiter keys and tab. + // -ignore DEL + if (!ignore && event.character > 31 && event.character != SWT.DEL || + event.character == SWT.CR || event.character == SWT.LF || + event.character == TAB) { + doContent(event.character); + update(); + } + } else { + invokeAction(action); + } +} +/** + * If a VerifyKey listener exists, verify that the key that was entered + * should be processed. + * + * @param event keyboard event + */ +void handleKeyDown(Event event) { + if (clipboardSelection == null) { + clipboardSelection = new Point(selection.x, selection.y); + } + + Event verifyEvent = new Event(); + verifyEvent.character = event.character; + verifyEvent.keyCode = event.keyCode; + verifyEvent.stateMask = event.stateMask; + verifyEvent.doit = true; + notifyListeners(VerifyKey, verifyEvent); + if (verifyEvent.doit) { + handleKey(event); + } +} +/** + * Update the Selection Clipboard. + * + * @param event keyboard event + */ +void handleKeyUp(Event event) { + if (clipboardSelection != null) { + if (clipboardSelection.x != selection.x || clipboardSelection.y != selection.y) { + try { + if (selection.y - selection.x > 0) { + setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); + } + } catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + } + } + } + clipboardSelection = null; +} +/** + * Updates the caret location and selection if mouse button 1 has been + * pressed. + */ +void handleMouseDoubleClick(Event event) { + if (event.button != 1 || !doubleClickEnabled) { + return; + } + mouseDoubleClick = true; + caretOffset = getWordStart(caretOffset); + resetSelection(); + caretOffset = getWordEndNoSpaces(caretOffset); + showCaret(); + doMouseSelection(); + doubleClickSelection = new Point(selection.x, selection.y); +} +/** + * Updates the caret location and selection if mouse button 1 has been + * pressed. + */ +void handleMouseDown(Event event) { + mouseDoubleClick = false; + + //force focus (object support) + forceFocus(); + + dragging = false; + removeListener(SWT.DragDetect, listener); + dragDetect = detectDrag(event.x, event.y, event.button); + if (dragDetect) { + addListener(SWT.DragDetect, listener); + return; + } + + mouseDown = true; + if (event.button == 2) { + String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD); + if (text != null && text.length() > 0) { + // position cursor + doMouseLocationChange(event.x, event.y, false); + // insert text + Event e = new Event(); + e.start = selection.x; + e.end = selection.y; + e.text = getModelDelimitedText(text); + sendKeyEvent(e); + } + } + if ((event.button != 1) || (IS_CARBON && (event.stateMask & SWT.MOD4) != 0)) { + return; + } + boolean select = (event.stateMask & SWT.MOD2) != 0; + doMouseLocationChange(event.x, event.y, select); +} +/** + * Updates the caret location and selection if mouse button 1 is pressed + * during the mouse move. + */ +void handleMouseMove(Event event) { + if (!mouseDown) return; + if ((event.stateMask & SWT.BUTTON1) == 0) { + return; + } + doMouseLocationChange(event.x, event.y, true); + update(); + doAutoScroll(event); +} +/** + * Autoscrolling ends when the mouse button is released. + */ +void handleMouseUp(Event event) { + mouseDown = false; + mouseDoubleClick = false; + endAutoScroll(); + if (dragDetect) { + removeListener(SWT.DragDetect, listener); + if (!dragging) { + boolean select = (event.stateMask & SWT.MOD2) != 0; + doMouseLocationChange(event.x, event.y, select); + } + } + dragDetect = dragging = false; + if (event.button == 1) { + try { + if (selection.y - selection.x > 0) { + setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); + } + } catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + } + } +} +/** + * Renders the invalidated area specified in the paint event. + * + * @param event paint event + */ +void handlePaint(Event event) { + if (event.width == 0 || event.height == 0) return; + if (clientAreaWidth == 0 || clientAreaHeight == 0) return; + + int startLine = getLineIndex(event.y); + int y = getLinePixel(startLine); + int endY = event.y + event.height; + GC gc = event.gc; + Color background = getBackground(); + Color foreground = getForeground(); + if (endY > 0) { + int lineCount = isSingleLine() ? 1 : content.getLineCount(); + int x = leftMargin - horizontalScrollOffset; + for (int i = startLine; y < endY && i < lineCount; i++) { + y += renderer.drawLine(i, x, y, gc, background, foreground); + } + if (y < endY) { + gc.setBackground(background); + drawBackground(gc, 0, y, clientAreaWidth, endY - y); + } + } + // fill the margin background + gc.setBackground(background); + if (topMargin > 0) { + drawBackground(gc, 0, 0, clientAreaWidth, topMargin); + } + if (bottomMargin > 0) { + drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin); + } + if (leftMargin > 0) { + drawBackground(gc, 0, 0, leftMargin, clientAreaHeight); + } + if (rightMargin > 0) { + drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight); + } +} +/** + * Recalculates the scroll bars. Rewraps all lines when in word + * wrap mode. + * + * @param event resize event + */ +void handleResize(Event event) { + int oldHeight = clientAreaHeight; + int oldWidth = clientAreaWidth; + Rectangle clientArea = getClientArea(); + clientAreaHeight = clientArea.height; + clientAreaWidth = clientArea.width; + /* Redraw the old or new right/bottom margin if needed */ + if (oldWidth != clientAreaWidth) { + if (rightMargin > 0) { + int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; + super.redraw(x, 0, rightMargin, oldHeight, false); + } + } + if (oldHeight != clientAreaHeight) { + if (bottomMargin > 0) { + int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; + super.redraw(0, y, oldWidth, bottomMargin, false); + } + } + if (wordWrap) { + if (oldWidth != clientAreaWidth) { + renderer.reset(0, content.getLineCount()); + verticalScrollOffset = -1; + renderer.calculateIdle(); + super.redraw(); + } + if (oldHeight != clientAreaHeight) { + if (oldHeight == 0) topIndexY = 0; + setScrollBars(true); + } + setCaretLocation(); + } else { + renderer.calculateClientArea(); + setScrollBars(true); + claimRightFreeSpace(); + } + claimBottomFreeSpace(); + //TODO FIX TOP INDEX DURING RESIZE +// if (oldHeight != clientAreaHeight || wordWrap) { +// calculateTopIndex(0); +// } +} +/** + * Updates the caret position and selection and the scroll bars to reflect + * the content change. + */ +void handleTextChanged(TextChangedEvent event) { + int firstLine = content.getLineAtOffset(lastTextChangeStart); + resetCache(firstLine, 0); + if (!isFixedLineHeight() && topIndex > firstLine) { + topIndex = firstLine; + topIndexY = 0; + super.redraw(); + } else { + int lastLine = firstLine + lastTextChangeNewLineCount; + int firstLineTop = getLinePixel(firstLine); + int newLastLineBottom = getLinePixel(lastLine + 1); + if (lastLineBottom != newLastLineBottom) { + scrollText(lastLineBottom, newLastLineBottom); + if (wordWrap) setCaretLocation(); + } + super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); + redrawLinesBullet(renderer.redrawLines); + } + renderer.redrawLines = null; + // update selection/caret location after styles have been changed. + // otherwise any text measuring could be incorrect + // + // also, this needs to be done after all scrolling. Otherwise, + // selection redraw would be flushed during scroll which is wrong. + // in some cases new text would be drawn in scroll source area even + // though the intent is to scroll it. + updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); + if (lastTextChangeReplaceLineCount > 0 || wordWrap) { + claimBottomFreeSpace(); + } + if (lastTextChangeReplaceCharCount > 0) { + claimRightFreeSpace(); + } +} +/** + * Updates the screen to reflect a pending content change. + * + * @param event.start the start offset of the change + * @param event.newText text that is going to be inserted or empty String + * if no text will be inserted + * @param event.replaceCharCount length of text that is going to be replaced + * @param event.newCharCount length of text that is going to be inserted + * @param event.replaceLineCount number of lines that are going to be replaced + * @param event.newLineCount number of new lines that are going to be inserted + */ +void handleTextChanging(TextChangingEvent event) { + if (event.replaceCharCount < 0) { + event.start += event.replaceCharCount; + event.replaceCharCount *= -1; + } + lastTextChangeStart = event.start; + lastTextChangeNewLineCount = event.newLineCount; + lastTextChangeNewCharCount = event.newCharCount; + lastTextChangeReplaceLineCount = event.replaceLineCount; + lastTextChangeReplaceCharCount = event.replaceCharCount; + int lineIndex = content.getLineAtOffset(event.start); + int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); + int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); + lastLineBottom = destY; + scrollText(srcY, destY); + + renderer.textChanging(event); + + // Update the caret offset if it is greater than the length of the content. + // This is necessary since style range API may be called between the + // handleTextChanging and handleTextChanged events and this API sets the + // caretOffset. + int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; + if (caretOffset > newEndOfText) caretOffset = newEndOfText; +} +/** + * Called when the widget content is set programatically, overwriting + * the old content. Resets the caret position, selection and scroll offsets. + * Recalculates the content width and scroll bars. Redraws the widget. + * + * @param event text change event. + */ +void handleTextSet(TextChangedEvent event) { + reset(); +} +/** + * Called when a traversal key is pressed. + * Allow tab next traversal to occur when the widget is in single + * line mode or in multi line and non-editable mode . + * When in editable multi line mode we want to prevent the tab + * traversal and receive the tab key event instead. + * + * @param event the event + */ +void handleTraverse(Event event) { + switch (event.detail) { + case SWT.TRAVERSE_ESCAPE: + case SWT.TRAVERSE_PAGE_NEXT: + case SWT.TRAVERSE_PAGE_PREVIOUS: + event.doit = true; + break; + case SWT.TRAVERSE_RETURN: + case SWT.TRAVERSE_TAB_NEXT: + case SWT.TRAVERSE_TAB_PREVIOUS: + if ((getStyle() & SWT.SINGLE) != 0) { + event.doit = true; + } else { + if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) { + event.doit = true; + } + } + break; + } +} +/** + * Scrolls the widget vertically. + */ +void handleVerticalScroll(Event event) { + int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset(); + scrollVertical(scrollPixel, false); +} +/** + * Add accessibility support for the widget. + */ +void initializeAccessible() { + final Accessible accessible = getAccessible(); + accessible.addAccessibleListener(new AccessibleAdapter() { + public void getName (AccessibleEvent e) { + String name = null; + Label label = getAssociatedLabel (); + if (label != null) { + name = stripMnemonic (label.getText()); + } + e.result = name; + } + public void getHelp(AccessibleEvent e) { + e.result = getToolTipText(); + } + public void getKeyboardShortcut(AccessibleEvent e) { + String shortcut = null; + Label label = getAssociatedLabel (); + if (label != null) { + String text = label.getText (); + if (text != null) { + char mnemonic = _findMnemonic (text); + if (mnemonic != '\0') { + shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ + } + } + } + e.result = shortcut; + } + }); + accessible.addAccessibleTextListener(new AccessibleTextAdapter() { + public void getCaretOffset(AccessibleTextEvent e) { + e.offset = StyledText.this.getCaretOffset(); + } + public void getSelectionRange(AccessibleTextEvent e) { + Point selection = StyledText.this.getSelectionRange(); + e.offset = selection.x; + e.length = selection.y; + } + }); + accessible.addAccessibleControlListener(new AccessibleControlAdapter() { + public void getRole(AccessibleControlEvent e) { + e.detail = ACC.ROLE_TEXT; + } + public void getState(AccessibleControlEvent e) { + int state = 0; + if (isEnabled()) state |= ACC.STATE_FOCUSABLE; + if (isFocusControl()) state |= ACC.STATE_FOCUSED; + if (!isVisible()) state |= ACC.STATE_INVISIBLE; + if (!getEditable()) state |= ACC.STATE_READONLY; + e.detail = state; + } + public void getValue(AccessibleControlEvent e) { + e.result = StyledText.this.getText(); + } + }); + addListener(SWT.FocusIn, new Listener() { + public void handleEvent(Event event) { + accessible.setFocus(ACC.CHILDID_SELF); + } + }); +} +/* + * Return the Label immediately preceding the receiver in the z-order, + * or null if none. + */ +Label getAssociatedLabel () { + Control[] siblings = getParent ().getChildren (); + for (int i = 0; i < siblings.length; i++) { + if (siblings [i] == StyledText.this) { + if (i > 0 && siblings [i-1] instanceof Label) { + return (Label) siblings [i-1]; + } + } + } + return null; +} +String stripMnemonic (String string) { + int index = 0; + int length = string.length (); + do { + while ((index < length) && (string.charAt (index) != '&')) index++; + if (++index >= length) return string; + if (string.charAt (index) != '&') { + return string.substring(0, index-1) + string.substring(index, length); + } + index++; + } while (index < length); + return string; +} +/* + * Return the lowercase of the first non-'&' character following + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +char _findMnemonic (String string) { + if (string == null) return '\0'; + int index = 0; + int length = string.length (); + do { + while (index < length && string.charAt (index) != '&') index++; + if (++index >= length) return '\0'; + if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index)); + index++; + } while (index < length); + return '\0'; +} +/** + * Executes the action. + * + * @param action one of the actions defined in ST.java + */ +public void invokeAction(int action) { + checkWidget(); + updateCaretDirection = true; + switch (action) { + // Navigation + case ST.LINE_UP: + doLineUp(false); + clearSelection(true); + break; + case ST.LINE_DOWN: + doLineDown(false); + clearSelection(true); + break; + case ST.LINE_START: + doLineStart(); + clearSelection(true); + break; + case ST.LINE_END: + doLineEnd(); + clearSelection(true); + break; + case ST.COLUMN_PREVIOUS: + doCursorPrevious(); + clearSelection(true); + break; + case ST.COLUMN_NEXT: + doCursorNext(); + clearSelection(true); + break; + case ST.PAGE_UP: + doPageUp(false, -1); + clearSelection(true); + break; + case ST.PAGE_DOWN: + doPageDown(false, -1); + clearSelection(true); + break; + case ST.WORD_PREVIOUS: + doWordPrevious(); + clearSelection(true); + break; + case ST.WORD_NEXT: + doWordNext(); + clearSelection(true); + break; + case ST.TEXT_START: + doContentStart(); + clearSelection(true); + break; + case ST.TEXT_END: + doContentEnd(); + clearSelection(true); + break; + case ST.WINDOW_START: + doPageStart(); + clearSelection(true); + break; + case ST.WINDOW_END: + doPageEnd(); + clearSelection(true); + break; + // Selection + case ST.SELECT_LINE_UP: + doSelectionLineUp(); + break; + case ST.SELECT_ALL: + selectAll(); + break; + case ST.SELECT_LINE_DOWN: + doSelectionLineDown(); + break; + case ST.SELECT_LINE_START: + doLineStart(); + doSelection(ST.COLUMN_PREVIOUS); + break; + case ST.SELECT_LINE_END: + doLineEnd(); + doSelection(ST.COLUMN_NEXT); + break; + case ST.SELECT_COLUMN_PREVIOUS: + doSelectionCursorPrevious(); + doSelection(ST.COLUMN_PREVIOUS); + break; + case ST.SELECT_COLUMN_NEXT: + doSelectionCursorNext(); + doSelection(ST.COLUMN_NEXT); + break; + case ST.SELECT_PAGE_UP: + doSelectionPageUp(-1); + break; + case ST.SELECT_PAGE_DOWN: + doSelectionPageDown(-1); + break; + case ST.SELECT_WORD_PREVIOUS: + doSelectionWordPrevious(); + doSelection(ST.COLUMN_PREVIOUS); + break; + case ST.SELECT_WORD_NEXT: + doSelectionWordNext(); + doSelection(ST.COLUMN_NEXT); + break; + case ST.SELECT_TEXT_START: + doContentStart(); + doSelection(ST.COLUMN_PREVIOUS); + break; + case ST.SELECT_TEXT_END: + doContentEnd(); + doSelection(ST.COLUMN_NEXT); + break; + case ST.SELECT_WINDOW_START: + doPageStart(); + doSelection(ST.COLUMN_PREVIOUS); + break; + case ST.SELECT_WINDOW_END: + doPageEnd(); + doSelection(ST.COLUMN_NEXT); + break; + // Modification + case ST.CUT: + cut(); + break; + case ST.COPY: + copy(); + break; + case ST.PASTE: + paste(); + break; + case ST.DELETE_PREVIOUS: + doBackspace(); + break; + case ST.DELETE_NEXT: + doDelete(); + break; + case ST.DELETE_WORD_PREVIOUS: + doDeleteWordPrevious(); + break; + case ST.DELETE_WORD_NEXT: + doDeleteWordNext(); + break; + // Miscellaneous + case ST.TOGGLE_OVERWRITE: + overwrite = !overwrite; // toggle insert/overwrite mode + break; + } +} +/** + * Temporary until SWT provides this + */ +boolean isBidi() { + return IS_GTK || BidiUtil.isBidiPlatform() || isMirrored; +} +boolean isBidiCaret() { + return BidiUtil.isBidiPlatform(); +} +boolean isFixedLineHeight() { + return fixedLineHeight; +} +/** + * Returns whether the given offset is inside a multi byte line delimiter. + * Example: + * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true + * + * @return true if the given offset is inside a multi byte line delimiter. + * false if the given offset is before or after a line delimiter. + */ +boolean isLineDelimiter(int offset) { + int line = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = offset - lineOffset; + // offsetInLine will be greater than line length if the line + // delimiter is longer than one character and the offset is set + // in between parts of the line delimiter. + return offsetInLine > content.getLine(line).length(); +} +/** + * Returns whether the widget is mirrored (right oriented/right to left + * writing order). + * + * @return isMirrored true=the widget is right oriented, false=the widget + * is left oriented + */ +boolean isMirrored() { + return isMirrored; +} +/** + * Returns whether the widget can have only one line. + * + * @return true if widget can have only one line, false if widget can have + * multiple lines + */ +boolean isSingleLine() { + return (getStyle() & SWT.SINGLE) != 0; +} +/** + * Sends the specified verify event, replace/insert text as defined by + * the event and send a modify event. + * + * @param event the text change event. + *
      + *
    • event.start - the replace start offset
    • + *
    • event.end - the replace end offset
    • + *
    • event.text - the new text
    • + *
    + * @param updateCaret whether or not he caret should be set behind + * the new text + */ +void modifyContent(Event event, boolean updateCaret) { + event.doit = true; + notifyListeners(SWT.Verify, event); + if (event.doit) { + StyledTextEvent styledTextEvent = null; + int replacedLength = event.end - event.start; + if (isListening(ExtendedModify)) { + styledTextEvent = new StyledTextEvent(content); + styledTextEvent.start = event.start; + styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.text = content.getTextRange(event.start, replacedLength); + } + if (updateCaret) { + //Fix advancing flag for delete/backspace key on direction boundary + if (event.text.length() == 0) { + int lineIndex = content.getLineAtOffset(event.start); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + int levelStart = layout.getLevel(event.start - lineOffset); + int lineIndexEnd = content.getLineAtOffset(event.end); + if (lineIndex != lineIndexEnd) { + renderer.disposeTextLayout(layout); + lineOffset = content.getOffsetAtLine(lineIndexEnd); + layout = renderer.getTextLayout(lineIndexEnd); + } + int levelEnd = layout.getLevel(event.end - lineOffset); + renderer.disposeTextLayout(layout); + if (levelStart != levelEnd) { + caretAlignment = PREVIOUS_OFFSET_TRAILING; + } else { + caretAlignment = OFFSET_LEADING; + } + } + } + content.replaceTextRange(event.start, replacedLength, event.text); + // set the caret position prior to sending the modify event. + // fixes 1GBB8NJ + if (updateCaret) { + // always update the caret location. fixes 1G8FODP + setSelection(event.start + event.text.length(), 0, true); + showCaret(); + } + sendModifyEvent(event); + if (isListening(ExtendedModify)) { + notifyListeners(ExtendedModify, styledTextEvent); + } + } +} +void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) { + if (isListening(PaintObject)) { + StyledTextEvent event = new StyledTextEvent (content) ; + event.gc = gc; + event.x = x; + event.y = y; + event.ascent = ascent; + event.descent = descent; + event.style = style; + event.bullet = bullet; + event.bulletIndex = bulletIndex; + notifyListeners(PaintObject, event); + } +} +/** + * Replaces the selection with the text on the DND.CLIPBOARD + * clipboard or, if there is no selection, inserts the text at the current + * caret offset. If the widget has the SWT.SINGLE style and the + * clipboard text contains more than one line, only the first line without + * line delimiters is inserted in the widget. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void paste(){ + checkWidget(); + String text = (String) getClipboardContent(DND.CLIPBOARD); + if (text != null && text.length() > 0) { + Event event = new Event(); + event.start = selection.x; + event.end = selection.y; + event.text = getModelDelimitedText(text); + sendKeyEvent(event); + } +} +/** + * Prints the widget's text to the default printer. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void print() { + checkWidget(); + Printer printer = new Printer(); + StyledTextPrintOptions options = new StyledTextPrintOptions(); + options.printTextForeground = true; + options.printTextBackground = true; + options.printTextFontStyle = true; + options.printLineBackground = true; + new Printing(this, printer, options).run(); + printer.dispose(); +} +/** + * Returns a runnable that will print the widget's text + * to the specified printer. + *

    + * The runnable may be run in a non-UI thread. + *

    + * + * @param printer the printer to print to + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when printer is null
    • + *
    + */ +public Runnable print(Printer printer) { + checkWidget(); + if (printer == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + StyledTextPrintOptions options = new StyledTextPrintOptions(); + options.printTextForeground = true; + options.printTextBackground = true; + options.printTextFontStyle = true; + options.printLineBackground = true; + return print(printer, options); +} +/** + * Returns a runnable that will print the widget's text + * to the specified printer. + *

    + * The runnable may be run in a non-UI thread. + *

    + * + * @param printer the printer to print to + * @param options print options to use during printing + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when printer or options is null
    • + *
    + * @since 2.1 + */ +public Runnable print(Printer printer, StyledTextPrintOptions options) { + checkWidget(); + if (printer == null || options == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + return new Printing(this, printer, options); +} +/** + * Causes the entire bounds of the receiver to be marked + * as needing to be redrawn. The next time a paint request + * is processed, the control will be completely painted. + *

    + * Recalculates the content width for all lines in the bounds. + * When a LineStyleListener is used a redraw call + * is the only notification to the widget that styles have changed + * and that the content width may have changed. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Control#update + */ +public void redraw() { + super.redraw(); + int itemCount = getPartialBottomIndex() - topIndex + 1; + renderer.reset(topIndex, itemCount); + renderer.calculate(topIndex, itemCount); + setScrollBars(false); +} +/** + * Causes the rectangular area of the receiver specified by + * the arguments to be marked as needing to be redrawn. + * The next time a paint request is processed, that area of + * the receiver will be painted. If the all flag + * is true, any children of the receiver which + * intersect with the specified area will also paint their + * intersecting areas. If the all flag is + * false, the children will not be painted. + *

    + * Marks the content width of all lines in the specified rectangle + * as unknown. Recalculates the content width of all visible lines. + * When a LineStyleListener is used a redraw call + * is the only notification to the widget that styles have changed + * and that the content width may have changed. + *

    + * + * @param x the x coordinate of the area to draw + * @param y the y coordinate of the area to draw + * @param width the width of the area to draw + * @param height the height of the area to draw + * @param all true if children should redraw, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Control#update + */ +public void redraw(int x, int y, int width, int height, boolean all) { + super.redraw(x, y, width, height, all); + if (height > 0) { + int firstLine = getLineIndex(y); + int lastLine = getLineIndex(y + height); + resetCache(firstLine, lastLine - firstLine + 1); + } +} +void redrawLines(int startLine, int lineCount) { + // do nothing if redraw range is completely invisible + int partialBottomIndex = getPartialBottomIndex(); + if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { + return; + } + // only redraw visible lines + if (startLine < topIndex) { + lineCount -= topIndex - startLine; + startLine = topIndex; + } + if (startLine + lineCount - 1 > partialBottomIndex) { + lineCount = partialBottomIndex - startLine + 1; + } + startLine -= topIndex; + int redrawTop = getLinePixel(startLine); + int redrawBottom = getLinePixel(startLine + lineCount); + int redrawWidth = clientAreaWidth - leftMargin - rightMargin; + super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); +} +void redrawLinesBullet (int[] redrawLines) { + if (redrawLines == null) return; + int topIndex = getPartialTopIndex(); + int bottomIndex = getPartialBottomIndex(); + for (int i = 0; i < redrawLines.length; i++) { + int lineIndex = redrawLines[i]; + if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue; + int width = -1; + Bullet bullet = renderer.getLineBullet(lineIndex, null); + if (bullet != null) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + width = metrics.width; + } + if (width == -1) width = getClientArea().width; + int height = renderer.getLineHeight(lineIndex); + int y = getLinePixel(lineIndex); + super.redraw(0, y, width, height, false); + } +} +/** + * Redraws the specified text range. + * + * @param start offset of the first character to redraw + * @param length number of characters to redraw + * @param clearBackground true if the background should be cleared as + * part of the redraw operation. If true, the entire redraw range will + * be cleared before anything is redrawn. If the redraw range includes + * the last character of a line (i.e., the entire line is redrawn) the + * line is cleared all the way to the right border of the widget. + * The redraw operation will be faster and smoother if clearBackground + * is set to false. Whether or not the flag can be set to false depends + * on the type of change that has taken place. If font styles or + * background colors for the redraw range have changed, clearBackground + * should be set to true. If only foreground colors have changed for + * the redraw range, clearBackground can be set to false. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
    • + *
    + */ +public void redrawRange(int start, int length, boolean clearBackground) { + checkWidget(); + int end = start + length; + int contentLength = content.getCharCount(); + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + int firstLine = content.getLineAtOffset(start); + int lastLine = content.getLineAtOffset(end); + resetCache(firstLine, lastLine - firstLine + 1); + internalRedrawRange(start, length); +} +/** + * Removes the specified bidirectional segment listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + * @since 2.0 + */ +public void removeBidiSegmentListener(BidiSegmentListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(LineGetSegments, listener); +} +/** + * Removes the specified extended modify listener. + * + * @param extendedModifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { + checkWidget(); + if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(ExtendedModify, extendedModifyListener); +} +/** + * Removes the specified line background listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeLineBackgroundListener(LineBackgroundListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(LineGetBackground, listener); +} +/** + * Removes the specified line style listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeLineStyleListener(LineStyleListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(LineGetStyle, listener); +} +/** + * Removes the specified modify listener. + * + * @param modifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeModifyListener(ModifyListener modifyListener) { + checkWidget(); + if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(SWT.Modify, modifyListener); +} +/** + * Removes the specified listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + * @since 3.2 + */ +public void removePaintObjectListener(PaintObjectListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(PaintObject, listener); +} +/** + * Removes the specified selection listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(SWT.Selection, listener); +} +/** + * Removes the specified verify listener. + * + * @param verifyListener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeVerifyListener(VerifyListener verifyListener) { + checkWidget(); + if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(SWT.Verify, verifyListener); +} +/** + * Removes the specified key verify listener. + * + * @param listener the listener + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeVerifyKeyListener(VerifyKeyListener listener) { + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(VerifyKey, listener); +} +/** + * Replaces the styles in the given range with new styles. This method + * effectively deletes the styles in the given range and then adds the + * the new styles. + *

    + * Note: Because a StyleRange includes the start and length, the + * same instance cannot occur multiple times in the array of styles. + * If the same style attributes, such as font and color, occur in + * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[]) + * can be used to share styles and reduce memory usage. + *

    + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param start offset of first character where styles will be deleted + * @param length length of the range to delete styles in + * @param ranges StyleRange objects containing the new style information. + * The ranges should not overlap and should be within the specified start + * and length. The style rendering is undefined if the ranges do overlap + * or are ill-defined. Must not be null. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • + *
    • ERROR_NULL_ARGUMENT when ranges is null
    • + *
    + * + * @since 2.0 + * + * @see #setStyleRanges(int, int, int[], StyleRange[]) + */ +public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + setStyleRanges(start, length, null, ranges, false); +} +/** + * Replaces the given text range with new text. + * If the widget has the SWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text + * that was set. Note that only a single line of text should be set when + * the SWT.SINGLE style is used. + *

    + * NOTE: During the replace operation the current selection is + * changed as follows: + *

      + *
    • selection before replaced text: selection unchanged + *
    • selection after replaced text: adjust the selection so that same text + * remains selected + *
    • selection intersects replaced text: selection is cleared and caret + * is placed after inserted text + *
    + *

    + * + * @param start offset of first character to replace + * @param length number of characters to replace. Use 0 to insert text + * @param text new text. May be empty to delete text. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
    • + *
    • ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. + * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
    • + *
    • ERROR_NULL_ARGUMENT when string is null
    • + *
    + */ +public void replaceTextRange(int start, int length, String text) { + checkWidget(); + if (text == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + int contentLength = getCharCount(); + int end = start + length; + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + Event event = new Event(); + event.start = start; + event.end = end; + event.text = text; + modifyContent(event, false); +} +/** + * Resets the caret position, selection and scroll offsets. Recalculate + * the content width and scroll bars. Redraw the widget. + */ +void reset() { + ScrollBar verticalBar = getVerticalBar(); + ScrollBar horizontalBar = getHorizontalBar(); + caretOffset = 0; + topIndex = 0; + topIndexY = 0; + verticalScrollOffset = 0; + horizontalScrollOffset = 0; + resetSelection(); + renderer.setContent(content); + if (verticalBar != null) { + verticalBar.setSelection(0); + } + if (horizontalBar != null) { + horizontalBar.setSelection(0); + } + resetCache(0, 0); + setCaretLocation(); + super.redraw(); +} +void resetCache(int firstLine, int count) { + renderer.reset(firstLine, count); + renderer.calculateClientArea(); + setScrollBars(true); + if (!isFixedLineHeight()) { + if (topIndex > firstLine) { + verticalScrollOffset = -1; + } + renderer.calculateIdle(); + } +} +/** + * Resets the selection. + */ +void resetSelection() { + selection.x = selection.y = caretOffset; + selectionAnchor = -1; +} + +public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) { + super.scroll(destX, destY, x, y, width, height, false); + if (all) { + int deltaX = destX - x, deltaY = destY - y; + Control[] children = getChildren(); + for (int i=0; i 0 = scroll left, + * < 0 scroll right + * @param adjustScrollBar + * true= the scroll thumb will be moved to reflect the new scroll offset. + * false = the scroll thumb will not be moved + * @return + * true=the widget was scrolled + * false=the widget was not scrolled, the given offset is not valid. + */ +boolean scrollHorizontal(int pixels, boolean adjustScrollBar) { + if (pixels == 0) { + return false; + } + ScrollBar horizontalBar = getHorizontalBar(); + if (horizontalBar != null && adjustScrollBar) { + horizontalBar.setSelection(horizontalScrollOffset + pixels); + } + int scrollHeight = clientAreaHeight - topMargin - bottomMargin; + if (pixels > 0) { + int sourceX = leftMargin + pixels; + int scrollWidth = clientAreaWidth - sourceX - rightMargin; + if (scrollWidth > 0) { + scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true); + } + if (sourceX > scrollWidth) { + super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true); + } + } else { + int destinationX = leftMargin - pixels; + int scrollWidth = clientAreaWidth - destinationX - rightMargin; + if (scrollWidth > 0) { + scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true); + } + if (destinationX > scrollWidth) { + super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true); + } + } + horizontalScrollOffset += pixels; + int oldColumnX = columnX; + setCaretLocation(); + columnX = oldColumnX; + return true; +} +/** + * Scrolls the widget vertically. + * + * @param pixel the new vertical scroll offset + * @param adjustScrollBar + * true= the scroll thumb will be moved to reflect the new scroll offset. + * false = the scroll thumb will not be moved + * @return + * true=the widget was scrolled + * false=the widget was not scrolled + */ +boolean scrollVertical(int pixels, boolean adjustScrollBar) { + if (pixels == 0) { + return false; + } + if (verticalScrollOffset != -1) { + ScrollBar verticalBar = getVerticalBar(); + if (verticalBar != null && adjustScrollBar) { + verticalBar.setSelection(verticalScrollOffset + pixels); + } + int scrollWidth = clientAreaWidth - leftMargin - rightMargin; + if (pixels > 0) { + int sourceY = topMargin + pixels; + int scrollHeight = clientAreaHeight - sourceY - bottomMargin; + if (scrollHeight > 0) { + scroll(leftMargin, topMargin, leftMargin, sourceY, scrollWidth, scrollHeight, true); + } + if (sourceY > scrollHeight) { + int redrawY = Math.max(0, topMargin + scrollHeight); + int redrawHeight = Math.min(clientAreaHeight, pixels - scrollHeight); + super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true); + } + } else { + int destinationY = topMargin - pixels; + int scrollHeight = clientAreaHeight - destinationY - bottomMargin; + if (scrollHeight > 0) { + scroll(leftMargin, destinationY, leftMargin, topMargin, scrollWidth, scrollHeight, true); + } + if (destinationY > scrollHeight) { + int redrawY = Math.max(0, topMargin + scrollHeight); + int redrawHeight = Math.min(clientAreaHeight, -pixels - scrollHeight); + super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true); + } + } + verticalScrollOffset += pixels; + calculateTopIndex(pixels); + } else { + calculateTopIndex(pixels); + super.redraw(); + } + int oldColumnX = columnX; + setCaretLocation(); + columnX = oldColumnX; + return true; +} +void scrollText(int srcY, int destY) { + if (srcY == destY) return; + int deltaY = destY - srcY; + int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight; + if (deltaY > 0) { + scrollHeight = clientAreaHeight - srcY - bottomMargin; + } else { + scrollHeight = clientAreaHeight - destY - bottomMargin; + } + scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true); + if ((0 < srcY + scrollHeight) && (topMargin > srcY)) { + super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false); + } + if ((0 < destY + scrollHeight) && (topMargin > destY)) { + super.redraw(leftMargin, 0, scrollWidth, topMargin, false); + } + if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) { + super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false); + } + if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) { + super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); + } +} +/** + * Selects all the text. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void selectAll() { + checkWidget(); + setSelection(0, Math.max(getCharCount(),0)); +} +/** + * Replaces/inserts text as defined by the event. + * + * @param event the text change event. + *
      + *
    • event.start - the replace start offset
    • + *
    • event.end - the replace end offset
    • + *
    • event.text - the new text
    • + *
    + */ +void sendKeyEvent(Event event) { + if (editable) { + modifyContent(event, true); + } +} +/** + * Returns a StyledTextEvent that can be used to request data such + * as styles and background color for a line. + *

    + * The specified line may be a visual (wrapped) line if in word + * wrap mode. The returned object will always be for a logical + * (unwrapped) line. + *

    + * + * @param lineOffset offset of the line. This may be the offset of + * a visual line if the widget is in word wrap mode. + * @param line line text. This may be the text of a visualline if + * the widget is in word wrap mode. + * @return StyledTextEvent that can be used to request line data + * for the given line. + */ +StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { + StyledTextEvent event = null; + if (isListening(eventType)) { + event = new StyledTextEvent(content); + event.detail = lineOffset; + event.text = line; + event.alignment = alignment; + event.indent = indent; + event.justify = justify; + notifyListeners(eventType, event); + } + return event; +} +void sendModifyEvent(Event event) { + Accessible accessible = getAccessible(); + if (event.text.length() == 0) { + accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); + } else { + if (event.start == event.end) { + accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length()); + } else { + accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); + accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length()); + } + } + notifyListeners(SWT.Modify, event); +} +/** + * Sends the specified selection event. + */ +void sendSelectionEvent() { + getAccessible().textSelectionChanged(); + Event event = new Event(); + event.x = selection.x; + event.y = selection.y; + notifyListeners(SWT.Selection, event); +} +/** + * Sets the alignment of the widget. The argument should be one of SWT.LEFT, + * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines. + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setLineAlignment(int, int, int) + * + * @since 3.2 + */ +public void setAlignment(int alignment) { + checkWidget(); + alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if (alignment == 0 || this.alignment == alignment) return; + this.alignment = alignment; + resetCache(0, content.getLineCount()); + setCaretLocation(); + super.redraw(); +} +/** + * @see org.eclipse.swt.widgets.Control#setBackground + */ +public void setBackground(Color color) { + checkWidget(); + background = color; + super.redraw(); +} +/** + * Sets the receiver's caret. Set the caret's height and location. + * + *

    + * @param caret the new caret for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setCaret(Caret caret) { + checkWidget (); + super.setCaret(caret); + caretDirection = SWT.NULL; + if (caret != null) { + setCaretLocation(); + } +} +/** + * Sets the BIDI coloring mode. When true the BIDI text display + * algorithm is applied to segments of text that are the same + * color. + * + * @param mode the new coloring mode + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @deprecated use BidiSegmentListener instead. + */ +public void setBidiColoring(boolean mode) { + checkWidget(); + bidiColoring = mode; +} +/** + * Moves the Caret to the current caret offset. + */ +void setCaretLocation() { + Point newCaretPos = getPointAtOffset(caretOffset); + setCaretLocation(newCaretPos, getCaretDirection()); +} +void setCaretLocation(Point location, int direction) { + Caret caret = getCaret(); + if (caret != null) { + boolean isDefaultCaret = caret == defaultCaret; + int lineHeight = renderer.getLineHeight(); + int caretHeight = lineHeight; + if (!isFixedLineHeight() && isDefaultCaret) { + caretHeight = getBoundsAtOffset(caretOffset).height; + if (caretHeight != lineHeight) { + direction = SWT.DEFAULT; + } + } + int imageDirection = direction; + if (isMirrored()) { + if (imageDirection == SWT.LEFT) { + imageDirection = SWT.RIGHT; + } else if (imageDirection == SWT.RIGHT) { + imageDirection = SWT.LEFT; + } + } + if (isDefaultCaret && imageDirection == SWT.RIGHT) { + location.x -= (caret.getSize().x - 1); + } + if (isDefaultCaret) { + caret.setBounds(location.x, location.y, 0, caretHeight); + } else { + caret.setLocation(location); + } + getAccessible().textCaretMoved(getCaretOffset()); + if (direction != caretDirection) { + caretDirection = direction; + if (isDefaultCaret) { + if (imageDirection == SWT.DEFAULT) { + defaultCaret.setImage(null); + } else if (imageDirection == SWT.LEFT) { + defaultCaret.setImage(leftCaretBitmap); + } else if (imageDirection == SWT.RIGHT) { + defaultCaret.setImage(rightCaretBitmap); + } + } + if (caretDirection == SWT.LEFT) { + BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI); + } else if (caretDirection == SWT.RIGHT) { + BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI); + } + } + } + columnX = location.x; +} +/** + * Sets the caret offset. + * + * @param offset caret offset, relative to the first character in the text. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) + *
    + */ +public void setCaretOffset(int offset) { + checkWidget(); + int length = getCharCount(); + if (length > 0 && offset != caretOffset) { + if (offset < 0) { + caretOffset = 0; + } else if (offset > length) { + caretOffset = length; + } else { + if (isLineDelimiter(offset)) { + // offset is inside a multi byte line delimiter. This is an + // illegal operation and an exception is thrown. Fixes 1GDKK3R + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + caretOffset = offset; + } + // clear the selection if the caret is moved. + // don't notify listeners about the selection change. + clearSelection(false); + } + setCaretLocation(); +} +/** + * Copies the specified text range to the clipboard. The text will be placed + * in the clipboard in plain text format and RTF format. + * + * @param start start index of the text + * @param length length of text to place in clipboard + * + * @exception SWTError, see Clipboard.setContents + * @see org.eclipse.swt.dnd.Clipboard#setContents + */ +void setClipboardContent(int start, int length, int clipboardType) throws SWTError { + if (clipboardType == DND.SELECTION_CLIPBOARD && !(IS_MOTIF || IS_GTK)) return; + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + TextWriter plainTextWriter = new TextWriter(start, length); + String plainText = getPlatformDelimitedText(plainTextWriter); + Object[] data; + Transfer[] types; + if (clipboardType == DND.SELECTION_CLIPBOARD) { + data = new Object[]{plainText}; + types = new Transfer[]{plainTextTransfer}; + } else { + RTFTransfer rtfTransfer = RTFTransfer.getInstance(); + RTFWriter rtfWriter = new RTFWriter(start, length); + String rtfText = getPlatformDelimitedText(rtfWriter); + data = new Object[]{rtfText, plainText}; + types = new Transfer[]{rtfTransfer, plainTextTransfer}; + } + clipboard.setContents(data, types, clipboardType); +} +/** + * Sets the content implementation to use for text storage. + * + * @param newContent StyledTextContent implementation to use for text storage. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void setContent(StyledTextContent newContent) { + checkWidget(); + if (newContent == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + if (content != null) { + content.removeTextChangeListener(textChangeListener); + } + content = newContent; + content.addTextChangeListener(textChangeListener); + reset(); +} +/** + * Sets the receiver's cursor to the cursor specified by the + * argument. Overridden to handle the null case since the + * StyledText widget uses an ibeam as its default cursor. + * + * @see org.eclipse.swt.widgets.Control#setCursor + */ +public void setCursor (Cursor cursor) { + if (cursor == null) { + Display display = getDisplay(); + super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM)); + } else { + super.setCursor(cursor); + } +} +/** + * Sets whether the widget implements double click mouse behavior. + *

    + * + * @param enable if true double clicking a word selects the word, if false + * double clicks have the same effect as regular mouse clicks. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDoubleClickEnabled(boolean enable) { + checkWidget(); + doubleClickEnabled = enable; +} +/** + * Sets whether the widget content can be edited. + *

    + * + * @param editable if true content can be edited, if false content can not be + * edited + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEditable(boolean editable) { + checkWidget(); + this.editable = editable; +} +/** + * Sets a new font to render text with. + *

    + * NOTE: Italic fonts are not supported unless they have no overhang + * and the same baseline as regular fonts. + *

    + * + * @param font new font + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setFont(Font font) { + checkWidget(); + int oldLineHeight = renderer.getLineHeight(); + super.setFont(font); + renderer.setFont(getFont(), tabLength); + // keep the same top line visible. fixes 5815 + if (isFixedLineHeight()) { + int lineHeight = renderer.getLineHeight(); + if (lineHeight != oldLineHeight) { + int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset(); + scrollVertical(vscroll, true); + } + } + resetCache(0, content.getLineCount()); + claimBottomFreeSpace(); + calculateScrollBars(); + if (isBidiCaret()) createCaretBitmaps(); + caretDirection = SWT.NULL; + setCaretLocation(); + super.redraw(); +} +/** + * @see org.eclipse.swt.widgets.Control#setForeground + */ +public void setForeground(Color color) { + checkWidget(); + foreground = color; + super.setForeground(getForeground()); + super.redraw(); +} +/** + * Sets the horizontal scroll offset relative to the start of the line. + * Do nothing if there is no text set. + *

    + * NOTE: The horizontal index is reset to 0 when new text is set in the + * widget. + *

    + * + * @param offset horizontal scroll offset relative to the start + * of the line, measured in character increments starting at 0, if + * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setHorizontalIndex(int offset) { + checkWidget(); + if (getCharCount() == 0) { + return; + } + if (offset < 0) { + offset = 0; + } + offset *= getHorizontalIncrement(); + // allow any value if client area width is unknown or 0. + // offset will be checked in resize handler. + // don't use isVisible since width is known even if widget + // is temporarily invisible + if (clientAreaWidth > 0) { + int width = renderer.getWidth(); + // prevent scrolling if the content fits in the client area. + // align end of longest line with right border of client area + // if offset is out of range. + if (offset > width - clientAreaWidth) { + offset = Math.max(0, width - clientAreaWidth); + } + } + scrollHorizontal(offset - horizontalScrollOffset, true); +} +/** + * Sets the horizontal pixel offset relative to the start of the line. + * Do nothing if there is no text set. + *

    + * NOTE: The horizontal pixel offset is reset to 0 when new text + * is set in the widget. + *

    + * + * @param pixel horizontal pixel offset relative to the start + * of the line. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.0 + */ +public void setHorizontalPixel(int pixel) { + checkWidget(); + if (getCharCount() == 0) { + return; + } + if (pixel < 0) { + pixel = 0; + } + // allow any value if client area width is unknown or 0. + // offset will be checked in resize handler. + // don't use isVisible since width is known even if widget + // is temporarily invisible + if (clientAreaWidth > 0) { + int width = renderer.getWidth(); + // prevent scrolling if the content fits in the client area. + // align end of longest line with right border of client area + // if offset is out of range. + if (pixel > width - clientAreaWidth) { + pixel = Math.max(0, width - clientAreaWidth); + } + } + scrollHorizontal(pixel - horizontalScrollOffset, true); +} +/** + * Sets the line indentation of the widget. + *

    + * It is the amount of blank space, in pixels, at the beginning of each line. + * When a line wraps in several lines only the first one is indented. + *

    + * + * @param indent the new indent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setLineIndent(int, int, int) + * + * @since 3.2 + */ +public void setIndent(int indent) { + checkWidget(); + if (this.indent == indent || indent < 0) return; + this.indent = indent; + resetCache(0, content.getLineCount()); + setCaretLocation(); + super.redraw(); +} +/** + * Sets whether the widget should justify lines. + * + * @param justify whether lines should be justified + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setLineJustify(int, int, boolean) + * + * @since 3.2 + */ +public void setJustify(boolean justify) { + checkWidget(); + if (this.justify == justify) return; + this.justify = justify; + resetCache(0, content.getLineCount()); + setCaretLocation(); + super.redraw(); +} +/** + * Maps a key to an action. + *

    + * One action can be associated with N keys. However, each key can only + * have one action (key:action is N:1 relation). + *

    + * + * @param key a key code defined in SWT.java or a character. + * Optionally ORd with a state mask. Preferred state masks are one or more of + * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform + * differences. However, there may be cases where using the specific state masks + * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. + * @param action one of the predefined actions defined in ST.java. + * Use SWT.NULL to remove a key binding. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setKeyBinding(int key, int action) { + checkWidget(); + int modifierValue = key & SWT.MODIFIER_MASK; + char keyChar = (char)(key & SWT.KEY_MASK); + if (Compatibility.isLetter(keyChar)) { + // make the keybinding case insensitive by adding it + // in its upper and lower case form + char ch = Character.toUpperCase(keyChar); + int newKey = ch | modifierValue; + if (action == SWT.NULL) { + keyActionMap.remove(new Integer(newKey)); + } else { + keyActionMap.put(new Integer(newKey), new Integer(action)); + } + ch = Character.toLowerCase(keyChar); + newKey = ch | modifierValue; + if (action == SWT.NULL) { + keyActionMap.remove(new Integer(newKey)); + } else { + keyActionMap.put(new Integer(newKey), new Integer(action)); + } + } else { + if (action == SWT.NULL) { + keyActionMap.remove(new Integer(key)); + } else { + keyActionMap.put(new Integer(key), new Integer(action)); + } + } +} +/** + * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT, + * SWT.CENTER or SWT.RIGHT. + *

    + * Should not be called if a LineStyleListener has been set since the listener + * maintains the line attributes. + *

    + * All line attributes are maintained relative to the line text, not the + * line index that is specified in this method call. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. + *

    + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + * + * @param startLine first line the alignment is applied to, 0 based + * @param lineCount number of lines the alignment applies to. + * @param alignment line alignment + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • + *
    + * @see #setAlignment(int) + * @since 3.2 + */ +public void setLineAlignment(int startLine, int lineCount, int alignment) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (startLine < 0 || startLine + lineCount > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + renderer.setLineAlignment(startLine, lineCount, alignment); + resetCache(startLine, lineCount); + redrawLines(startLine, lineCount); + int caretLine = getCaretLine(); + if (startLine <= caretLine && caretLine < startLine + lineCount) { + setCaretLocation(); + } +} +/** + * Sets the background color of the specified lines. + *

    + * The background color is drawn for the width of the widget. All + * line background colors are discarded when setText is called. + * The text background color if defined in a StyleRange overlays the + * line background color. + *

    + * Should not be called if a LineBackgroundListener has been set since the + * listener maintains the line backgrounds. + *

    + * All line attributes are maintained relative to the line text, not the + * line index that is specified in this method call. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. + *

    + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + *

    + * + * @param startLine first line the color is applied to, 0 based + * @param lineCount number of lines the color applies to. + * @param background line background color + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • + *
    + */ +public void setLineBackground(int startLine, int lineCount, Color background) { + checkWidget(); + if (isListening(LineGetBackground)) return; + if (startLine < 0 || startLine + lineCount > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (background != null) { + renderer.setLineBackground(startLine, lineCount, background); + } else { + renderer.clearLineBackground(startLine, lineCount); + } + redrawLines(startLine, lineCount); +} +/** + * Sets the bullet of the specified lines. + *

    + * Should not be called if a LineStyleListener has been set since the listener + * maintains the line attributes. + *

    + * All line attributes are maintained relative to the line text, not the + * line index that is specified in this method call. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. + *

    + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + *

    + * + * @param startLine first line the bullet is applied to, 0 based + * @param lineCount number of lines the bullet applies to. + * @param bullet line bullet + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • + *
    + * @since 3.2 + */ +public void setLineBullet(int startLine, int lineCount, Bullet bullet) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (startLine < 0 || startLine + lineCount > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + renderer.setLineBullet(startLine, lineCount, bullet); + resetCache(startLine, lineCount); + redrawLines(startLine, lineCount); + int caretLine = getCaretLine(); + if (startLine <= caretLine && caretLine < startLine + lineCount) { + setCaretLocation(); + } +} +void setVariableLineHeight () { + if (!fixedLineHeight) return; + fixedLineHeight = false; + renderer.calculateIdle(); +} +/** + * Sets the indent of the specified lines. + *

    + * Should not be called if a LineStyleListener has been set since the listener + * maintains the line attributes. + *

    + * All line attributes are maintained relative to the line text, not the + * line index that is specified in this method call. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. + *

    + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + *

    + * + * @param startLine first line the indent is applied to, 0 based + * @param lineCount number of lines the indent applies to. + * @param indent line indent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • + *
    + * @see #setIndent(int) + * @since 3.2 + */ +public void setLineIndent(int startLine, int lineCount, int indent) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (startLine < 0 || startLine + lineCount > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + renderer.setLineIndent(startLine, lineCount, indent); + resetCache(startLine, lineCount); + redrawLines(startLine, lineCount); + int caretLine = getCaretLine(); + if (startLine <= caretLine && caretLine < startLine + lineCount) { + setCaretLocation(); + } +} +/** + * Sets the justify of the specified lines. + *

    + * Should not be called if a LineStyleListener has been set since the listener + * maintains the line attributes. + *

    + * All line attributes are maintained relative to the line text, not the + * line index that is specified in this method call. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. + *

    + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + *

    + * + * @param startLine first line the justify is applied to, 0 based + * @param lineCount number of lines the justify applies to. + * @param justify true if lines should be justified + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when the specified line range is invalid
    • + *
    + * @see #setJustify(boolean) + * @since 3.2 + */ +public void setLineJustify(int startLine, int lineCount, boolean justify) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (startLine < 0 || startLine + lineCount > content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + renderer.setLineJustify(startLine, lineCount, justify); + resetCache(startLine, lineCount); + redrawLines(startLine, lineCount); + int caretLine = getCaretLine(); + if (startLine <= caretLine && caretLine < startLine + lineCount) { + setCaretLocation(); + } +} +/** + * Sets the line spacing of the widget. The line spacing applies for all lines. + * + * @param lineSpacing the line spacing + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 3.2 + */ +public void setLineSpacing(int lineSpacing) { + checkWidget(); + if (this.lineSpacing == lineSpacing || lineSpacing < 0) return; + this.lineSpacing = lineSpacing; + setVariableLineHeight(); + resetCache(0, content.getLineCount()); + setCaretLocation(); + super.redraw(); +} +void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) { + checkWidget(); + this.leftMargin = leftMargin; + this.topMargin = topMargin; + this.rightMargin = rightMargin; + this.bottomMargin = bottomMargin; + setCaretLocation(); +} +/** + * Flips selection anchor based on word selection direction. + */ +void setMouseWordSelectionAnchor() { + if (mouseDoubleClick) { + if (caretOffset < doubleClickSelection.x) { + selectionAnchor = doubleClickSelection.y; + } else if (caretOffset > doubleClickSelection.y) { + selectionAnchor = doubleClickSelection.x; + } + } +} +/** + * Sets the orientation of the receiver, which must be one + * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. + * + * @param orientation new orientation style + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1.2 + */ +public void setOrientation(int orientation) { + if ((orientation & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)) == 0) { + return; + } + if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && (orientation & SWT.LEFT_TO_RIGHT) != 0) { + return; + } + if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && isMirrored()) { + return; + } + if ((orientation & SWT.LEFT_TO_RIGHT) != 0 && !isMirrored()) { + return; + } + if (!BidiUtil.setOrientation(handle, orientation)) { + return; + } + isMirrored = (orientation & SWT.RIGHT_TO_LEFT) != 0; + caretDirection = SWT.NULL; + setCaretLocation(); + keyActionMap.clear(); + createKeyBindings(); + super.redraw(); +} +/** + * Adjusts the maximum and the page size of the scroll bars to + * reflect content width/length changes. + * + * @param vertical indicates if the vertical scrollbar also needs to be set + */ +void setScrollBars(boolean vertical) { + int inactive = 1; + if (vertical || !isFixedLineHeight()) { + ScrollBar verticalBar = getVerticalBar(); + if (verticalBar != null) { + int maximum = renderer.getHeight(); + // only set the real values if the scroll bar can be used + // (ie. because the thumb size is less than the scroll maximum) + // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 + if (clientAreaHeight < maximum) { + verticalBar.setValues( + verticalBar.getSelection(), + verticalBar.getMinimum(), + maximum, + clientAreaHeight, // thumb size + verticalBar.getIncrement(), + clientAreaHeight); // page size + } else if (verticalBar.getThumb() != inactive || verticalBar.getMaximum() != inactive) { + verticalBar.setValues( + verticalBar.getSelection(), + verticalBar.getMinimum(), + inactive, + inactive, + verticalBar.getIncrement(), + inactive); + } + } + } + ScrollBar horizontalBar = getHorizontalBar(); + if (horizontalBar != null && horizontalBar.getVisible()) { + int maximum = renderer.getWidth(); + // only set the real values if the scroll bar can be used + // (ie. because the thumb size is less than the scroll maximum) + // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 + if (clientAreaWidth < maximum) { + horizontalBar.setValues( + horizontalBar.getSelection(), + horizontalBar.getMinimum(), + maximum, + clientAreaWidth - leftMargin - rightMargin, // thumb size + horizontalBar.getIncrement(), + clientAreaWidth - leftMargin - rightMargin); // page size + } else if (horizontalBar.getThumb() != inactive || horizontalBar.getMaximum() != inactive) { + horizontalBar.setValues( + horizontalBar.getSelection(), + horizontalBar.getMinimum(), + inactive, + inactive, + horizontalBar.getIncrement(), + inactive); + } + } +} +/** + * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). + * + * @param start new caret position + * @see #setSelection(int,int) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) + *
    + */ +public void setSelection(int start) { + // checkWidget test done in setSelectionRange + setSelection(start, start); +} +/** + * Sets the selection and scrolls it into view. + *

    + * Indexing is zero based. Text selections are specified in terms of + * caret positions. In a text widget that contains N characters, there are + * N+1 caret positions, ranging from 0..N + *

    + * + * @param point x=selection start offset, y=selection end offset + * The caret will be placed at the selection start when x > y. + * @see #setSelection(int,int) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when point is null
    • + *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) + *
    + */ +public void setSelection(Point point) { + checkWidget(); + if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + setSelection(point.x, point.y); +} +/** + * Sets the receiver's selection background color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.1 + */ +public void setSelectionBackground (Color color) { + checkWidget (); + if (color != null) { + if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + selectionBackground = color; + super.redraw(); +} +/** + * Sets the receiver's selection foreground color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.1 + */ +public void setSelectionForeground (Color color) { + checkWidget (); + if (color != null) { + if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + selectionForeground = color; + super.redraw(); +} +/** + * Sets the selection and scrolls it into view. + *

    + * Indexing is zero based. Text selections are specified in terms of + * caret positions. In a text widget that contains N characters, there are + * N+1 caret positions, ranging from 0..N + *

    + * + * @param start selection start offset. The caret will be placed at the + * selection start when start > end. + * @param end selection end offset + * @see #setSelectionRange(int,int) + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) + *
    + */ +public void setSelection(int start, int end) { + setSelectionRange(start, end - start); + showSelection(); +} +/** + * Sets the selection. + *

    + * The new selection may not be visible. Call showSelection to scroll + * the selection into view. + *

    + * + * @param start offset of the first selected character, start >= 0 must be true. + * @param length number of characters to select, 0 <= start + length + * <= getCharCount() must be true. + * A negative length places the caret at the selection start. + * @param sendEvent a Selection event is sent when set to true and when + * the selection is reset. + */ +void setSelection(int start, int length, boolean sendEvent) { + int end = start + length; + if (start > end) { + int temp = end; + end = start; + start = temp; + } + // is the selection range different or is the selection direction + // different? + if (selection.x != start || selection.y != end || + (length > 0 && selectionAnchor != selection.x) || + (length < 0 && selectionAnchor != selection.y)) { + clearSelection(sendEvent); + if (length < 0) { + selectionAnchor = selection.y = end; + caretOffset = selection.x = start; + } else { + selectionAnchor = selection.x = start; + caretOffset = selection.y = end; + } + internalRedrawRange(selection.x, selection.y - selection.x); + } +} +/** + * Sets the selection. + *

    + * The new selection may not be visible. Call showSelection to scroll the selection + * into view. A negative length places the caret at the visual start of the selection. + *

    + * + * @param start offset of the first selected character + * @param length number of characters to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) + *
    + */ +public void setSelectionRange(int start, int length) { + checkWidget(); + int contentLength = getCharCount(); + start = Math.max(0, Math.min (start, contentLength)); + int end = start + length; + if (end < 0) { + length = -start; + } else { + if (end > contentLength) length = contentLength - start; + } + if (isLineDelimiter(start) || isLineDelimiter(start + length)) { + // the start offset or end offset of the selection range is inside a + // multi byte line delimiter. This is an illegal operation and an exception + // is thrown. Fixes 1GDKK3R + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + setSelection(start, length, false); + setCaretLocation(); +} +/** + * Adds the specified style. + *

    + * The new style overwrites existing styles for the specified range. + * Existing style ranges are adjusted if they partially overlap with + * the new style. To clear an individual style, call setStyleRange + * with a StyleRange that has null attributes. + *

    + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param range StyleRange object containing the style information. + * Overwrites the old style in the given range. May be null to delete + * all styles. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
    • + *
    + */ +public void setStyleRange(StyleRange range) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (range != null) { + if (range.isUnstyled()) { + setStyleRanges(range.start, range.length, null, null, false); + } else { + setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); + } + } else { + setStyleRanges(0, 0, null, null, true); + } +} +/** + * Clears the styles in the range specified by start and + * length and adds the new styles. + *

    + * The ranges array contains start and length pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] with length ranges[n+1] uses the style + * at styles[n/2]. The range fields within each StyleRange are ignored. + * If ranges or styles is null, the specified range is cleared. + *

    + * Note: It is expected that the same instance of a StyleRange will occur + * multiple times within the styles array, reducing memory usage. + *

    + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param start offset of first character where styles will be deleted + * @param length length of the range to delete styles in + * @param ranges the array of ranges. The ranges must not overlap and must be in order. + * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • + *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • + *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • + *
    • ERROR_INVALID_RANGE when a range overlaps
    • + *
    + * + * @since 3.2 + */ +public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (ranges == null || styles == null) { + setStyleRanges(start, length, null, null, false); + } else { + setStyleRanges(start, length, ranges, styles, false); + } +} +/** + * Sets styles to be used for rendering the widget content. + *

    + * All styles in the widget will be replaced with the given set of ranges and styles. + * The ranges array contains start and length pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] with length ranges[n+1] uses the style + * at styles[n/2]. The range fields within each StyleRange are ignored. + * If either argument is null, the styles are cleared. + *

    + * Note: It is expected that the same instance of a StyleRange will occur + * multiple times within the styles array, reducing memory usage. + *

    + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param ranges the array of ranges. The ranges must not overlap and must be in order. + * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when an element in the styles array is null
    • + *
    • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
    • + *
    • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
    • + *
    • ERROR_INVALID_RANGE when a range overlaps
    • + *
    + * + * @since 3.2 + */ +public void setStyleRanges(int[] ranges, StyleRange[] styles) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (ranges == null || styles == null) { + setStyleRanges(0, 0, null, null, true); + } else { + setStyleRanges(0, 0, ranges, styles, true); + } +} +void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) { + int charCount = content.getCharCount(); + int end = start + length; + if (start > end || start < 0) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (styles != null) { + if (end > charCount) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + if (ranges != null) { + if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + int lastOffset = 0; + boolean variableHeight = false; + for (int i = 0; i < styles.length; i ++) { + if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + int rangeStart, rangeLength; + if (ranges != null) { + rangeStart = ranges[i << 1]; + rangeLength = ranges[(i << 1) + 1]; + } else { + rangeStart = styles[i].start; + rangeLength = styles[i].length; + } + if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + variableHeight |= styles[i].isVariableHeight(); + lastOffset = rangeStart + rangeLength; + } + if (variableHeight) setVariableLineHeight(); + } + int rangeStart = start, rangeEnd = end; + if (styles != null && styles.length > 0) { + if (ranges != null) { + rangeStart = ranges[0]; + rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1]; + } else { + rangeStart = styles[0].start; + rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length; + } + } + int lastLineBottom = 0; + if (!isFixedLineHeight() && !reset) { + int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); + int partialTopIndex = getPartialTopIndex(); + int partialBottomIndex = getPartialBottomIndex(); + if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { + lastLineBottom = getLinePixel(lineEnd + 1); + } + } + if (reset) { + renderer.setStyleRanges(null, null); + } else { + renderer.updateRanges(start, length, length); + } + if (styles != null && styles.length > 0) { + renderer.setStyleRanges(ranges, styles); + } + if (reset) { + resetCache(0, content.getLineCount()); + super.redraw(); + } else { + int lineStart = content.getLineAtOffset(Math.min(start, rangeStart)); + int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd)); + resetCache(lineStart, lineEnd - lineStart + 1); + int partialTopIndex = getPartialTopIndex(); + int partialBottomIndex = getPartialBottomIndex(); + if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) { + int y = 0; + int height = clientAreaHeight; + if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) { + int lineTop = Math.max(y, getLinePixel(lineStart)); + y = lineTop; + height -= lineTop; + } + if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) { + int newLastLineBottom = getLinePixel(lineEnd + 1); + if (!isFixedLineHeight()) { + scrollText(lastLineBottom, newLastLineBottom); + } + height = newLastLineBottom - y; + } + super.redraw(0, y, clientAreaWidth, height, false); + } + } + setCaretLocation(); +} +/** + * Sets styles to be used for rendering the widget content. All styles + * in the widget will be replaced with the given set of styles. + *

    + * Note: Because a StyleRange includes the start and length, the + * same instance cannot occur multiple times in the array of styles. + * If the same style attributes, such as font and color, occur in + * multiple StyleRanges, setStyleRanges(int[], StyleRange[]) + * can be used to share styles and reduce memory usage. + *

    + * Should not be called if a LineStyleListener has been set since the + * listener maintains the styles. + *

    + * + * @param ranges StyleRange objects containing the style information. + * The ranges should not overlap. The style rendering is undefined if + * the ranges do overlap. Must not be null. The styles need to be in order. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when the list of ranges is null
    • + *
    • ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
    • + *
    + * + * @see #setStyleRanges(int[], StyleRange[]) + */ +public void setStyleRanges(StyleRange[] ranges) { + checkWidget(); + if (isListening(LineGetStyle)) return; + if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + setStyleRanges(0, 0, null, ranges, true); +} +/** + * Sets the tab width. + * + * @param tabs tab width measured in characters. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTabs(int tabs) { + checkWidget(); + tabLength = tabs; + renderer.setFont(null, tabs); + if (caretOffset > 0) { + caretOffset = 0; + showCaret(); + clearSelection(false); + } + resetCache(0, content.getLineCount()); + super.redraw(); +} +/** + * Sets the widget content. + * If the widget has the SWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text + * that was set. + *

    + * Note: Only a single line of text should be set when the SWT.SINGLE + * style is used. + *

    + * + * @param text new widget content. Replaces existing content. Line styles + * that were set using StyledText API are discarded. The + * current selection is also discarded. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when string is null
    • + *
    + */ +public void setText(String text) { + checkWidget(); + if (text == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + Event event = new Event(); + event.start = 0; + event.end = getCharCount(); + event.text = text; + event.doit = true; + notifyListeners(SWT.Verify, event); + if (event.doit) { + StyledTextEvent styledTextEvent = null; + if (isListening(ExtendedModify)) { + styledTextEvent = new StyledTextEvent(content); + styledTextEvent.start = event.start; + styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); + } + content.setText(event.text); + sendModifyEvent(event); + if (styledTextEvent != null) { + notifyListeners(ExtendedModify, styledTextEvent); + } + } +} +/** + * Sets the text limit to the specified number of characters. + *

    + * The text limit specifies the amount of text that + * the user can type into the widget. + *

    + * + * @param limit the new text limit. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_CANNOT_BE_ZERO when limit is 0
    • + *
    + */ +public void setTextLimit(int limit) { + checkWidget(); + if (limit == 0) { + SWT.error(SWT.ERROR_CANNOT_BE_ZERO); + } + textLimit = limit; +} +/** + * Sets the top index. Do nothing if there is no text set. + *

    + * The top index is the index of the line that is currently at the top + * of the widget. The top index changes when the widget is scrolled. + * Indexing starts from zero. + * Note: The top index is reset to 0 when new text is set in the widget. + *

    + * + * @param topIndex new top index. Must be between 0 and + * getLineCount() - fully visible lines per page. If no lines are fully + * visible the maximum value is getLineCount() - 1. An out of range + * index will be adjusted accordingly. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTopIndex(int topIndex) { + checkWidget(); + if (getCharCount() == 0) { + return; + } + int lineCount = content.getLineCount(), pixel; + if (isFixedLineHeight()) { + int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); + if (topIndex < 0) { + topIndex = 0; + } else if (topIndex > lineCount - pageSize) { + topIndex = lineCount - pageSize; + } + pixel = getLinePixel(topIndex); + } else { + topIndex = Math.max(0, Math.min(lineCount - 1, topIndex)); + pixel = getLinePixel(topIndex); + if (pixel > 0) { + pixel = getAvailableHeightBellow(pixel); + } else { + pixel = getAvailableHeightAbove(pixel); + } + } + scrollVertical(pixel, true); +} +/** + * Sets the top pixel offset. Do nothing if there is no text set. + *

    + * The top pixel offset is the vertical pixel offset of the widget. The + * widget is scrolled so that the given pixel position is at the top. + * The top index is adjusted to the corresponding top line. + * Note: The top pixel is reset to 0 when new text is set in the widget. + *

    + * + * @param pixel new top pixel offset. Must be between 0 and + * (getLineCount() - visible lines per page) / getLineHeight()). An out + * of range offset will be adjusted accordingly. + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @since 2.0 + */ +public void setTopPixel(int pixel) { + checkWidget(); + if (getCharCount() == 0) { + return; + } + if (pixel < 0) pixel = 0; + int lineCount = content.getLineCount(); + int height = clientAreaHeight - topMargin - bottomMargin; + int verticalOffset = getVerticalScrollOffset(); + if (isFixedLineHeight()) { + int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); + if (pixel > maxTopPixel) pixel = maxTopPixel; + pixel -= verticalOffset; + } else { + pixel -= verticalOffset; + if (pixel > 0) { + pixel = getAvailableHeightBellow(pixel); + } + } + scrollVertical(pixel, true); +} +/** + * Sets whether the widget wraps lines. + *

    + * This overrides the creation style bit SWT.WRAP. + *

    + * + * @param wrap true=widget wraps lines, false=widget does not wrap lines + * @since 2.0 + */ +public void setWordWrap(boolean wrap) { + checkWidget(); + if ((getStyle() & SWT.SINGLE) != 0) return; + if (wordWrap == wrap) return; + wordWrap = wrap; + setVariableLineHeight(); + resetCache(0, content.getLineCount()); + horizontalScrollOffset = 0; + ScrollBar horizontalBar = getHorizontalBar(); + if (horizontalBar != null) { + horizontalBar.setVisible(!wordWrap); + } + setScrollBars(true); + setCaretLocation(); + super.redraw(); +} +/** + * Scrolls the specified location into view. + * + * @param x the x coordinate that should be made visible. + * @param line the line that should be made visible. Relative to the + * first line in the document. + * @return + * true=the widget was scrolled to make the specified location visible. + * false=the specified location is already visible, the widget was + * not scrolled. + */ +boolean showLocation(Rectangle rect) { + int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; + int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; + boolean scrolled = false; + if (rect.y <= topMargin) { + scrolled = scrollVertical(rect.y - topMargin, true); + } else if (rect.y + rect.height > clientAreaHeight) { + scrolled = scrollVertical(rect.y + rect.height - clientAreaHeight, true); + } + if (clientAreaWidth > 0) { + // always make 1/4 of a page visible + if (rect.x < leftMargin) { + int scrollWidth = Math.max(leftMargin - rect.x, clientAreaWidth / 4); + int maxScroll = horizontalScrollOffset; + scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true); + } else if (rect.x + rect.width > clientAreaWidth) { + int scrollWidth = Math.max(rect.x + rect.width - clientAreaWidth, clientAreaWidth / 4); + int maxScroll = renderer.getWidth() - horizontalScrollOffset - this.clientAreaWidth; + scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true); + } + } + return scrolled; +} +/** + * Sets the caret location and scrolls the caret offset into view. + */ +void showCaret() { + Rectangle bounds = getBoundsAtOffset(caretOffset); + if (!showLocation(bounds)) { + setCaretLocation(); + } +} +/** + * Scrolls the selection into view. + *

    + * The end of the selection will be scrolled into view. + * Note that if a right-to-left selection exists, the end of the selection is + * the visual beginning of the selection (i.e., where the caret is located). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void showSelection() { + checkWidget(); + // is selection from right-to-left? + boolean rightToLeft = caretOffset == selection.x; + int startOffset, endOffset; + if (rightToLeft) { + startOffset = selection.y; + endOffset = selection.x; + } else { + startOffset = selection.x; + endOffset = selection.y; + } + + Rectangle startBounds = getBoundsAtOffset(startOffset); + Rectangle endBounds = getBoundsAtOffset(endOffset); + + // can the selection be fully displayed within the widget's visible width? + int w = clientAreaWidth; + boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; + if (selectionFits) { + // show as much of the selection as possible by first showing + // the start of the selection + if (showLocation(startBounds)) { + // endX value could change if showing startX caused a scroll to occur + endBounds = getBoundsAtOffset(endOffset); + } + showLocation(endBounds); + } else { + // just show the end of the selection since the selection start + // will not be visible + showLocation(endBounds); + } +} +/** + * Updates the selection and caret position depending on the text change. + *

    + * If the selection intersects with the replaced text, the selection is + * reset and the caret moved to the end of the new text. + * If the selection is behind the replaced text it is moved so that the + * same text remains selected. If the selection is before the replaced text + * it is left unchanged. + *

    + * + * @param startOffset offset of the text change + * @param replacedLength length of text being replaced + * @param newLength length of new text + */ +void updateSelection(int startOffset, int replacedLength, int newLength) { + if (selection.y <= startOffset) { + // selection ends before text change + return; + } + if (selection.x < startOffset) { + // clear selection fragment before text change + internalRedrawRange(selection.x, startOffset - selection.x); + } + if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { + // clear selection fragment after text change. + // do this only when the selection is actually affected by the + // change. Selection is only affected if it intersects the change (1GDY217). + int netNewLength = newLength - replacedLength; + int redrawStart = startOffset + newLength; + internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart); + } + if (selection.y > startOffset && selection.x < startOffset + replacedLength) { + // selection intersects replaced text. set caret behind text change + setSelection(startOffset + newLength, 0, true); + } else { + // move selection to keep same text selected + setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); + } + setCaretLocation(); +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java new file mode 100644 index 00000000000..7d0135b78c5 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + + +/** + * Clients may implement the StyledTextContent interface to provide a + * custom store for the StyledText widget content. The StyledText widget + * interacts with its StyledTextContent in order to access and update + * the text that is being displayed and edited in the widget. + * A custom content implementation can be set in the widget using the + * StyledText.setContent API. + */ +public interface StyledTextContent { + +/** + * Called by StyledText to add itself as an Observer to content changes. + * See TextChangeListener for a description of the listener methods that + * are called when text changes occur. + *

    + * + * @param listener the listener + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void addTextChangeListener(TextChangeListener listener); + +/** + * Return the number of characters in the content. + *

    + * + * @return the number of characters in the content. + */ +public int getCharCount(); + +/** + * Return the line at the given line index without delimiters. + *

    + * + * @param lineIndex index of the line to return. Does not include + * delimiters of preceding lines. Index 0 is the first line of the + * content. + * @return the line text without delimiters + */ +public String getLine(int lineIndex); + +/** + * Return the line index at the given character offset. + *

    + * + * @param offset offset of the line to return. The first character of the + * document is at offset 0. An offset of getLength() is valid and should + * answer the number of lines. + * @return the line index. The first line is at index 0. If the character + * at offset is a delimiter character, answer the line index of the line + * that is delimited. + * For example, if text = "\r\n\r\n", and delimiter = "\r\n", then: + *

      + *
    • getLineAtOffset(0) == 0 + *
    • getLineAtOffset(1) == 0 + *
    • getLineAtOffset(2) == 1 + *
    • getLineAtOffset(3) == 1 + *
    • getLineAtOffset(4) == 2 + *
    + */ +public int getLineAtOffset(int offset); + +/** + * Return the number of lines. Should answer 1 when no text is specified. + * The StyledText widget relies on this behavior for drawing the cursor. + *

    + * + * @return the number of lines. For example: + *

      + *
    • text value ==> getLineCount + *
    • null ==> 1 + *
    • "" ==> 1 + *
    • "a\n" ==> 2 + *
    • "\n\n" ==> 3 + *
    + */ +public int getLineCount(); + +/** + * Return the line delimiter that should be used by the StyledText + * widget when inserting new lines. New lines entered using key strokes + * and paste operations use this line delimiter. + * Implementors may use System.getProperty("line.separator") to return + * the platform line delimiter. + *

    + * + * @return the line delimiter that should be used by the StyledText widget + * when inserting new lines. + */ +public String getLineDelimiter(); + +/** + * Return the character offset of the first character of the given line. + *

    + * NOTE: When there is no text (i.e., no lines), getOffsetAtLine(0) + * is a valid call that should return 0. + *

    + * + * @param lineIndex index of the line. The first line is at index 0. + * @return offset offset of the first character of the line. The first + * character of the document is at offset 0. The return value should + * include line delimiters. + * For example, if text = "\r\ntest\r\n" and delimiter = "\r\n", then: + *
      + *
    • getOffsetAtLine(0) == 0 + *
    • getOffsetAtLine(1) == 2 + *
    • getOffsetAtLine(2) == 8 + *
    + */ +public int getOffsetAtLine(int lineIndex); + +/** + * Returns a string representing the content at the given range. + *

    + * + * @param start the start offset of the text to return. Offset 0 is the + * first character of the document. + * @param length the length of the text to return + * @return the text at the given range + */ +public String getTextRange(int start, int length); + +/** + * Remove the specified text changed listener. + *

    + * + * @param listener the listener + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT when listener is null
    • + *
    + */ +public void removeTextChangeListener(TextChangeListener listener); + +/** + * Replace the text with "newText" starting at position "start" + * for a length of "replaceLength". + *

    + * Implementors have to notify the TextChangeListeners that were added + * using addTextChangeListener before and after the content + * is changed. A TextChangingEvent has to be sent to the + * textChanging method before the content is changed and a + * TextChangedEvent has to be sent to the textChanged method + * after the content has changed. + * The text change that occurs after the TextChangingEvent + * has been sent has to be consistent with the data provided in the + * TextChangingEvent. + * This data will be cached by the widget and will be used when the + * TextChangedEvent is received. + *

    + * The TextChangingEvent should be set as follows: + *

      + *
    • event.start = start of the replaced text + *
    • event.newText = text that is going to be inserted or empty String + * if no text will be inserted + *
    • event.replaceCharCount = length of text that is going to be replaced + *
    • event.newCharCount = length of text that is going to be inserted + *
    • event.replaceLineCount = number of lines that are going to be replaced + *
    • event.newLineCount = number of new lines that are going to be inserted + *
    + * NOTE: newLineCount is the number of inserted lines and replaceLineCount + * is the number of deleted lines based on the change that occurs visually. + * For example: + *
      + *
    • (replaceText, newText) ==> (replaceLineCount, newLineCount) + *
    • ("", "\n") ==> (0, 1) + *
    • ("\n\n", "a") ==> (2, 0) + *
    • ("a", "\n\n") ==> (0, 2) + *
    • ("\n", "") ==> (1, 0) + *
    + *

    + * + * @param start start offset of text to replace, none of the offsets include + * delimiters of preceding lines, offset 0 is the first character of the + * document + * @param replaceLength length of text to replace + * @param text text to replace + * @see TextChangeListener + */ +public void replaceTextRange(int start, int replaceLength, String text); + +/** + * Set text to "text". + * Implementors have to send a TextChangedEvent to the + * textSet method of the TextChangeListeners that were added using + * addTextChangeListener. + *

    + * + * @param text the new text + * @see TextChangeListener + */ +public void setText(String text); +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java new file mode 100644 index 00000000000..30e70dde4f9 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * + */ +class StyledTextEvent extends Event { + // used by LineStyleEvent + int[] ranges; + StyleRange[] styles; + int alignment; + int indent; + boolean justify; + Bullet bullet; + int bulletIndex; + // used by LineBackgroundEvent + Color lineBackground; + // used by BidiSegmentEvent + int[] segments; + // used by TextChangedEvent + int replaceCharCount; + int newCharCount; + int replaceLineCount; + int newLineCount; + // used by PaintObjectEvent + int x; + int y; + int ascent; + int descent; + GC gc; + StyleRange style; + +StyledTextEvent (StyledTextContent content) { + super(); + data = content; +} +} + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java new file mode 100644 index 00000000000..c87e5b229ab --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + +import org.eclipse.swt.events.*; +import org.eclipse.swt.widgets.*; +import org.eclipse.swt.internal.SWTEventListener; + +class StyledTextListener extends TypedListener { +/** + */ +StyledTextListener(SWTEventListener listener) { + super(listener); +} +/** + * Process StyledText events by invoking the event's handler. + */ +public void handleEvent(Event e) { + TextChangedEvent textChangedEvent; + + switch (e.type) { + case StyledText.ExtendedModify: + ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent((StyledTextEvent) e); + ((ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent); + break; + case StyledText.LineGetBackground: + LineBackgroundEvent lineBgEvent = new LineBackgroundEvent((StyledTextEvent) e); + ((LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent); + ((StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground; + break; + case StyledText.LineGetSegments: + BidiSegmentEvent segmentEvent = new BidiSegmentEvent((StyledTextEvent) e); + ((BidiSegmentListener) eventListener).lineGetSegments(segmentEvent); + ((StyledTextEvent) e).segments = segmentEvent.segments; + break; + case StyledText.LineGetStyle: + LineStyleEvent lineStyleEvent = new LineStyleEvent((StyledTextEvent) e); + ((LineStyleListener) eventListener).lineGetStyle(lineStyleEvent); + ((StyledTextEvent) e).ranges = lineStyleEvent.ranges; + ((StyledTextEvent) e).styles = lineStyleEvent.styles; + ((StyledTextEvent) e).alignment = lineStyleEvent.alignment; + ((StyledTextEvent) e).indent = lineStyleEvent.indent; + ((StyledTextEvent) e).justify = lineStyleEvent.justify; + ((StyledTextEvent) e).bullet = lineStyleEvent.bullet; + ((StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex; + break; + case StyledText.PaintObject: + PaintObjectEvent paintObjectEvent = new PaintObjectEvent((StyledTextEvent) e); + ((PaintObjectListener) eventListener).paintObject(paintObjectEvent); + break; + case StyledText.VerifyKey: + VerifyEvent verifyEvent = new VerifyEvent(e); + ((VerifyKeyListener) eventListener).verifyKey(verifyEvent); + e.doit = verifyEvent.doit; + break; + case StyledText.TextChanged: + textChangedEvent = new TextChangedEvent((StyledTextContent) e.data); + ((TextChangeListener) eventListener).textChanged(textChangedEvent); + break; + case StyledText.TextChanging: + TextChangingEvent textChangingEvent = new TextChangingEvent((StyledTextContent) e.data, (StyledTextEvent) e); + ((TextChangeListener) eventListener).textChanging(textChangingEvent); + break; + case StyledText.TextSet: + textChangedEvent = new TextChangedEvent((StyledTextContent) e.data); + ((TextChangeListener) eventListener).textSet(textChangedEvent); + break; + } +} +} + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java new file mode 100644 index 00000000000..794cf0c33b2 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + +/** + * Use StyledTextPrintOptions to specify printing options for the + * StyledText.print(Printer, StyledTextPrintOptions) API. + *

    + * The following example prints a right aligned page number in the footer, + * sets the job name to "Example" and prints line background colors but no other + * formatting: + *

    + *
    + * StyledTextPrintOptions options = new StyledTextPrintOptions();
    + * options.footer = "\t\t<page>"; 
    + * options.jobName = "Example";
    + * options.printLineBackground = true;
    + * 
    + * Runnable runnable = styledText.print(new Printer(), options); 
    + * runnable.run();
    + * 
    + * @since 2.1 + */ +public class StyledTextPrintOptions { + /** + * Page number placeholder constant for use in header + * and footer. Value is <page> + */ + public static final String PAGE_TAG = ""; + /** + * Separator constant for use in header and + * footer. Value is \t + */ + public static final String SEPARATOR = "\t"; + /** + * Formatted text to print in the header of each page. + *

    "left '\t' center '\t' right"

    + *

    left, center, right = <page> | #CDATA

    + *

    Header and footer are defined as three separate regions for arbitrary + * text or the page number placeholder <page> + * (StyledTextPrintOptions.PAGE_TAG). The three regions are + * left aligned, centered and right aligned. They are separated by a tab + * character (StyledTextPrintOptions.SEPARATOR). + */ + public String header = null; + /** + * Formatted text to print in the footer of each page. + *

    "left '\t' center '\t' right"

    + *

    left, center, right = <page> | #CDATA

    + *

    Header and footer are defined as three separate regions for arbitrary + * text or the page number placeholder <page> + * (StyledTextPrintOptions.PAGE_TAG). The three regions are + * left aligned, centered and right aligned. They are separated by a tab + * character (StyledTextPrintOptions.SEPARATOR). + */ + public String footer = null; + /** + * Name of the print job. + */ + public String jobName = null; + + /** + * Print the text foreground color. Default value is false. + */ + public boolean printTextForeground = false; + /** + * Print the text background color. Default value is false. + */ + public boolean printTextBackground = false; + /** + * Print the font styles. Default value is false. + */ + public boolean printTextFontStyle = false; + /** + * Print the line background color. Default value is false. + */ + public boolean printLineBackground = false; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java new file mode 100644 index 00000000000..966feaf1609 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java @@ -0,0 +1,1480 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.custom; + + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * A StyledTextRenderer renders the content of a StyledText widget. + * This class can be used to render to the display or to a printer. + */ +class StyledTextRenderer { + Device device; + StyledText styledText; + StyledTextContent content; + + /* Font info */ + Font regularFont, boldFont, italicFont, boldItalicFont; + int tabWidth; + int ascent, descent; + int lineEndSpaceWidth; + int averageCharWidth; + + /* Line data */ + int topIndex = -1; + TextLayout[] layouts; + int lineCount; + int[] lineWidth; + int[] lineHeight; + LineInfo[] lines; + int maxWidth; + int maxWidthLineIndex; + boolean idleRunning; + + /* Bullet */ + Bullet[] bullets; + int[] bulletsIndices; + int[] redrawLines; + + /* Style data */ + int[] ranges; + int styleCount; + StyleRange[] styles; + StyleRange[] stylesSet; + int stylesSetCount = 0; + final static int BULLET_MARGIN = 8; + + final static boolean COMPACT_STYLES = true; + final static boolean MERGE_STYLES = true; + + final static int GROW = 32; + final static int IDLE_TIME = 50; + final static int CACHE_SIZE = 128; + + final static int BACKGROUND = 1 << 0; + final static int ALIGNMENT = 1 << 1; + final static int INDENT = 1 << 2; + final static int JUSTIFY = 1 << 3; + final static int SEGMENTS = 1 << 5; + + static class LineInfo { + int flags; + Color background; + int alignment; + int indent; + boolean justify; + int[] segments; + + public LineInfo() { + } + public LineInfo(LineInfo info) { + flags = info.flags; + background = info.background; + alignment = info.alignment; + indent = info.indent; + justify = info.justify; + segments = info.segments; + } + } + +StyledTextRenderer(Device device, StyledText styledText) { + this.device = device; + this.styledText = styledText; +} +int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { + int rangeCount = styleCount << 1; + StyleRange endStyle = null; + int endStart = 0, endLength = 0; + if (modifyEnd < rangeCount) { + endStyle = styles[modifyEnd >> 1]; + endStart = ranges[modifyEnd]; + endLength = ranges[modifyEnd + 1]; + } + int grow = mergeCount - (modifyEnd - modifyStart); + if (rangeCount + grow >= ranges.length) { + int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)]; + System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart); + StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW]; + System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1); + if (rangeCount > modifyEnd) { + System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd); + System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); + } + ranges = tmpRanges; + styles = tmpStyles; + } else { + if (rangeCount > modifyEnd) { + System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd); + System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1)); + } + } + if (MERGE_STYLES) { + int j = modifyStart; + for (int i = 0; i < mergeCount; i += 2) { + if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) { + ranges[j - 1] += mergeRanges[i + 1]; + } else { + styles[j >> 1] = mergeStyles[i >> 1]; + ranges[j++] = mergeRanges[i]; + ranges[j++] = mergeRanges[i + 1]; + } + } + if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) { + ranges[j - 1] += endLength; + modifyEnd += 2; + mergeCount += 2; + } + if (rangeCount > modifyEnd) { + System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd); + System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1)); + } + grow = (j - modifyStart) - (modifyEnd - modifyStart); + } else { + System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount); + System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1); + } + styleCount += grow >> 1; + return grow; +} +int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) { + int grow = mergeCount - (modifyEnd - modifyStart); + StyleRange endStyle = null; + if (modifyEnd < styleCount) endStyle = styles[modifyEnd]; + if (styleCount + grow >= styles.length) { + StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW]; + System.arraycopy(styles, 0, tmpStyles, 0, modifyStart); + if (styleCount > modifyEnd) { + System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd); + } + styles = tmpStyles; + } else { + if (styleCount > modifyEnd) { + System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd); + } + } + if (MERGE_STYLES) { + int j = modifyStart; + for (int i = 0; i < mergeCount; i++) { + StyleRange newStyle = mergeStyles[i], style; + if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) { + style.length += newStyle.length; + } else { + styles[j++] = newStyle; + } + } + StyleRange style = styles[j - 1]; + if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) { + style.length += endStyle.length; + modifyEnd++; + mergeCount++; + } + if (styleCount > modifyEnd) { + System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd); + } + grow = (j - modifyStart) - (modifyEnd - modifyStart); + } else { + System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount); + } + styleCount += grow; + return grow; +} +void calculate(int startLine, int lineCount) { + int endLine = startLine + lineCount; + if (startLine < 0 || endLine > lineWidth.length) { + return; + } + int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth(); + for (int i = startLine; i < endLine; i++) { + if (lineWidth[i] == -1 || lineHeight[i] == -1) { + TextLayout layout = getTextLayout(i); + Rectangle rect = layout.getBounds(); + lineWidth[i] = rect.width + hTrim; + lineHeight[i] = rect.height; + disposeTextLayout(layout); + } + if (lineWidth[i] > maxWidth) { + maxWidth = lineWidth[i]; + maxWidthLineIndex = i; + } + } +} +void calculateClientArea () { + int index = styledText.getTopIndex(); + int lineCount = content.getLineCount(); + int height = styledText.getClientArea().height; + int y = 0; + while (height > y && lineCount > index) { + calculate(index, 1); + y += lineHeight[index++]; + } +} +void calculateIdle () { + if (idleRunning) return; + Runnable runnable = new Runnable() { + public void run() { + if (styledText == null) return; + int i; + long start = System.currentTimeMillis(); + for (i = 0; i < lineCount; i++) { + if (lineHeight[i] == -1 || lineWidth[i] == -1) { + calculate(i, 1); + if (System.currentTimeMillis() - start > IDLE_TIME) break; + } + } + if (i < lineCount) { + Display display = styledText.getDisplay(); + display.asyncExec(this); + } else { + idleRunning = false; + styledText.setScrollBars(true); + ScrollBar bar = styledText.getVerticalBar(); + if (bar != null) { + bar.setSelection(styledText.getVerticalScrollOffset()); + } + } + } + }; + Display display = styledText.getDisplay(); + display.asyncExec(runnable); + idleRunning = true; +} +void clearLineBackground(int startLine, int count) { + if (lines == null) return; + for (int i = startLine; i < startLine + count; i++) { + LineInfo info = lines[i]; + if (info != null) { + info.flags &= ~BACKGROUND; + info.background = null; + if (info.flags == 0) lines[i] = null; + } + } +} +void clearLineStyle(int startLine, int count) { + if (lines == null) return; + for (int i = startLine; i < startLine + count; i++) { + LineInfo info = lines[i]; + if (info != null) { + info.flags &= ~(ALIGNMENT | INDENT | JUSTIFY); + if (info.flags == 0) lines[i] = null; + } + } +} +void copyInto(StyledTextRenderer renderer) { + if (ranges != null) { + int[] newRanges = renderer.ranges = new int[styleCount << 1]; + System.arraycopy(ranges, 0, newRanges, 0, newRanges.length); + } + if (styles != null) { + StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount]; + for (int i = 0; i < newStyles.length; i++) { + newStyles[i] = (StyleRange)styles[i].clone(); + } + renderer.styleCount = styleCount; + } + if (lines != null) { + LineInfo[] newLines = renderer.lines = new LineInfo[lineCount]; + for (int i = 0; i < newLines.length; i++) { + newLines[i] = new LineInfo(lines[i]); + } + renderer.lineCount = lineCount; + } +} +void dispose() { + if (boldFont != null) boldFont.dispose(); + if (italicFont != null) italicFont.dispose(); + if (boldItalicFont != null) boldItalicFont.dispose(); + boldFont = italicFont = boldItalicFont = null; + reset(); + content = null; + device = null; + styledText = null; +} +void disposeTextLayout (TextLayout layout) { + if (layouts != null) { + for (int i = 0; i < layouts.length; i++) { + if (layouts[i] == layout) return; + } + } + layout.dispose(); +} +void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + Color color = style.foreground; + if (color != null) gc.setForeground(color); + if ((bullet.type & ST.BULLET_DOT) != 0 && StyledText.IS_MOTIF) { + int size = Math.max(4, (lineAscent + lineDescent) / 4); + if ((size & 1) == 0) size++; + if (color == null) { + Display display = styledText.getDisplay(); + color = display.getSystemColor(SWT.COLOR_BLACK); + } + gc.setBackground(color); + int x = paintX + Math.max(0, metrics.width - size - BULLET_MARGIN); + gc.fillArc(x, paintY + size, size + 1, size + 1, 0, 360); + return; + } + Font font = style.font; + if (font != null) gc.setFont(font); + String string = ""; + int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER); + switch (type) { + case ST.BULLET_DOT: string = "\u2022"; break; + case ST.BULLET_NUMBER: string = String.valueOf(index); break; + case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break; + case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break; + } + if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text; + Display display = styledText.getDisplay(); + TextLayout layout = new TextLayout(display); + layout.setText(string); + layout.setAscent(lineAscent); + layout.setDescent(lineDescent); + style = (StyleRange)style.clone(); + style.metrics = null; + if (style.font == null) style.font = getFont(style.fontStyle); + layout.setStyle(style, 0, string.length()); + int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN); + layout.draw(gc, x, paintY); + layout.dispose(); +} +int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackground, Color widgetForeground) { + TextLayout layout = getTextLayout(lineIndex); + String line = content.getLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); + int lineLength = line.length(); + Point selection = styledText.getSelection(); + int selectionStart = selection.x; + int selectionEnd = selection.y; + Rectangle client = styledText.getClientArea(); + Color lineBackground = getLineBackground(lineIndex, widgetBackground); + StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line); + if (event != null && event.lineBackground != null) lineBackground = event.lineBackground; + + boolean fullSelection = (styledText.getStyle() & SWT.FULL_SELECTION) != 0; + if (!fullSelection || selectionStart > lineOffset || selectionEnd <= lineOffset + lineLength) { + // draw background if full selection is off or if line is not completely selected + gc.setBackground(lineBackground); + styledText.drawBackground(gc, client.x, paintY, client.width, layout.getBounds().height); + } + if (selectionStart != selectionEnd) { + int y = paintY; + gc.setBackground(styledText.getSelectionBackground()); + int lineCount = layout.getLineCount(); + if (fullSelection) { + int[] offsets = layout.getLineOffsets(); + for (int i = 0; i < lineCount - 1; i++) { + int lineStart = offsets[i]; + if (lineStart >= selectionEnd - lineOffset) break; + int lineEnd = offsets[i + 1]; + Rectangle lineBounds = layout.getLineBounds(i); + if (selectionStart - lineOffset <= lineEnd && lineEnd <= selectionEnd - lineOffset) { + int x = paintX + lineBounds.x + lineBounds.width; + gc.fillRectangle(x, y, client.width - x, lineBounds.height); + } + y += lineBounds.height + layout.getSpacing(); + } + } + if (selectionStart - lineOffset <= lineLength && lineLength < selectionEnd - lineOffset) { + Rectangle lineBounds = layout.getLineBounds(lineCount - 1); + int x = paintX + lineBounds.x + lineBounds.width; + if (fullSelection) { + gc.fillRectangle(x, paintY + lineBounds.y, client.width - styledText.rightMargin - x, lineBounds.height); + } else { + gc.fillRectangle(x, paintY + lineBounds.y, lineEndSpaceWidth, lineBounds.height); + } + } + } + gc.setForeground(widgetForeground); + gc.setBackground(lineBackground); + if (selectionStart == selectionEnd || (selectionEnd <= lineOffset && selectionStart > lineOffset + lineLength - 1)) { + layout.draw(gc, paintX, paintY); + } else { + int start = Math.max(0, selectionStart - lineOffset); + int end = Math.min(lineLength, selectionEnd - lineOffset); + Color selectionFg = styledText.getSelectionForeground(); + Color selectionBg = styledText.getSelectionBackground(); + layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg); + } + + // draw objects + Bullet bullet = null; + int bulletIndex = -1; + if (bullets != null) { + if (bulletsIndices != null) { + int index = lineIndex - topIndex; + if (0 <= index && index < CACHE_SIZE) { + bullet = bullets[index]; + bulletIndex = bulletsIndices[index]; + } + } else { + for (int i = 0; i < bullets.length; i++) { + bullet = bullets[i]; + bulletIndex = bullet.indexOf(lineIndex); + if (bulletIndex != -1) break; + } + } + } + if (bulletIndex != -1 && bullet != null) { + FontMetrics metrics = layout.getLineMetrics(0); + int lineAscent = metrics.getAscent() + metrics.getLeading(); + if (bullet.type == ST.BULLET_CUSTOM) { + bullet.style.start = lineOffset; + styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex); + } else { + drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent()); + } + } + + TextStyle[] styles = layout.getStyles(); + int[] ranges = null; + for (int i = 0; i < styles.length; i++) { + if (styles[i].metrics != null) { + if (ranges == null) ranges = layout.getRanges(); + int start = ranges[i << 1]; + int length = ranges[(i << 1) + 1] - start; + Point point = layout.getLocation(start, false); + FontMetrics metrics = layout.getLineMetrics(layout.getLineIndex(start)); + StyleRange style = (StyleRange)((StyleRange)styles[i]).clone(); + style.start = start + lineOffset; + style.length = length; + int lineAscent = metrics.getAscent() + metrics.getLeading(); + styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0); + } + } + int height = layout.getBounds().height; + disposeTextLayout(layout); + return height; +} +int getBaseline() { + return ascent; +} +Font getFont(int style) { + switch (style) { + case SWT.BOLD: + if (boldFont != null) return boldFont; + return boldFont = new Font(device, getFontData(style)); + case SWT.ITALIC: + if (italicFont != null) return italicFont; + return italicFont = new Font(device, getFontData(style)); + case SWT.BOLD | SWT.ITALIC: + if (boldItalicFont != null) return boldItalicFont; + return boldItalicFont = new Font(device, getFontData(style)); + default: + return regularFont; + } +} +FontData[] getFontData(int style) { + FontData[] fontDatas = regularFont.getFontData(); + for (int i = 0; i < fontDatas.length; i++) { + fontDatas[i].setStyle(style); + } + return fontDatas; +} +int getHeight () { + int defaultLineHeight = getLineHeight(); + if (styledText.isFixedLineHeight()) { + return lineCount * defaultLineHeight; + } + int totalHeight = 0; + int width = styledText.getWrapWidth(); + for (int i = 0; i < lineCount; i++) { + int height = lineHeight[i]; + if (height == -1) { + if (width > 0) { + int length = content.getLine(i).length(); + height = ((length * averageCharWidth / width) + 1) * defaultLineHeight; + } else { + height = defaultLineHeight; + } + } + totalHeight += height; + } + return totalHeight + styledText.topMargin + styledText.bottomMargin; +} +int getLineAlignment(int index, int defaultAlignment) { + if (lines == null) return defaultAlignment; + LineInfo info = lines[index]; + if (info != null && (info.flags & ALIGNMENT) != 0) { + return info.alignment; + } + return defaultAlignment; +} +Color getLineBackground(int index, Color defaultBackground) { + if (lines == null) return defaultBackground; + LineInfo info = lines[index]; + if (info != null && (info.flags & BACKGROUND) != 0) { + return info.background; + } + return defaultBackground; +} +Bullet getLineBullet (int index, Bullet defaultBullet) { + if (bullets == null) return defaultBullet; + if (bulletsIndices != null) return defaultBullet; + for (int i = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + if (bullet.indexOf(index) != -1) return bullet; + } + return defaultBullet; +} +int getLineEndSpace() { + return lineEndSpaceWidth; +} +int getLineHeight() { + return ascent + descent; +} +int getLineHeight(int lineIndex) { + if (lineHeight[lineIndex] == -1) { + calculate(lineIndex, 1); + } + return lineHeight[lineIndex]; +} +int getLineIndent(int index, int defaultIndent) { + if (lines == null) return defaultIndent; + LineInfo info = lines[index]; + if (info != null && (info.flags & INDENT) != 0) { + return info.indent; + } + return defaultIndent; +} +boolean getLineJustify(int index, boolean defaultJustify) { + if (lines == null) return defaultJustify; + LineInfo info = lines[index]; + if (info != null && (info.flags & JUSTIFY) != 0) { + return info.justify; + } + return defaultJustify; +} +int[] getLineSegments(int index, int[] defaultSegments) { + if (lines == null) return defaultSegments; + LineInfo info = lines[index]; + if (info != null && (info.flags & SEGMENTS) != 0) { + return info.segments; + } + return defaultSegments; +} +int getRangeIndex(int offset, int low, int high) { + if (styleCount == 0) return 0; + if (ranges != null) { + while (high - low > 2) { + int index = ((high + low) / 2) / 2 * 2; + int end = ranges[index] + ranges[index + 1]; + if (end > offset) { + high = index; + } else { + low = index; + } + } + } else { + while (high - low > 1) { + int index = ((high + low) / 2); + int end = styles[index].start + styles[index].length; + if (end > offset) { + high = index; + } else { + low = index; + } + } + } + return high; +} +int[] getRanges(int start, int length) { + int[] newRanges; + int end = start + length - 1; + if (ranges != null) { + int rangeCount = styleCount << 1; + int rangeStart = getRangeIndex(start, -1, rangeCount); + if (rangeStart >= rangeCount) return null; + if (ranges[rangeStart] > end) return null; + int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1); + newRanges = new int[rangeEnd - rangeStart + 2]; + System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length); + } else { + int rangeStart = getRangeIndex(start, -1, styleCount); + if (rangeStart >= styleCount) return null; + if (styles[rangeStart].start > end) return null; + int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); + newRanges = new int[(rangeEnd - rangeStart + 1) << 1]; + for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) { + StyleRange style = styles[i]; + newRanges[j] = style.start; + newRanges[j + 1] = style.length; + } + } + if (start > newRanges[0]) { + newRanges[1] = newRanges[0] + newRanges[1] - start; + newRanges[0] = start; + } + if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) { + newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2]; + } + return newRanges; +} +StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) { + StyleRange[] newStyles; + int end = start + length - 1; + if (ranges != null) { + int rangeCount = styleCount << 1; + int rangeStart = getRangeIndex(start, -1, rangeCount); + if (rangeStart >= rangeCount) return null; + if (ranges[rangeStart] > end) return null; + int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1); + newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1]; + if (includeRanges) { + for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) { + newStyles[j] = (StyleRange)styles[i >> 1].clone(); + newStyles[j].start = ranges[i]; + newStyles[j].length = ranges[i + 1]; + } + } else { + System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length); + } + } else { + int rangeStart = getRangeIndex(start, -1, styleCount); + if (rangeStart >= styleCount) return null; + if (styles[rangeStart].start > end) return null; + int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount)); + newStyles = new StyleRange[rangeEnd - rangeStart + 1]; + System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length); + } + StyleRange style = newStyles[0]; + if (start > style.start) { + if (!includeRanges || ranges == null) newStyles[0] = style = (StyleRange)style.clone(); + style.length = style.start + style.length - start; + style.start = start; + } + style = newStyles[newStyles.length - 1]; + if (end < style.start + style.length - 1) { + if (!includeRanges || ranges == null) newStyles[newStyles.length - 1] = style = (StyleRange)style.clone(); + style.length = end - style.start + 1; + } + return newStyles; +} +StyleRange getStyleRange(StyleRange style) { + if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style; + StyleRange clone = (StyleRange)style.clone(); + clone.start = clone.length = 0; + clone.fontStyle = SWT.NORMAL; + if (clone.font == null) clone.font = getFont(style.fontStyle); + return clone; +} +TextLayout getTextLayout(int lineIndex) { + return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing); +} +TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) { + TextLayout layout = null; + if (styledText != null) { + int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0; + if (layouts == null || topIndex != this.topIndex) { + TextLayout[] newLayouts = new TextLayout[CACHE_SIZE]; + if (layouts != null) { + for (int i = 0; i < layouts.length; i++) { + if (layouts[i] != null) { + int layoutIndex = (i + this.topIndex) - topIndex; + if (0 <= layoutIndex && layoutIndex < newLayouts.length) { + newLayouts[layoutIndex] = layouts[i]; + } else { + layouts[i].dispose(); + } + } + } + } + if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) { + int delta = topIndex - this.topIndex; + if (delta > 0) { + if (delta < bullets.length) { + System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta); + System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta); + } + int startIndex = Math.max(0, bullets.length - delta); + for (int i = startIndex; i < bullets.length; i++) bullets[i] = null; + } else { + if (-delta < bullets.length) { + System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta); + System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta); + } + int endIndex = Math.min(bullets.length, -delta); + for (int i = 0; i < endIndex; i++) bullets[i] = null; + } + } + this.topIndex = topIndex; + layouts = newLayouts; + } + if (layouts != null) { + int layoutIndex = lineIndex - topIndex; + if (0 <= layoutIndex && layoutIndex < layouts.length) { + layout = layouts[layoutIndex]; + if (layout != null) { + if (lineWidth[lineIndex] != -1) return layout; + } else { + layout = layouts[layoutIndex] = new TextLayout(device); + } + } + } + } + if (layout == null) layout = new TextLayout(device); + String line = content.getLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); + int[] segments = null; + int indent = 0; + int alignment = SWT.LEFT; + boolean justify = false; + Bullet bullet = null; + int[] ranges = null; + StyleRange[] styles = null; + int rangeStart = 0, styleCount = 0; + StyledTextEvent event = null; + if (styledText != null) { + event = styledText.getLineStyleData(lineOffset, line); + segments = styledText.getBidiSegments(lineOffset, line); + indent = styledText.indent; + alignment = styledText.alignment; + justify = styledText.justify; + } + if (event != null) { + indent = event.indent; + alignment = event.alignment; + justify = event.justify; + bullet = event.bullet; + ranges = event.ranges; + styles = event.styles; + if (styles != null) { + styleCount = styles.length; + if (styledText.isFixedLineHeight()) { + for (int i = 0; i < styleCount; i++) { + if (styles[i].isVariableHeight()) { + styledText.verticalScrollOffset = -1; + styledText.setVariableLineHeight(); + styledText.redraw(); + break; + } + } + } + } + if (bullets == null || bulletsIndices == null) { + bullets = new Bullet[CACHE_SIZE]; + bulletsIndices = new int[CACHE_SIZE]; + } + int index = lineIndex - topIndex; + if (0 <= index && index < CACHE_SIZE) { + bullets[index] = bullet; + bulletsIndices[index] = event.bulletIndex; + } + } else { + if (lines != null) { + LineInfo info = lines[lineIndex]; + if (info != null) { + if ((info.flags & INDENT) != 0) indent = info.indent; + if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment; + if ((info.flags & JUSTIFY) != 0) justify = info.justify; + if ((info.flags & SEGMENTS) != 0) segments = info.segments; + } + } + if (bulletsIndices != null) { + bullets = null; + bulletsIndices = null; + } + if (bullets != null) { + for (int i = 0; i < bullets.length; i++) { + if (bullets[i].indexOf(lineIndex) != -1) { + bullet = bullets[i]; + break; + } + } + } + ranges = this.ranges; + styles = this.styles; + styleCount = this.styleCount; + if (ranges != null) { + rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1); + } else { + rangeStart = getRangeIndex(lineOffset, -1, styleCount); + } + } + if (bullet != null) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + indent += metrics.width; + } + layout.setFont(regularFont); + layout.setAscent(ascent); + layout.setDescent(descent); + layout.setText(line); + layout.setOrientation(orientation); + layout.setSegments(segments); + layout.setWidth(width); + layout.setSpacing(lineSpacing); + layout.setTabs(new int[]{tabWidth}); + layout.setIndent(indent); + layout.setAlignment(alignment); + layout.setJustify(justify); + + int lastOffset = 0; + int length = line.length(); + if (styles != null) { + if (ranges != null) { + int rangeCount = styleCount << 1; + for (int i = rangeStart; i < rangeCount; i += 2) { + int start, end; + if (lineOffset > ranges[i]) { + start = 0; + end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]); + } else { + start = ranges[i] - lineOffset; + end = Math.min(length, start + ranges[i + 1]); + } + if (start >= length) break; + if (lastOffset < start) { + layout.setStyle(null, lastOffset, start - 1); + } + layout.setStyle(getStyleRange(styles[i >> 1]), start, end); + lastOffset = Math.max(lastOffset, end); + } + } else { + for (int i = rangeStart; i < styleCount; i++) { + int start, end; + if (lineOffset > styles[i].start) { + start = 0; + end = Math.min (length, styles[i].length - lineOffset + styles[i].start); + } else { + start = styles[i].start - lineOffset; + end = Math.min(length, start + styles[i].length); + } + if (start >= length) break; + if (lastOffset < start) { + layout.setStyle(null, lastOffset, start - 1); + } + layout.setStyle(getStyleRange(styles[i]), start, end); + lastOffset = Math.max(lastOffset, end); + } + } + } + if (lastOffset < length) layout.setStyle(null, lastOffset, length); + if (styledText != null && styledText.isFixedLineHeight()) { + int index = -1; + int lineCount = layout.getLineCount(); + int height = getLineHeight(); + for (int i = 0; i < lineCount; i++) { + int lineHeight = layout.getLineBounds(i).height; + if (lineHeight > height) { + height = lineHeight; + index = i; + } + } + if (index != -1) { + FontMetrics metrics = layout.getLineMetrics(index); + ascent = metrics.getAscent() + metrics.getLeading(); + descent = metrics.getDescent(); + if (layouts != null) { + for (int i = 0; i < layouts.length; i++) { + if (layouts[i] != null && layouts[i] != layout) { + layouts[i].setAscent(ascent); + layouts[i].setDescent(descent); + } + } + } + if (styledText.verticalScrollOffset != 0) { + int topIndex = styledText.topIndex; + int topIndexY = styledText.topIndexY; + int lineHeight = getLineHeight(); + if (topIndexY >= 0) { + styledText.verticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY; + } else { + styledText.verticalScrollOffset = topIndex * lineHeight - topIndexY; + } + } + styledText.calculateScrollBars(); + if (styledText.isBidiCaret()) styledText.createCaretBitmaps(); + styledText.caretDirection = SWT.NULL; + styledText.setCaretLocation(); + styledText.redraw(); + } + } + return layout; +} +int getWidth() { + return maxWidth; +} +void reset() { + if (layouts != null) { + for (int i = 0; i < layouts.length; i++) { + TextLayout layout = layouts[i]; + if (layout != null) layout.dispose(); + } + layouts = null; + } + topIndex = -1; + stylesSetCount = styleCount = lineCount = 0; + ranges = null; + styles = null; + stylesSet = null; + lines = null; + lineWidth = null; + lineHeight = null; + bullets = null; + bulletsIndices = null; + redrawLines = null; +} +void reset(int startLine, int lineCount) { + int endLine = startLine + lineCount; + if (startLine < 0 || endLine > lineWidth.length) return; + for (int i = startLine; i < endLine; i++) { + lineWidth[i] = -1; + lineHeight[i] = -1; + } + if (startLine <= maxWidthLineIndex && maxWidthLineIndex < endLine) { + maxWidth = 0; + maxWidthLineIndex = -1; + if (lineCount != this.lineCount) { + for (int i = 0; i < this.lineCount; i++) { + if (lineWidth[i] > maxWidth) { + maxWidth = lineWidth[i]; + maxWidthLineIndex = i; + } + } + } + } +} +void setContent(StyledTextContent content) { + reset(); + this.content = content; + lineCount = content.getLineCount(); + lineWidth = new int[lineCount]; + lineHeight = new int[lineCount]; + reset(0, lineCount); +} +void setFont(Font font, int tabs) { + TextLayout layout = new TextLayout(device); + layout.setFont(regularFont); + if (font != null) { + if (boldFont != null) boldFont.dispose(); + if (italicFont != null) italicFont.dispose(); + if (boldItalicFont != null) boldItalicFont.dispose(); + boldFont = italicFont = boldItalicFont = null; + regularFont = font; + layout.setText(" "); + layout.setFont(font); + layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0); + layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1); + layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2); + layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3); + FontMetrics metrics = layout.getLineMetrics(0); + ascent = metrics.getAscent() + metrics.getLeading(); + descent = metrics.getDescent(); + lineEndSpaceWidth = layout.getBounds(0, 0).width; + boldFont.dispose(); + italicFont.dispose(); + boldItalicFont.dispose(); + boldFont = italicFont = boldItalicFont = null; + } + layout.dispose(); + layout = new TextLayout(device); + layout.setFont(regularFont); + StringBuffer tabBuffer = new StringBuffer(tabs); + for (int i = 0; i < tabs; i++) { + tabBuffer.append(' '); + } + layout.setText(tabBuffer.toString()); + tabWidth = layout.getBounds().width; + layout.dispose(); +} +void setLineAlignment(int startLine, int count, int alignment) { + if (lines == null) lines = new LineInfo[lineCount]; + for (int i = startLine; i < startLine + count; i++) { + if (lines[i] == null) { + lines[i] = new LineInfo(); + } + lines[i].flags |= ALIGNMENT; + lines[i].alignment = alignment; + } +} +void setLineBackground(int startLine, int count, Color background) { + if (lines == null) lines = new LineInfo[lineCount]; + for (int i = startLine; i < startLine + count; i++) { + if (lines[i] == null) { + lines[i] = new LineInfo(); + } + lines[i].flags |= BACKGROUND; + lines[i].background = background; + } +} +void setLineBullet(int startLine, int count, Bullet bullet) { + if (bulletsIndices != null) { + bulletsIndices = null; + bullets = null; + } + if (bullets == null) { + if (bullet == null) return; + bullets = new Bullet[1]; + bullets[0] = bullet; + } + int index = 0; + while (index < bullets.length) { + if (bullet == bullets[index]) break; + index++; + } + if (bullet != null) { + if (index == bullets.length) { + Bullet[] newBulletsList = new Bullet[bullets.length + 1]; + System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length); + newBulletsList[index] = bullet; + bullets = newBulletsList; + } + bullet.addIndices(startLine, count); + } else { + updateBullets(startLine, count, 0, false); + styledText.redrawLinesBullet(redrawLines); + redrawLines = null; + } +} +void setLineIndent(int startLine, int count, int indent) { + if (lines == null) lines = new LineInfo[lineCount]; + for (int i = startLine; i < startLine + count; i++) { + if (lines[i] == null) { + lines[i] = new LineInfo(); + } + lines[i].flags |= INDENT; + lines[i].indent = indent; + } +} +void setLineJustify(int startLine, int count, boolean justify) { + if (lines == null) lines = new LineInfo[lineCount]; + for (int i = startLine; i < startLine + count; i++) { + if (lines[i] == null) { + lines[i] = new LineInfo(); + } + lines[i].flags |= JUSTIFY; + lines[i].justify = justify; + } +} +void setLineSegments(int startLine, int count, int[] segments) { + if (lines == null) lines = new LineInfo[lineCount]; + for (int i = startLine; i < startLine + count; i++) { + if (lines[i] == null) { + lines[i] = new LineInfo(); + } + lines[i].flags |= SEGMENTS; + lines[i].segments = segments; + } +} +void setStyleRanges (int[] newRanges, StyleRange[] newStyles) { + if (newStyles == null) { + stylesSetCount = styleCount = 0; + ranges = null; + styles = null; + stylesSet = null; + return; + } + if (newRanges == null && COMPACT_STYLES) { + newRanges = new int[newStyles.length << 1]; + StyleRange[] tmpStyles = new StyleRange[newStyles.length]; + if (stylesSet == null) stylesSet = new StyleRange[4]; + for (int i = 0, j = 0; i < newStyles.length; i++) { + StyleRange newStyle = newStyles[i]; + newRanges[j++] = newStyle.start; + newRanges[j++] = newStyle.length; + int index = 0; + while (index < stylesSetCount) { + if (stylesSet[index].similarTo(newStyle)) break; + index++; + } + if (index == stylesSetCount) { + if (stylesSetCount == stylesSet.length) { + StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4]; + System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount); + stylesSet = tmpStylesSet; + } + stylesSet[stylesSetCount++] = newStyle; + } + tmpStyles[i] = stylesSet[index]; + } + newStyles = tmpStyles; + } + + if (styleCount == 0) { + if (newRanges != null) { + ranges = new int[newRanges.length]; + System.arraycopy(newRanges, 0, ranges, 0, ranges.length); + } + styles = new StyleRange[newStyles.length]; + System.arraycopy(newStyles, 0, styles, 0, styles.length); + styleCount = newStyles.length; + return; + } + if (newRanges != null && ranges == null) { + ranges = new int[styles.length << 1]; + for (int i = 0, j = 0; i < styleCount; i++) { + ranges[j++] = styles[i].start; + ranges[j++] = styles[i].length; + } + } + if (newRanges == null && ranges != null) { + newRanges = new int[newStyles.length << 1]; + for (int i = 0, j = 0; i < newStyles.length; i++) { + newRanges[j++] = newStyles[i].start; + newRanges[j++] = newStyles[i].length; + } + } + if (ranges != null) { + int rangeCount = styleCount << 1; + int start = newRanges[0]; + int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd; + boolean insert = modifyStart == rangeCount; + if (!insert) { + int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1]; + modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); + insert = modifyStart == modifyEnd && ranges[modifyStart] >= end; + } + if (insert) { + addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart); + return; + } + modifyEnd = modifyStart; + int[] mergeRanges = new int[6]; + StyleRange[] mergeStyles = new StyleRange[3]; + for (int i = 0; i < newRanges.length; i += 2) { + int newStart = newRanges[i]; + int newEnd = newStart + newRanges[i + 1]; + if (newStart == newEnd) continue; + int modifyLast = 0, mergeCount = 0; + while (modifyEnd < rangeCount) { + if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2; + if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break; + modifyEnd += 2; + } + if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) { + mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1]; + mergeRanges[mergeCount] = ranges[modifyStart]; + mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart]; + mergeCount += 2; + } + mergeStyles[mergeCount >> 1] = newStyles[i >> 1]; + mergeRanges[mergeCount] = newStart; + mergeRanges[mergeCount + 1] = newRanges[i + 1]; + mergeCount += 2; + if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) { + mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1]; + mergeRanges[mergeCount] = newEnd; + mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd; + mergeCount += 2; + modifyLast = 2; + } + int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); + rangeCount += grow; + modifyStart = modifyEnd += grow; + } + } else { + int start = newStyles[0].start; + int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd; + boolean insert = modifyStart == styleCount; + if (!insert) { + int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length; + modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); + insert = modifyStart == modifyEnd && styles[modifyStart].start >= end; + } + if (insert) { + addMerge(newStyles, newStyles.length, modifyStart, modifyStart); + return; + } + modifyEnd = modifyStart; + StyleRange[] mergeStyles = new StyleRange[3]; + for (int i = 0; i < newStyles.length; i++) { + StyleRange newStyle = newStyles[i], style; + int newStart = newStyle.start; + int newEnd = newStart + newStyle.length; + if (newStart == newEnd) continue; + int modifyLast = 0, mergeCount = 0; + while (modifyEnd < styleCount) { + if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++; + if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break; + modifyEnd++; + } + style = styles[modifyStart]; + if (style.start < newStart && newStart < style.start + style.length) { + style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); + style.length = newStart - style.start; + } + mergeStyles[mergeCount++] = newStyle; + if (modifyEnd < styleCount) { + style = styles[modifyEnd]; + if (style.start < newEnd && newEnd < style.start + style.length) { + style = mergeStyles[mergeCount++] = (StyleRange)style.clone(); + style.length += style.start - newEnd; + style.start = newEnd; + modifyLast = 1; + } + } + int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast); + modifyStart = modifyEnd += grow; + } + } +} +void textChanging(TextChangingEvent event) { + int start = event.start; + int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount; + int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount; + + updateRanges(start, replaceCharCount, newCharCount); + + int startLine = content.getLineAtOffset(start); + if (replaceCharCount == content.getCharCount()) lines = null; + if (replaceLineCount == lineCount) { + lineCount = newLineCount; + lineWidth = new int[lineCount]; + lineHeight = new int[lineCount]; + reset(0, lineCount); + } else { + int delta = newLineCount - replaceLineCount; + if (lineCount + delta > lineWidth.length) { + int[] newWidths = new int[lineCount + delta + GROW]; + System.arraycopy(lineWidth, 0, newWidths, 0, lineCount); + lineWidth = newWidths; + int[] newHeights = new int[lineCount + delta + GROW]; + System.arraycopy(lineHeight, 0, newHeights, 0, lineCount); + lineHeight = newHeights; + } + if (lines != null) { + if (lineCount + delta > lines.length) { + LineInfo[] newLines = new LineInfo[lineCount + delta + GROW]; + System.arraycopy(lines, 0, newLines, 0, lineCount); + lines = newLines; + } + } + int startIndex = startLine + replaceLineCount + 1; + int endIndex = startLine + newLineCount + 1; + System.arraycopy(lineWidth, startIndex, lineWidth, endIndex, lineCount - startIndex); + System.arraycopy(lineHeight, startIndex, lineHeight, endIndex, lineCount - startIndex); + for (int i = startLine; i < endIndex; i++) { + lineWidth[i] = lineHeight[i] = -1; + } + for (int i = lineCount + delta; i < lineCount; i++) { + lineWidth[i] = lineHeight[i] = -1; + } + if (layouts != null) { + int layoutStartLine = startLine - topIndex; + int layoutEndLine = layoutStartLine + replaceLineCount + 1; + for (int i = layoutStartLine; i < layoutEndLine; i++) { + if (0 <= i && i < layouts.length) { + if (layouts[i] != null) layouts[i].dispose(); + layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; + } + } + if (delta > 0) { + for (int i = layouts.length - 1; i >= layoutEndLine; i--) { + if (0 <= i && i < layouts.length) { + endIndex = i + delta; + if (0 <= endIndex && endIndex < layouts.length) { + layouts[endIndex] = layouts[i]; + layouts[i] = null; + if (bullets != null && bulletsIndices != null) { + bullets[endIndex] = bullets[i]; + bulletsIndices[endIndex] = bulletsIndices[i]; + bullets[i] = null; + } + } else { + if (layouts[i] != null) layouts[i].dispose(); + layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; + } + } + } + } else if (delta < 0) { + for (int i = layoutEndLine; i < layouts.length; i++) { + if (0 <= i && i < layouts.length) { + endIndex = i + delta; + if (0 <= endIndex && endIndex < layouts.length) { + layouts[endIndex] = layouts[i]; + layouts[i] = null; + if (bullets != null && bulletsIndices != null) { + bullets[endIndex] = bullets[i]; + bulletsIndices[endIndex] = bulletsIndices[i]; + bullets[i] = null; + } + } else { + if (layouts[i] != null) layouts[i].dispose(); + layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; + } + } + } + } + } + if (replaceLineCount != 0 || newLineCount != 0) { + int startLineOffset = content.getOffsetAtLine(startLine); + if (startLineOffset != start) startLine++; + updateBullets(startLine, replaceLineCount, newLineCount, true); + if (lines != null) { + startIndex = startLine + replaceLineCount; + endIndex = startLine + newLineCount; + System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex); + for (int i = startLine; i < endIndex; i++) { + lines[i] = null; + } + for (int i = lineCount + delta; i < lineCount; i++) { + lines[i] = null; + } + } + } + lineCount += delta; + if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) { + maxWidth = 0; + maxWidthLineIndex = -1; + for (int i = 0; i < lineCount; i++) { + if (lineWidth[i] > maxWidth) { + maxWidth = lineWidth[i]; + maxWidthLineIndex = i; + } + } + } + } +} +void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) { + if (bullets == null) return; + if (bulletsIndices != null) return; + for (int i = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update); + if (lines != null) { + if (redrawLines == null) { + redrawLines = lines; + } else { + int[] newRedrawBullets = new int[redrawLines.length + lines.length]; + System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length); + System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length); + redrawLines = newRedrawBullets; + } + } + } + int removed = 0; + for (int i = 0; i < bullets.length; i++) { + if (bullets[i].size() == 0) removed++; + } + if (removed > 0) { + if (removed == bullets.length) { + bullets = null; + } else { + Bullet[] newBulletsList = new Bullet[bullets.length - removed]; + for (int i = 0, j = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + if (bullet.size() > 0) newBulletsList[j++] = bullet; + } + bullets = newBulletsList; + } + } +} +void updateRanges(int start, int replaceCharCount, int newCharCount) { + if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return; + if (ranges != null) { + int rangeCount = styleCount << 1; + int modifyStart = getRangeIndex(start, -1, rangeCount); + if (modifyStart == rangeCount) return; + int end = start + replaceCharCount; + int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount); + int offset = newCharCount - replaceCharCount; + if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { + if (newCharCount == 0) { + ranges[modifyStart + 1] -= replaceCharCount; + modifyEnd += 2; + } else { + if (rangeCount + 2 > ranges.length) { + int[] newRanges = new int[ranges.length + (GROW << 1)]; + System.arraycopy(ranges, 0, newRanges, 0, rangeCount); + ranges = newRanges; + StyleRange[] newStyles = new StyleRange[styles.length + GROW]; + System.arraycopy(styles, 0, newStyles, 0, styleCount); + styles = newStyles; + } + System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2)); + System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1)); + ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end; + ranges[modifyStart + 2] = start + newCharCount; + ranges[modifyStart + 1] = start - ranges[modifyStart]; + styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1]; + rangeCount += 2; + styleCount++; + modifyEnd += 4; + } + if (offset != 0) { + for (int i = modifyEnd; i < rangeCount; i += 2) { + ranges[i] += offset; + } + } + } else { + if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) { + ranges[modifyStart + 1] = start - ranges[modifyStart]; + modifyStart += 2; + } + if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) { + ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end; + ranges[modifyEnd] = end; + } + if (offset != 0) { + for (int i = modifyEnd; i < rangeCount; i += 2) { + ranges[i] += offset; + } + } + System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd); + System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1)); + styleCount -= (modifyEnd - modifyStart) >> 1; + } + } else { + int modifyStart = getRangeIndex(start, -1, styleCount); + if (modifyStart == styleCount) return; + int end = start + replaceCharCount; + int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount); + int offset = newCharCount - replaceCharCount; + if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) { + if (newCharCount == 0) { + styles[modifyStart].length -= replaceCharCount; + modifyEnd++; + } else { + if (styleCount + 1 > styles.length) { + StyleRange[] newStyles = new StyleRange[styles.length + GROW]; + System.arraycopy(styles, 0, newStyles, 0, styleCount); + styles = newStyles; + } + System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1)); + styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone(); + styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end; + styles[modifyStart + 1].start = start + newCharCount; + styles[modifyStart].length = start - styles[modifyStart].start; + styleCount++; + modifyEnd += 2; + } + if (offset != 0) { + for (int i = modifyEnd; i < styleCount; i++) { + styles[i].start += offset; + } + } + } else { + if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) { + styles[modifyStart].length = start - styles[modifyStart].start; + modifyStart++; + } + if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) { + styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end; + styles[modifyEnd].start = end; + } + if (offset != 0) { + for (int i = modifyEnd; i < styleCount; i++) { + styles[i].start += offset; + } + } + System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd); + styleCount -= modifyEnd - modifyStart; + } + } +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java new file mode 100644 index 00000000000..73c4bf6f9e1 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + + +/** + * The class ByteArrayTransfer provides a platform specific + * mechanism for converting a java byte[] to a platform + * specific representation of the byte array and vice versa. See + * Transfer for additional information. + * + *

    ByteArrayTransfer is never used directly but is sub-classed + * by transfer agents that convert between data in a java format such as a + * String and a platform specific byte array. + * + *

    If the data you are converting does not map to a + * byte[], you should sub-class Transfer directly + * and do your own mapping to a platform data type.

    + * + *

    The following snippet shows a subclass of ByteArrayTransfer that transfers + * data defined by the class MyType.

    + * + *
    
    + * public class MyType {
    + *  public String fileName;
    + *  public long fileLength;
    + *  public long lastModified;
    + * }
    + * 
    + * + *
    
    + * public class MyTypeTransfer extends ByteArrayTransfer {
    + *  
    + *  private static final String MYTYPENAME = "my_type_name";
    + *  private static final int MYTYPEID = registerType(MYTYPENAME);
    + *  private static MyTypeTransfer _instance = new MyTypeTransfer();
    + * 
    + * private MyTypeTransfer() {}
    + * 
    + * public static MyTypeTransfer getInstance () {
    + *  return _instance;
    + * }
    + * public void javaToNative (Object object, TransferData transferData) {
    + *  if (object == null || !(object instanceof MyType[])) return;
    + *  
    + *  if (isSupportedType(transferData)) {
    + *    MyType[] myTypes = (MyType[]) object; 
    + *    try {
    + *      // write data to a byte array and then ask super to convert to pMedium
    + *      ByteArrayOutputStream out = new ByteArrayOutputStream();
    + *      DataOutputStream writeOut = new DataOutputStream(out);
    + *      for (int i = 0, length = myTypes.length; i < length;  i++){
    + *        byte[] buffer = myTypes[i].fileName.getBytes();
    + *        writeOut.writeInt(buffer.length);
    + *        writeOut.write(buffer);
    + *        writeOut.writeLong(myTypes[i].fileLength);
    + *        writeOut.writeLong(myTypes[i].lastModified);
    + *      }
    + *      byte[] buffer = out.toByteArray();
    + *      writeOut.close();
    + * 
    + *      super.javaToNative(buffer, transferData);
    + *      
    + *    } catch (IOException e) {
    + *    }
    + *  }
    + * }
    + * public Object nativeToJava(TransferData transferData){ 
    + * 
    + *  if (isSupportedType(transferData)) {
    + *    
    + *    byte[] buffer = (byte[])super.nativeToJava(transferData);
    + *    if (buffer == null) return null;
    + *    
    + *    MyType[] myData = new MyType[0];
    + *    try {
    + *      ByteArrayInputStream in = new ByteArrayInputStream(buffer);
    + *      DataInputStream readIn = new DataInputStream(in);
    + *      while(readIn.available() > 20) {
    + *        MyType datum = new MyType();
    + *        int size = readIn.readInt();
    + *        byte[] name = new byte[size];
    + *        readIn.read(name);
    + *        datum.fileName = new String(name);
    + *        datum.fileLength = readIn.readLong();
    + *        datum.lastModified = readIn.readLong();
    + *        MyType[] newMyData = new MyType[myData.length + 1];
    + *        System.arraycopy(myData, 0, newMyData, 0, myData.length);
    + *        newMyData[myData.length] = datum;
    + *        myData = newMyData;
    + *      }
    + *      readIn.close();
    + *    } catch (IOException ex) {
    + *      return null;
    + *    }
    + *    return myData;
    + *  }
    + * 
    + *  return null;
    + * }
    + * protected String[] getTypeNames(){
    + *  return new String[]{MYTYPENAME};
    + * }
    + * protected int[] getTypeIds(){
    + *  return new int[] {MYTYPEID};
    + * }
    + * }
    + * 
    + */ +public abstract class ByteArrayTransfer extends Transfer { + +public TransferData[] getSupportedTypes() { + TransferData transferData = new TransferData(); + // TODO: how to obtain the list of types? + transferData.dataFlavor = byteArrayDataFlavor; + return new TransferData[] {transferData}; +// int[] types = getTypeNames(); +// TransferData[] data = new TransferData[names.length]; +// for (int i = 0; i < names.length; i++) { +// data[i] = new TransferData(); +// data[i].type = types[i]; +// } +// return data; +} + +DataFlavor byteArrayDataFlavor = new DataFlavor(byte[].class, "Bytes"); + +protected DataFlavor getDataFlavor() { + return byteArrayDataFlavor; +} + +/** + * This implementation of javaToNative converts a java + * byte[] to a platform specific representation. For additional + * information see Transfer#javaToNative. + * + * @see Transfer#javaToNative + * + * @param object a java byte[] containing the data to be converted + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +protected void javaToNative (final Object object, TransferData transferData) { + if (!checkByteArray(object) && !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + transferData.transferable = new Transferable() { + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if(flavor != byteArrayDataFlavor) { + throw new UnsupportedFlavorException(flavor); + } + return object; + } + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] {byteArrayDataFlavor}; + } + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor == byteArrayDataFlavor; + } + }; +} + +boolean checkByteArray(Object object) { + return (object != null && object instanceof byte[] && ((byte[])object).length > 0); +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java new file mode 100644 index 00000000000..2a3915acde4 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java @@ -0,0 +1,614 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.ArrayList; + +import javax.swing.SwingUtilities; + +import org.eclipse.swt.*; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.widgets.*; + +/** + * The Clipboard provides a mechanism for transferring data from one + * application to another or within an application. + * + *

    IMPORTANT: This class is not intended to be subclassed.

    + */ +public class Clipboard { + +private Display display; + +/** + * Constructs a new instance of this class. Creating an instance of a Clipboard + * may cause system resources to be allocated depending on the platform. It is therefore + * mandatory that the Clipboard instance be disposed when no longer required. + * + * @param display the display on which to allocate the clipboard + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Clipboard#dispose + * @see Clipboard#checkSubclass + */ +public Clipboard(Display display) { + checkSubclass (); + if (display == null) { + display = Display.getCurrent(); + if (display == null) { + display = Display.getDefault(); + } + } + if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS); + this.display = display; +} + +/** + * Checks that this class can be subclassed. + *

    + * The SWT class library is intended to be subclassed + * only at specific, controlled points. This method enforces this + * rule unless it is overridden. + *

    + * IMPORTANT: By providing an implementation of this + * method that allows a subclass of a class which does not + * normally allow subclassing to be created, the implementer + * agrees to be fully responsible for the fact that any such + * subclass will likely fail between SWT releases and will be + * strongly platform specific. No support is provided for + * user-written classes which are implemented in this fashion. + *

    + * The ability to subclass outside of the allowed SWT classes + * is intended purely to enable those not on the SWT development + * team to implement patches in order to get around specific + * limitations in advance of when those limitations can be + * addressed by the team. Subclassing should not be attempted + * without an intimate and detailed understanding of the hierarchy. + *

    + * + * @exception SWTException
      + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +protected void checkSubclass () { + String name = getClass().getName (); + String validName = Clipboard.class.getName(); + if (!validName.equals(name)) { + DND.error (SWT.ERROR_INVALID_SUBCLASS); + } +} + +/** + * Throws an SWTException if the receiver can not + * be accessed by the caller. This may include both checks on + * the state of the receiver and more generally on the entire + * execution context. This method should be called by + * widget implementors to enforce the standard SWT invariants. + *

    + * Currently, it is an error to invoke any method (other than + * isDisposed()) on a widget that has had its + * dispose() method called. It is also an error + * to call widget methods from any thread that is different + * from the thread that created the widget. + *

    + * In future releases of SWT, there may be more or fewer error + * checks and exceptions may be thrown for different reasons. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +protected void checkWidget () { + Display display = this.display; + if (display == null) DND.error (SWT.ERROR_WIDGET_DISPOSED); + if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS); + if (display.isDisposed()) DND.error(SWT.ERROR_WIDGET_DISPOSED); +} + +/** + * If this clipboard is currently the owner of the data on the system clipboard, + * clear the contents. If this clipboard is not the owner, then nothing is done. + * Note that there are clipboard assistant applications that take ownership of + * data or make copies of data when it is placed on the clipboard. In these + * cases, it may not be possible to clear the clipboard. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void clearContents() { + clearContents(DND.CLIPBOARD); +} + +/** + * If this clipboard is currently the owner of the data on the specified + * clipboard, clear the contents. If this clipboard is not the owner, then + * nothing is done. + * + *

    Note that there are clipboard assistant applications that take ownership + * of data or make copies of data when it is placed on the clipboard. In these + * cases, it may not be possible to clear the clipboard.

    + * + *

    The clipboards value is either one of the clipboard constants defined in + * class DND, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those DND clipboard constants.

    + * + * @param clipboards to be cleared + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DND#CLIPBOARD + * @see DND#SELECTION_CLIPBOARD + * + * @since 3.1 + */ +public void clearContents(int clipboards) { + checkWidget(); + try { + if ((clipboards & DND.CLIPBOARD) != 0) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(null, null); + } + if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) { + java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection(); + if(systemSelection != null) { + systemSelection.setContents(null, null); + } + } + } catch(Exception e) { + DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); + } +} + +/** + * Disposes of the operating system resources associated with the clipboard. + * The data will still be available on the system clipboard after the dispose + * method is called. + * + *

    NOTE: On some platforms the data will not be available once the application + * has exited or the display has been disposed.

    + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + */ +public void dispose () { + if (isDisposed()) return; + if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS); + display = null; +} + +/** + * Retrieve the data of the specified type currently available on the system + * clipboard. Refer to the specific subclass of Transfer to + * determine the type of object returned. + * + *

    The following snippet shows text and RTF text being retrieved from the + * clipboard:

    + * + *
    + *    Clipboard clipboard = new Clipboard(display);
    + *    TextTransfer textTransfer = TextTransfer.getInstance();
    + *    String textData = (String)clipboard.getContents(textTransfer);
    + *    if (textData != null) System.out.println("Text is "+textData);
    + *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
    + *    String rtfData = (String)clipboard.getContents(rtfTransfer);
    + *    if (rtfData != null) System.out.println("RTF Text is "+rtfData);
    + *    clipboard.dispose();
    + *    
    + * + * @param transfer the transfer agent for the type of data being requested + * @return the data obtained from the clipboard or null if no data of this type is available + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if transfer is null
    • + *
    + * + * @see Transfer + */ +public Object getContents(Transfer transfer) { + return getContents(transfer, DND.CLIPBOARD); +} +/** + * Retrieve the data of the specified type currently available on the specified + * clipboard. Refer to the specific subclass of Transfer to + * determine the type of object returned. + * + *

    The following snippet shows text and RTF text being retrieved from the + * clipboard:

    + * + *
    + *    Clipboard clipboard = new Clipboard(display);
    + *    TextTransfer textTransfer = TextTransfer.getInstance();
    + *    String textData = (String)clipboard.getContents(textTransfer);
    + *    if (textData != null) System.out.println("Text is "+textData);
    + *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
    + *    String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
    + *    if (rtfData != null) System.out.println("RTF Text is "+rtfData);
    + *    clipboard.dispose();
    + *    
    + * + *

    The clipboards value is either one of the clipboard constants defined in + * class DND, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those DND clipboard constants.

    + * + * @param transfer the transfer agent for the type of data being requested + * @param clipboards on which to look for data + * + * @return the data obtained from the clipboard or null if no data of this type is available + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if transfer is null
    • + *
    + * + * @see Transfer + * @see DND#CLIPBOARD + * @see DND#SELECTION_CLIPBOARD + * + * @since 3.1 + */ +public Object getContents(Transfer transfer, int clipboards) { + checkWidget(); + if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT); + ArrayList clipboardList = new ArrayList(); + if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) { + java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection(); + if(systemSelection != null) { + clipboardList.add(systemSelection); + } + } + if ((clipboards & DND.CLIPBOARD) != 0) { + clipboardList.add(Toolkit.getDefaultToolkit().getSystemClipboard()); + } + for(int i=clipboardList.size() - 1; i >= 0; i--) { + java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i); + TransferData[] supportedTypes = transfer.getSupportedTypes(); + for(int j=0; jtrue if the clipboard has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the clipboard. + * When a clipboard has been disposed, it is an error to + * invoke any other method using the clipboard. + *

    + * + * @return true when the widget is disposed and false otherwise + * + * @since 3.0 + */ +public boolean isDisposed () { + return (display == null); +} + +/** + * Place data of the specified type on the system clipboard. More than one type + * of data can be placed on the system clipboard at the same time. Setting the + * data clears any previous data from the system clipboard, regardless of type. + * + *

    NOTE: On some platforms, the data is immediately copied to the system + * clipboard but on other platforms it is provided upon request. As a result, + * if the application modifes the data object it has set on the clipboard, that + * modification may or may not be available when the data is subsequently + * requested.

    + * + *

    The following snippet shows text and RTF text being set on the copy/paste + * clipboard: + *

    + * + *
    + * 	Clipboard clipboard = new Clipboard(display);
    + *	String textData = "Hello World";
    + *	String rtfData = "{\\rtf1\\b\\i Hello World}";
    + *	TextTransfer textTransfer = TextTransfer.getInstance();
    + *	RTFTransfer rtfTransfer = RTFTransfer.getInstance();
    + *	Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
    + *	Object[] data = new Object[]{textData, rtfData};
    + *	clipboard.setContents(data, transfers);
    + *	clipboard.dispose();
    + * 
    + * + * @param data the data to be set in the clipboard + * @param dataTypes the transfer agents that will convert the data to its + * platform specific format; each entry in the data array must have a + * corresponding dataType + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if data is null or datatypes is null + * or the length of data is not the same as the length of dataTypes
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception SWTError
      + *
    • ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
    • + *
    + * + *

    NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a + * recoverable error, but can not be changed due to backward compatability.

    + */ +public void setContents(Object[] data, Transfer[] dataTypes) { + setContents(data, dataTypes, DND.CLIPBOARD); +} + +/** + * Place data of the specified type on the specified clipboard. More than one + * type of data can be placed on the specified clipboard at the same time. + * Setting the data clears any previous data from the specified + * clipboard, regardless of type. + * + *

    NOTE: On some platforms, the data is immediately copied to the specified + * clipboard but on other platforms it is provided upon request. As a result, + * if the application modifes the data object it has set on the clipboard, that + * modification may or may not be available when the data is subsequently + * requested.

    + * + *

    The clipboards value is either one of the clipboard constants defined in + * class DND, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those DND clipboard constants.

    + * + *

    The following snippet shows text and RTF text being set on the copy/paste + * clipboard: + *

    + * + *
    + * 	Clipboard clipboard = new Clipboard(display);
    + *	String textData = "Hello World";
    + *	String rtfData = "{\\rtf1\\b\\i Hello World}";
    + *	TextTransfer textTransfer = TextTransfer.getInstance();
    + *	RTFTransfer rtfTransfer = RTFTransfer.getInstance();
    + *	Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
    + *	Object[] data = new Object[]{textData, rtfData};
    + *	clipboard.setContents(data, transfers, DND.CLIPBOARD);
    + *	clipboard.dispose();
    + * 
    + * + * @param data the data to be set in the clipboard + * @param dataTypes the transfer agents that will convert the data to its + * platform specific format; each entry in the data array must have a + * corresponding dataType + * @param clipboards on which to set the data + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if data is null or datatypes is null + * or the length of data is not the same as the length of dataTypes
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception SWTError
      + *
    • ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
    • + *
    + * + *

    NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a + * recoverable error, but can not be changed due to backward compatability.

    + * + * @see DND#CLIPBOARD + * @see DND#SELECTION_CLIPBOARD + * + * @since 3.1 + */ +public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) { + checkWidget(); + if (data == null || dataTypes == null || data.length != dataTypes.length || data.length == 0) { + DND.error(SWT.ERROR_INVALID_ARGUMENT); + } + for (int i = 0; i < data.length; i++) { + if (data[i] == null || dataTypes[i] == null || !dataTypes[i].validate(data[i])) { + DND.error(SWT.ERROR_INVALID_ARGUMENT); + } + } + ArrayList transferableList = new ArrayList(); + ArrayList flavorList = new ArrayList(); + for(int i=0; i= 0; i--) { + java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i); + clipboard.setContents(transferable, null); + } +//DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); +} + +/** + * Returns an array of the data types currently available on the system + * clipboard. Use with Transfer.isSupportedType. + * + * @return array of data types currently available on the system clipboard + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Transfer#isSupportedType + * + * @since 3.0 + */ +public TransferData[] getAvailableTypes() { + return getAvailableTypes(DND.CLIPBOARD); +} + +/** + * Returns an array of the data types currently available on the specified + * clipboard. Use with Transfer.isSupportedType. + * + *

    The clipboards value is either one of the clipboard constants defined in + * class DND, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those DND clipboard constants.

    + * + * @param clipboards from which to get the data types + * @return array of data types currently available on the specified clipboard + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Transfer#isSupportedType + * @see DND#CLIPBOARD + * @see DND#SELECTION_CLIPBOARD + * + * @since 3.1 + */ +public TransferData[] getAvailableTypes(int clipboards) { + checkWidget(); + ArrayList clipboardList = new ArrayList(); + if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) { + java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection(); + if(systemSelection != null) { + clipboardList.add(systemSelection); + } + } + if ((clipboards & DND.CLIPBOARD) != 0) { + clipboardList.add(Toolkit.getDefaultToolkit().getSystemClipboard()); + } + for(int i=clipboardList.size() - 1; i >= 0; i--) { + java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i); + DataFlavor[] dataFlavors = clipboard.getAvailableDataFlavors(); + TransferData[] dataArray = new TransferData[dataFlavors.length]; + for(int j=0; jNote: getAvailableTypeNames is a utility for writing a Transfer + * sub-class. It should NOT be used within an application because it provides + * platform specific information.

    + * + * @return a platform specific list of the data types currently available on the + * system clipboard + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String[] getAvailableTypeNames() { + checkWidget(); + DataFlavor[] flavors = Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors(); + String[] typeNames = new String[flavors.length]; + for(int i=0; iDragSource defines the source object for a drag and drop transfer. + * + *

    IMPORTANT: This class is not intended to be subclassed.

    + * + *

    A drag source is the object which originates a drag and drop operation. For the specified widget, + * it defines the type of data that is available for dragging and the set of operations that can + * be performed on that data. The operations can be any bit-wise combination of DND.MOVE, DND.COPY or + * DND.LINK. The type of data that can be transferred is specified by subclasses of Transfer such as + * TextTransfer or FileTransfer. The type of data transferred can be a predefined system type or it + * can be a type defined by the application. For instructions on how to define your own transfer type, + * refer to ByteArrayTransfer.

    + * + *

    You may have several DragSources in an application but you can only have one DragSource + * per Control. Data dragged from this DragSource can be dropped on a site within this application + * or it can be dropped on another application such as an external Text editor.

    + * + *

    The application supplies the content of the data being transferred by implementing the + * DragSourceListener and associating it with the DragSource via DragSource#addDragListener.

    + * + *

    When a successful move operation occurs, the application is required to take the appropriate + * action to remove the data from its display and remove any associated operating system resources or + * internal references. Typically in a move operation, the drop target makes a copy of the data + * and the drag source deletes the original. However, sometimes copying the data can take a long + * time (such as copying a large file). Therefore, on some platforms, the drop target may actually + * move the data in the operating system rather than make a copy. This is usually only done in + * file transfers. In this case, the drag source is informed in the DragEnd event that a + * DROP_TARGET_MOVE was performed. It is the responsibility of the drag source at this point to clean + * up its displayed information. No action needs to be taken on the operating system resources.

    + * + *

    The following example shows a Label widget that allows text to be dragged from it.

    + * + *
    + *	// Enable a label as a Drag Source
    + *	Label label = new Label(shell, SWT.NONE);
    + *	// This example will allow text to be dragged
    + *	Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
    + *	// This example will allow the text to be copied or moved to the drop target
    + *	int operations = DND.DROP_MOVE | DND.DROP_COPY;
    + *
    + *	DragSource source = new DragSource(label, operations);
    + *	source.setTransfer(types);
    + *	source.addDragListener(new DragSourceListener() {
    + *		public void dragStart(DragSourceEvent e) {
    + *			// Only start the drag if there is actually text in the
    + *			// label - this text will be what is dropped on the target.
    + *			if (label.getText().length() == 0) {
    + *				event.doit = false;
    + *			}
    + *		};
    + *		public void dragSetData(DragSourceEvent event) {
    + *			// A drop has been performed, so provide the data of the
    + *			// requested type.
    + *			// (Checking the type of the requested data is only
    + *			// necessary if the drag source supports more than
    + *			// one data type but is shown here as an example).
    + *			if (TextTransfer.getInstance().isSupportedType(event.dataType)){
    + *				event.data = label.getText();
    + *			}
    + *		}
    + *		public void dragFinished(DragSourceEvent event) {
    + *			// A Move operation has been performed so remove the data
    + *			// from the source
    + *			if (event.detail == DND.DROP_MOVE)
    + *				label.setText("");
    + *		}
    + *	});
    + * 
    + * + * + *
    + *
    Styles
    DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
    + *
    Events
    DND.DragStart, DND.DragSetData, DND.DragEnd
    + *
    + */ +public class DragSource extends Widget { + + // info for registering as a drag source + Control control; + Listener controlListener; + Transfer[] transferAgents = new Transfer[0]; + DragAndDropEffect effect; +// Composite topControl; + + //workaround - track the operation performed by the drop target for DragEnd event + int dataEffect = DND.DROP_NONE; + + static final String DRAGSOURCEID = "DragSource"; //$NON-NLS-1$ +// static final int CFSTR_PERFORMEDDROPEFFECT = Transfer.registerType("Performed DropEffect"); //$NON-NLS-1$ + +/** + * Creates a new DragSource to handle dragging from the specified Control. + * Creating an instance of a DragSource may cause system resources to be allocated depending on the platform. + * It is therefore mandatory that the DragSource instance be disposed when no longer required. + * + * @param control the Control that the user clicks on to initiate the drag + * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of + * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * @exception SWTError
      + *
    • ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than one + * drag source is created for a control or if the operating system will not allow the creation + * of the drag source
    • + *
    + * + *

    NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a + * recoverable error, but can not be changed due to backward compatability.

    + * + * @see Widget#dispose + * @see DragSource#checkSubclass + * @see DND#DROP_NONE + * @see DND#DROP_COPY + * @see DND#DROP_MOVE + * @see DND#DROP_LINK + */ +public DragSource(Control control, int style) { + super(control, checkStyle(style)); + this.control = control; + if (control.getData(DRAGSOURCEID) != null) { + DND.error(DND.ERROR_CANNOT_INIT_DRAG); + } + control.setData(DRAGSOURCEID, this); + controlListener = event -> { + if (event.type == SWT.Dispose) { + if (!DragSource.this.isDisposed()) { + DragSource.this.dispose(); + } + } + }; + control.addListener(SWT.Dispose, controlListener); + control.addListener(SWT.DragDetect, controlListener); + this.addListener(SWT.Dispose, e -> DragSource.this.onDispose()); + boolean isPropertySet = true; + try { + System.setProperty("awt.dnd.drag.threshold", "0"); + Method method = Toolkit.class.getDeclaredMethod("setDesktopProperty", new Class[] {String.class, Object.class}); + method.setAccessible(true); + method.invoke(Toolkit.getDefaultToolkit(), new Object[] {"DnD.gestureMotionThreshold", new Integer(0)}); + method.setAccessible(false); + } catch(Throwable e) { + isPropertySet = false; + } + Container swingComponent = ((CControl)control.handle).getClientArea(); + // We need to be first to process the mouse event. + MouseListener[] mouseListeners = swingComponent.getMouseListeners(); + for(int i=0; iDragSourceListener + * interface. + * + *

      + *
    • dragStart is called when the user has begun the actions required to drag the widget. + * This event gives the application the chance to decide if a drag should be started. + *
    • dragSetData is called when the data is required from the drag source. + *
    • dragFinished is called when the drop has successfully completed (mouse up + * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup + * such as removing data from the source side on a successful move operation. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DragSourceListener + * @see #removeDragListener + * @see DragSourceEvent + */ +public void addDragListener(DragSourceListener listener) { + if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT); + DNDListener typedListener = new DNDListener(listener); + addListener(DND.DragStart, typedListener); + addListener(DND.DragSetData, typedListener); + addListener(DND.DragEnd, typedListener); +} + +@Override +protected void checkSubclass() { + String name = getClass().getName(); + String validName = DragSource.class.getName(); + if (!validName.equals(name)) { + DND.error(SWT.ERROR_INVALID_SUBCLASS); + } +} + +Image dragCursor; + + +/** + * Returns the Control which is registered for this DragSource. This is the control that the + * user clicks in to initiate dragging. + * + * @return the Control which is registered for this DragSource + */ +public Control getControl() { + return control; +} + +/** + * Returns the list of data types that can be transferred by this DragSource. + * + * @return the list of data types that can be transferred by this DragSource + */ +public Transfer[] getTransfer(){ + return transferAgents; +} + +private void onDispose() { + if (control == null) return; + if (controlListener != null){ + control.removeListener(SWT.Dispose, controlListener); + control.removeListener(SWT.DragDetect, controlListener); + } + controlListener = null; + control.setData(DRAGSOURCEID, null); + control = null; + transferAgents = null; + // TODO: release resources? +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when a drag and drop operation is in progress. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DragSourceListener + * @see #addDragListener + */ +public void removeDragListener(DragSourceListener listener) { + if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(DND.DragStart, listener); + removeListener(DND.DragSetData, listener); + removeListener(DND.DragEnd, listener); +} + +/** + * Specifies the list of data types that can be transferred by this DragSource. + * The application must be able to provide data to match each of these types when + * a successful drop has occurred. + * + * @param transferAgents a list of Transfer objects which define the types of data that can be + * dragged from this source + */ +public void setTransfer(Transfer[] transferAgents){ + this.transferAgents = transferAgents; +} + +class SWTDragGestureRecognizer extends MouseDragGestureRecognizer { + protected SWTDragGestureRecognizer(java.awt.dnd.DragSource dragsource, Component component, int actions, DragGestureListener draggesturelistener) { + super(dragsource, component, actions, draggesturelistener); + } + @Override +public void mouseClicked(MouseEvent e) { + } + @Override +public void mousePressed(MouseEvent e) { + events.clear(); + if(getDragAction(e) != 0) { + appendEvent(e); + } + } + @Override +public void mouseReleased(MouseEvent e) { + events.clear(); + } + @Override +public void mouseEntered(MouseEvent e) { + events.clear(); + } + @Override +public void mouseExited(MouseEvent e) { + if(!events.isEmpty()) { + int dragAction = getDragAction(e); + if(dragAction == 0) { + events.clear(); + } + } + } + @Override +public void mouseDragged(MouseEvent e) { + if(!events.isEmpty()) { + int dragAction = getDragAction(e); + if(dragAction == 0) { + return; + } +// MouseEvent me = (MouseEvent)events.get(0); +// Point p1 = e.getPoint(); +// Point p2 = me.getPoint(); +// int j = Math.abs(p2.x - p1.x); +// int k = Math.abs(p2.y - p1.y); +// if(j > 0 || k > 0) { + fireDragGestureRecognized(dragAction, ((MouseEvent)getTriggerEvent()).getPoint()); +// } else { +// appendEvent(e); +// } + } + } + @Override +public void mouseMoved(MouseEvent mouseevent) { + } + protected int getDragAction(MouseEvent e) { + int modifiers = e.getModifiersEx(); + if((modifiers & MouseEvent.BUTTON1_DOWN_MASK) == 0) { + return 0; + } + int dropAction = 0; + int sourceActions = getSourceActions(); + switch(modifiers & (MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK)) { + case MouseEvent.CTRL_DOWN_MASK: + dropAction = DnDConstants.ACTION_COPY; + break; + case MouseEvent.SHIFT_DOWN_MASK: + dropAction = DnDConstants.ACTION_MOVE; + break; + case MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK: + dropAction = DnDConstants.ACTION_LINK; + break; + default: + if((sourceActions & DnDConstants.ACTION_COPY) != 0) { + dropAction = DnDConstants.ACTION_COPY; + break; + } + if((sourceActions & DnDConstants.ACTION_MOVE) != 0) { + dropAction = DnDConstants.ACTION_MOVE; + break; + } + if((sourceActions & DnDConstants.ACTION_LINK) != 0) + dropAction = DnDConstants.ACTION_LINK; + break; + } + return dropAction & sourceActions; + } +} + +class SWTDragGestureListener implements DragGestureListener { + @Override +public void dragGestureRecognized(DragGestureEvent e) { + if (DragSource.this.isDisposed()) { + return; + } + java.awt.Point dragOrigin = e.getDragOrigin(); + DNDEvent event = new DNDEvent(); + event.widget = DragSource.this; + event.x = dragOrigin.x; + event.y = dragOrigin.y; + event.time = Utils.getCurrentTime(); + event.doit = true; + notifyListeners(DND.DragStart,event); + if (!event.doit || transferAgents == null || transferAgents.length == 0 ) return; + TransferData transferData = new TransferData(); + event = new DNDEvent(); + event.widget = DragSource.this; + event.time = Utils.getCurrentTime(); + event.dataType = transferData; + notifyListeners(DND.DragSetData,event); + // START - copy from clipboard + // TODO: refactor to share code? + ArrayList transferableList = new ArrayList(); + ArrayList flavorList = new ArrayList(); + for(int i=0; iDropTarget defines the target object for a drag and drop transfer. + * + * IMPORTANT: This class is not intended to be subclassed. + * + *

    This class identifies the Control over which the user must position the cursor + * in order to drop the data being transferred. It also specifies what data types can be dropped on + * this control and what operations can be performed. You may have several DropTragets in an + * application but there can only be a one to one mapping between a Control and a DropTarget. + * The DropTarget can receive data from within the same application or from other applications + * (such as text dragged from a text editor like Word).

    + * + *
    + *	int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
    + *	Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
    + *	DropTarget target = new DropTarget(label, operations);
    + *	target.setTransfer(types);
    + * 
    + * + *

    The application is notified of data being dragged over this control and of when a drop occurs by + * implementing the interface DropTargetListener which uses the class + * DropTargetEvent. The application can modify the type of drag being performed + * on this Control at any stage of the drag by modifying the event.detail field or the + * event.currentDataType field. When the data is dropped, it is the responsibility of + * the application to copy this data for its own purposes. + * + *

    + *	target.addDropListener (new DropTargetListener() {
    + *		public void dragEnter(DropTargetEvent event) {};
    + *		public void dragOver(DropTargetEvent event) {};
    + *		public void dragLeave(DropTargetEvent event) {};
    + *		public void dragOperationChanged(DropTargetEvent event) {};
    + *		public void dropAccept(DropTargetEvent event) {}
    + *		public void drop(DropTargetEvent event) {
    + *			// A drop has occurred, copy over the data
    + *			if (event.data == null) { // no data to copy, indicate failure in event.detail
    + *				event.detail = DND.DROP_NONE;
    + *				return;
    + *			}
    + *			label.setText ((String) event.data); // data copied to label text
    + *		}
    + * 	});
    + * 
    + * + *
    + *
    Styles
    DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
    + *
    Events
    DND.DragEnter, DND.DragLeave, DND.DragOver, DND.DragOperationChanged, + * DND.DropAccept, DND.Drop
    + *
    + */ +public class DropTarget extends Widget { + + Control control; + Listener controlListener; + Transfer[] transferAgents = new Transfer[0]; + DragAndDropEffect effect; + +// // Track application selections +// TransferData selectedDataType; +// int selectedOperation; + + static final String DROPTARGETID = "DropTarget"; //$NON-NLS-1$ + +/** + * Creates a new DropTarget to allow data to be dropped on the specified + * Control. + * Creating an instance of a DropTarget may cause system resources to be allocated + * depending on the platform. It is therefore mandatory that the DropTarget instance + * be disposed when no longer required. + * + * @param control the Control over which the user positions the cursor to drop the data + * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of + * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * @exception SWTError
      + *
    • ERROR_CANNOT_INIT_DROP - unable to initiate drop target; this will occur if more than one + * drop target is created for a control or if the operating system will not allow the creation + * of the drop target
    • + *
    + * + *

    NOTE: ERROR_CANNOT_INIT_DROP should be an SWTException, since it is a + * recoverable error, but can not be changed due to backward compatability.

    + * + * @see Widget#dispose + * @see DropTarget#checkSubclass + * @see DND#DROP_NONE + * @see DND#DROP_COPY + * @see DND#DROP_MOVE + * @see DND#DROP_LINK + */ +public DropTarget(Control control, int style) { + super (control, checkStyle(style)); + this.control = control; + if (control.getData(DROPTARGETID) != null) { + DND.error(DND.ERROR_CANNOT_INIT_DROP); + } + control.setData(DROPTARGETID, this); + controlListener = event -> { + if (!DropTarget.this.isDisposed()){ + DropTarget.this.dispose(); + } + }; + control.addListener (SWT.Dispose, controlListener); + this.addListener(SWT.Dispose, event -> onDispose()); + new java.awt.dnd.DropTarget(((CControl)control.handle).getSwingComponent(), Utils.convertDnDActionsToSwing(style), new java.awt.dnd.DropTargetListener() { + @Override + public void dragEnter(java.awt.dnd.DropTargetDragEvent e) { + lastAction = DND.DROP_DEFAULT; + processDropTargetDragEvent(e, DND.DragEnter); + } + @Override + public void dragOver(DropTargetDragEvent e) { + processDropTargetDragEvent(e, DND.DragOver); + } + @Override + public void dropActionChanged(DropTargetDragEvent e) { + processDropTargetDragEvent(e, DND.DragOperationChanged); + } + public void processDropTargetDragEvent(java.awt.dnd.DropTargetDragEvent e, int notificationType) { + DNDEvent event = new DNDEvent(); + if(setDragEventData(event, e)) { + int allowedOperations = event.operations; + notifyListeners(notificationType, event); + if(Utils.isLocalDragAndDropInProgress && !hasMetas()) { + lastAction = event.detail; + } + if (event.detail == DND.DROP_DEFAULT) { + event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; + } + int action = 0; + if ((allowedOperations & event.detail) != 0) { + action = Utils.convertDnDActionsToSwing(event.detail); + } + if(action == 0) { + e.rejectDrag(); + } else { + e.acceptDrag(action); + } + effect.showDropTargetEffect(event.feedback, event.x, event.y); + } else { + e.rejectDrag(); + } + } + @Override + public void dragExit(java.awt.dnd.DropTargetEvent e) { + DNDEvent event = new DNDEvent(); + event.widget = DropTarget.this; + event.time = Utils.getCurrentTime(); + event.detail = DND.DROP_NONE; + notifyListeners(DND.DragLeave, event); + } + @Override + public void drop(DropTargetDropEvent e) { + DNDEvent event = new DNDEvent(); + if(!setDropEventData(event, e)) { + e.rejectDrop(); + e.dropComplete(false); + } + int allowedOperations = event.operations; + int action = 0; + if (event.detail == DND.DROP_DEFAULT) { + event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; + } + if ((allowedOperations & event.detail) != 0) { + action = Utils.convertDnDActionsToSwing(event.detail); + } + if(action == 0) { + e.rejectDrop(); + e.dropComplete(true); + return; + } + // We accept the drop as a move, to be able to move the data if the user changes the detail of the event to a move. + boolean isLocalTransfer = e.isLocalTransfer(); + e.acceptDrop(isLocalTransfer? action: DnDConstants.ACTION_MOVE); + Object object = null; + for (int i = 0; i < transferAgents.length; i++){ + if (transferAgents[i].isSupportedType(event.dataType)) { + object = transferAgents[i].nativeToJava(event.dataType); + break; + } + } + if (object == null){ + event.detail = DND.DROP_NONE; + } + try { + event.data = object; + } catch(Exception ex) { + ex.printStackTrace(); + } + notifyListeners(DND.Drop, event); + // We validated the drop only if it is a move, so that the initiator deletes the data on its side. + if(event.detail == DND.DROP_MOVE) { + e.dropComplete(true); + } + effect.showDropTargetEffect(event.feedback, event.x, event.y); + } + }, true); + // Drag under effect +// if (control instanceof Tree) { +// effect = new TreeDragAndDropEffect((Tree)control); +// } else if (control instanceof Table) { +// effect = new TableDragAndDropEffect((Table)control); +// } else if (control instanceof StyledText) { +// effect = new StyledTextDragAndDropEffect((StyledText)control); +// } else { + effect = new NoDragAndDropEffect(control); +// } +} + +protected int lastAction; + +protected boolean hasMetas() { + return (Utils.modifiersEx & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0; +} + +boolean setDragEventData(DNDEvent event, java.awt.dnd.DropTargetDragEvent e) { + ArrayList transferDataList = new ArrayList(); + Transferable transferable = e.getTransferable(); + DataFlavor[] flavors = transferable.getTransferDataFlavors(); + for(int i=0; iDropTargetListener + * interface. + * + *

      + *
    • dragEnter is called when the cursor has entered the drop target boundaries + *
    • dragLeave is called when the cursor has left the drop target boundaries and just before + * the drop occurs or is cancelled. + *
    • dragOperationChanged is called when the operation being performed has changed + * (usually due to the user changing the selected modifier key(s) while dragging) + *
    • dragOver is called when the cursor is moving over the drop target + *
    • dropAccept is called just before the drop is performed. The drop target is given + * the chance to change the nature of the drop or veto the drop by setting the event.detail field + *
    • drop is called when the data is being dropped + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DropTargetListener + * @see #removeDropListener + * @see DropTargetEvent + */ +public void addDropListener(DropTargetListener listener) { + if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT); + DNDListener typedListener = new DNDListener (listener); + addListener (DND.DragEnter, typedListener); + addListener (DND.DragLeave, typedListener); + addListener (DND.DragOver, typedListener); + addListener (DND.DragOperationChanged, typedListener); + addListener (DND.Drop, typedListener); + addListener (DND.DropAccept, typedListener); +} + +@Override +protected void checkSubclass () { + String name = getClass().getName (); + String validName = DropTarget.class.getName(); + if (!validName.equals(name)) { + DND.error (SWT.ERROR_INVALID_SUBCLASS); + } +} + +/** + * Returns the Control which is registered for this DropTarget. This is the control over which the + * user positions the cursor to drop the data. + * + * @return the Control which is registered for this DropTarget + */ +public Control getControl () { + return control; +} + +/** + * Returns a list of the data types that can be transferred to this DropTarget. + * + * @return a list of the data types that can be transferred to this DropTarget + */ +public Transfer[] getTransfer() { + return transferAgents; +} + +void onDispose () { + if (control == null) return; + if (controlListener != null) + control.removeListener(SWT.Dispose, controlListener); + controlListener = null; + control.setData(DROPTARGETID, null); + transferAgents = null; + control = null; + // TODO: release resources? +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when a drag and drop operation is in progress. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DropTargetListener + * @see #addDropListener + */ +public void removeDropListener(DropTargetListener listener) { + if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT); + removeListener (DND.DragEnter, listener); + removeListener (DND.DragLeave, listener); + removeListener (DND.DragOver, listener); + removeListener (DND.DragOperationChanged, listener); + removeListener (DND.Drop, listener); + removeListener (DND.DropAccept, listener); +} + +/** + * Specifies the data types that can be transferred to this DropTarget. If data is + * being dragged that does not match one of these types, the drop target will be notified of + * the drag and drop operation but the currentDataType will be null and the operation + * will be DND.NONE. + * + * @param transferAgents a list of Transfer objects which define the types of data that can be + * dropped on this target + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if transferAgents is null
    • + *
    + */ +public void setTransfer(Transfer[] transferAgents){ + if (transferAgents == null) DND.error(SWT.ERROR_NULL_ARGUMENT); + this.transferAgents = transferAgents; +} + +public DropTargetEffect getDropTargetEffect() { + throw new UnsupportedOperationException("Not implemented yet"); +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java new file mode 100644 index 00000000000..d0215950d16 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * The class FileTransfer provides a platform specific mechanism + * for converting a list of files represented as a java String[] to a + * platform specific representation of the data and vice versa. + * Each String in the array contains the absolute path for a single + * file or directory. + * See Transfer for additional information. + * + *

    An example of a java String[] containing a list of files is shown + * below:

    + * + *
    + *     File file1 = new File("C:\temp\file1");
    + *     File file2 = new File("C:\temp\file2");
    + *     String[] fileData = new String[2];
    + *     fileData[0] = file1.getAbsolutePath();
    + *     fileData[1] = file2.getAbsolutePath();
    + * 
    + */ +public class FileTransfer extends ByteArrayTransfer { + + private static FileTransfer _instance = new FileTransfer(); + +private FileTransfer() {} + +/** + * Returns the singleton instance of the FileTransfer class. + * + * @return the singleton instance of the FileTransfer class + */ +public static FileTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts a list of file names + * represented by a java String[] to a platform specific representation. + * Each String in the array contains the absolute path for a single + * file or directory. For additional information see + * Transfer#javaToNative. + * + * @param object a java String[] containing the file names to be + * converted + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative(Object object, TransferData transferData) { + if (!checkFile(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + String[] fileNames = (String[]) object; + final List fileList = new ArrayList(fileNames.length); + for(int i=0; inativeToJava converts a platform specific + * representation of a list of file names to a java String[]. + * Each String in the array contains the absolute path for a single file or directory. + * For additional information see Transfer#nativeToJava. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java String[] containing a list of file names if the + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData) { + if (!isSupportedType(transferData) || transferData.transferable == null) return null; + List fileList = (List)super.nativeToJava(transferData); + File[] files = (File[])fileList.toArray(new File[0]); + String[] fileNames = new String[files.length]; + for(int i=0; iHTMLTransfer provides a platform specific mechanism + * for converting text in HTML format represented as a java String + * to a platform specific representation of the data and vice versa. See + * Transfer for additional information. + * + *

    An example of a java String containing HTML text is shown + * below:

    + * + *
    + *     String htmlData = "

    This is a paragraph of text.

    "; + *
    + */ +public class HTMLTransfer extends Transfer { + +private static HTMLTransfer _instance = new HTMLTransfer(); + +private HTMLTransfer() {} + +/** + * Returns the singleton instance of the HTMLTransfer class. + * + * @return the singleton instance of the HTMLTransfer class + */ +public static HTMLTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts HTML-formatted text + * represented by a java String to a platform specific representation. + * For additional information see Transfer#javaToNative. + * + * @param object a java String containing HTML text + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative (Object object, TransferData transferData){ + if (!checkHTML(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + transferData.transferable = new StringSelection((String)object); +} + +/** + * This implementation of nativeToJava converts a platform specific + * representation of HTML text to a java String. + * For additional information see Transfer#nativeToJava. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java String containing HTML text if the + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData){ + Object o = super.nativeToJava(transferData); + if(o instanceof Reader) { + StringBuilder sb = new StringBuilder(); + Reader reader = (Reader)o; + char[] chars = new char[128]; + try { + for(int i; (i=reader.read(chars)) != -1; ) { + sb.append(chars, 0, i); + } + } catch(Exception e) { + e.printStackTrace(); + } + return sb.toString(); + } + return o; +} + +boolean checkHTML(Object object) { + return (object != null && object instanceof String && ((String)object).length() > 0); +} + +protected boolean validate(Object object) { + return checkHTML(object); +} + +static DataFlavor HTML_FLAVOR_1 = new DataFlavor("text/html; class=java.lang.String", "HTML Text"); +//static DataFlavor HTML_FLAVOR_2 = new DataFlavor("text/html; class=java.io.Reader", "HTML Text"); + +public TransferData[] getSupportedTypes() { + TransferData data1 = new TransferData(); + data1.dataFlavor = HTML_FLAVOR_1; + return new TransferData[] {data1}; +// TransferData data2 = new TransferData(); +// data2.dataFlavor = HTML_FLAVOR_2; +// return new TransferData[] {data1, data2}; +} + +protected DataFlavor getDataFlavor() { + return HTML_FLAVOR_1; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java new file mode 100644 index 00000000000..07e96a18ba3 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java @@ -0,0 +1,11 @@ +package org.eclipse.swt.dnd; + +import org.eclipse.swt.widgets.*; + +public class NoDragAndDropEffect extends DragAndDropEffect { + + public NoDragAndDropEffect(Control control) { + // TODO Auto-generated constructor stub + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java new file mode 100644 index 00000000000..f619b35825c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * The class RTFTransfer provides a platform specific mechanism + * for converting text in RTF format represented as a java String + * to a platform specific representation of the data and vice versa. See + * Transfer for additional information. + * + *

    An example of a java String containing RTF text is shown + * below:

    + * + *
    + *     String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
    + * 
    + */ +public class RTFTransfer extends Transfer { + +private static RTFTransfer _instance = new RTFTransfer(); + +private RTFTransfer() {} + +/** + * Returns the singleton instance of the RTFTransfer class. + * + * @return the singleton instance of the RTFTransfer class + */ +public static RTFTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts RTF-formatted text + * represented by a java String to a platform specific representation. + * For additional information see Transfer#javaToNative. + * + * @param object a java String containing RTF text + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative (final Object object, TransferData transferData){ + if (!checkRTF(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + transferData.transferable = new Transferable() { + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if(!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + return new ByteArrayInputStream(((String)object).getBytes()); + } + public boolean isDataFlavorSupported(DataFlavor flavor) { + return getDataFlavor().equals(flavor); + } + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] {getDataFlavor()}; + } + }; +} + +/** + * This implementation of nativeToJava converts a platform specific + * representation of RTF text to a java String. + * For additional information see Transfer#nativeToJava. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java String containing RTF text if the + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData){ + if (!isSupportedType(transferData) || transferData.transferable == null) return null; + InputStreamReader reader = new InputStreamReader((ByteArrayInputStream)super.nativeToJava(transferData)); + StringBuilder sb = new StringBuilder(); + char[] chars = new char[128]; + try { + for(int i; (i=reader.read(chars)) != -1; ) { + sb.append(chars, 0, i); + } + } catch(Exception e) { + e.printStackTrace(); + } + return sb.toString(); +} + +boolean checkRTF(Object object) { + return (object != null && object instanceof String && ((String)object).length() > 0); +} + +protected boolean validate(Object object) { + return checkRTF(object); +} + +static DataFlavor RTF_FLAVOR = new DataFlavor("text/rtf", "RTF Text"); + +public TransferData[] getSupportedTypes() { + TransferData data = new TransferData(); + data.dataFlavor = RTF_FLAVOR; + return new TransferData[] {data}; +} + +protected DataFlavor getDataFlavor() { + return RTF_FLAVOR; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java new file mode 100644 index 00000000000..14158e2f743 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; + +/** + * The class TextTransfer provides a platform specific mechanism + * for converting plain text represented as a java String + * to a platform specific representation of the data and vice versa. + * + *

    An example of a java String containing plain text is shown + * below:

    + * + *
    + *     String textData = "Hello World";
    + * 
    + * + * @see Transfer + */ +public class TextTransfer extends Transfer { + +private static TextTransfer _instance = new TextTransfer(); + +private TextTransfer() {} + +/** + * Returns the singleton instance of the TextTransfer class. + * + * @return the singleton instance of the TextTransfer class + */ +public static TextTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts plain text + * represented by a java String to a platform specific representation. + * + * @param object a java String containing text + * @param transferData an empty TransferData object; this object + * will be filled in on return with the platform specific format of the data + * + * @see Transfer#javaToNative + */ +public void javaToNative (Object object, TransferData transferData){ + if (!checkText(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + transferData.transferable = new StringSelection((String)object); +} + +/** + * This implementation of nativeToJava converts a platform specific + * representation of plain text to a java String. + * + * @param transferData the platform specific representation of the data to be converted + * @return a java String containing text if the conversion was successful; otherwise null + * + * @see Transfer#nativeToJava + */ +public Object nativeToJava(TransferData transferData){ + return super.nativeToJava(transferData); +} + +boolean checkText(Object object) { + return (object != null && object instanceof String && ((String)object).length() > 0); +} + +protected boolean validate(Object object) { + return checkText(object); +} + +public TransferData[] getSupportedTypes() { + TransferData data = new TransferData(); + data.dataFlavor = DataFlavor.stringFlavor; + return new TransferData[] {data}; +} + +protected DataFlavor getDataFlavor() { + return DataFlavor.stringFlavor; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java new file mode 100644 index 00000000000..34fecc0973b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +/** + * Transfer provides a mechanism for converting between a java + * representation of data and a platform specific representation of data and + * vice versa. It is used in data transfer operations such as drag and drop and + * clipboard copy/paste. + * + *

    You should only need to become familiar with this class if you are + * implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.

    + * + * @see ByteArrayTransfer + */ +public abstract class Transfer { + +abstract protected DataFlavor getDataFlavor(); + +/** + * Returns a list of the platform specific data types that can be converted using + * this transfer agent. + * + *

    Only the dataFlavor fields of the TransferData objects are filled + * in.

    + * + * @return a list of the data types that can be converted using this transfer agent + */ +abstract public TransferData[] getSupportedTypes(); + +/** + * Returns true if the TransferData data type can be converted + * using this transfer agent, or false otherwise (including if transferData is + * null). + * + * @param transferData a platform specific description of a data type; only the + * dataFlavor fields of the TransferData object need to be filled in. + * + * @return true if the transferData data type can be converted using this transfer + * agent + */ +public boolean isSupportedType(TransferData transferData) { + TransferData[] types = getSupportedTypes(); + for(int i=0; iOn a successful conversion, the transferData.result field will be set as follows: + *
      + *
    • Windows: COM.S_OK + *
    • Motif: 1 + *
    • GTK: 1 + *
    • Photon: 1 + *

    + * + *

    If this transfer agent is unable to perform the conversion, the transferData.result + * field will be set to a failure value as follows: + *

      + *
    • Windows: COM.DV_E_TYMED or COM.E_FAIL + *
    • Motif: 0 + *
    • GTK: 0 + *
    • Photon: 0 + *

    + * + * @param object a java representation of the data to be converted; the type of + * Object that is passed in is dependant on the Transfer subclass. + * + * @param transferData an empty TransferData object; this object will be + * filled in on return with the platform specific representation of the data + * + * @exception org.eclipse.swt.SWTException
      + *
    • ERROR_INVALID_DATA - if object does not contain data in a valid format or is null
    • + *
    + */ +abstract protected void javaToNative (Object object, TransferData transferData); + +/** + * Converts a platform specific representation of data to a java representation. + * + * @param transferData the platform specific representation of the data to be + * converted + * + * @return a java representation of the converted data if the conversion was + * successful; otherwise null. If transferData is null then + * null is returned. The type of Object that is returned is + * dependant on the Transfer subclass. + */ +protected Object nativeToJava(TransferData transferData){ + if (!isSupportedType(transferData) || transferData.transferable == null) return null; + try { + return transferData.transferable.getTransferData(getDataFlavor()); + } catch(UnsupportedFlavorException e) { + } catch(IOException e) {} + return null; +} + +/** + * Registers a name for a data type and returns the associated unique identifier. + * + *

    You may register the same type more than once, the same unique identifier + * will be returned if the type has been previously registered.

    + * + *

    Note: On windows, do not call this method with pre-defined + * Clipboard Format types such as CF_TEXT or CF_BITMAP because the + * pre-defined identifier will not be returned

    + * + * @param formatName the name of a data type + * + * @return the unique identifier associated with this data type + */ +public static int registerType(String formatName) { + return getTypeID(formatName); +} + +static int getTypeID(String formatName) { + // copied from the Carbon's port Transfer class + int length = formatName.length(); + // TODO - hashcode may not be unique - need another way + if (length > 4) return formatName.hashCode(); + int type = 0; + if (length > 0) type |= (formatName.charAt(0) & 0xff) << 24; + if (length > 1) type |= (formatName.charAt(1) & 0xff) << 16; + if (length > 2) type |= (formatName.charAt(2) & 0xff) << 8; + if (length > 3) type |= formatName.charAt(3) & 0xff; + return type; +} + +/** + * Test that the object is of the correct format for this Transfer class. + * + * @param object a java representation of the data to be converted + * + * @return true if object is of the correct form for this transfer type + * + * @since 3.1 + */ +protected boolean validate(Object object) { + return true; +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java new file mode 100644 index 00000000000..27b029ab4e8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.*; + +/** + * The TransferData class is a platform specific data structure for + * describing the type and the contents of data being converted by a transfer agent. + * + *

    As an application writer, you do not need to know the specifics of + * TransferData. TransferData instances are passed to a subclass of Transfer + * and the Transfer object manages the platform specific issues. + * You can ask a Transfer subclass if it can handle this data by calling + * Transfer.isSupportedType(transferData).

    + * + *

    You should only need to become familiar with the fields in this class if you + * are implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.

    + */ +public class TransferData { + /** + * The dataFlavor is a unique identifier of a system format or user defined format. + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public DataFlavor dataFlavor; + + /** + * The transferable is a unique identifier of a system format or user defined format. + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public Transferable transferable; + + /** + * The type is a unique identifier of a system format or user defined format. + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + * + * @noreference This field is not intended to be referenced by clients. + */ + public int type; + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java new file mode 100644 index 00000000000..fad26cacd13 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.net.URL; + +/** + * The class URLTransfer provides a platform specific mechanism + * for converting text in URL format represented as a java String[] + * to a platform specific representation of the data and vice versa. See + * Transfer for additional information. The first string in the + * array is mandatory and must contain the fully specified url. The second + * string in the array is optional and if present contains the title for the + * page. + * + *

    An example of a java String[] containing a URL is shown + * below:

    + * + *
    + *     String[] urlData = new String[] {"http://www.eclipse.org", "Eclipse.org Main Page"};
    + * 
    + */ +public class URLTransfer extends Transfer { + +private static URLTransfer _instance = new URLTransfer(); + +private URLTransfer() {} + +/** + * Returns the singleton instance of the URLTransfer class. + * + * @return the singleton instance of the URLTransfer class + */ +public static URLTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts a URL and optionally a title + * represented by a java String[] to a platform specific representation. + * For additional information see Transfer#javaToNative. + * + * @param object a java String[] containing a URL and optionally, a title + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative (Object object, TransferData transferData) { + if (!checkURL(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + String s = ((String[])object)[0]; + if(!s.endsWith("\r\n")) { + if(s.endsWith("\n")) { + s = s.substring(0, s.length() - 1) + "\r\n"; + } else if(s.endsWith("\r")) { + s += "\n"; + } + } + transferData.transferable = new StringSelection(s); +} + +/** + * This implementation of nativeToJava converts a platform specific + * representation of a URL and optionally, a title to a java String[]. + * For additional information see Transfer#nativeToJava. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java String[] containing a URL and optionally a title if the + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData){ + String s = (String)super.nativeToJava(transferData); + if(s.endsWith("\n")) { + s = s.substring(0, s.length() - 1); + } + if(s.endsWith("\r")) { + s = s.substring(0, s.length() - 1); + } + return new String[] {s, null}; +} + +boolean checkURL(Object object) { + if (object == null || !(object instanceof String[]) || ((String[])object).length == 0) return false; + String[] strings = (String[])object; + if (strings[0] == null || strings[0].length() == 0) return false; + try { + new URL(strings[0]); + } catch (java.net.MalformedURLException e) { + return false; + } + return true; +} + +static DataFlavor URL_FLAVOR = new DataFlavor("text/uri-list; class=java.lang.String", "URI list"); + +protected boolean validate(Object object) { + return checkURL(object); +} + +public TransferData[] getSupportedTypes() { + TransferData data = new TransferData(); + data.dataFlavor = URL_FLAVOR; + return new TransferData[] {data}; +} + +protected DataFlavor getDataFlavor() { + return URL_FLAVOR; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT OpenGL/common/org/eclipse/swt/opengl/GLData.java b/bundles/org.eclipse.swt/Eclipse SWT OpenGL/common/org/eclipse/swt/opengl/GLData.java index 5a5ecc7addb..7deeeaa3fe8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT OpenGL/common/org/eclipse/swt/opengl/GLData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT OpenGL/common/org/eclipse/swt/opengl/GLData.java @@ -25,127 +25,127 @@ */ public class GLData { - /** - * Specifies a double-buffered surface. During context - * creation, only double-buffered formats are considered - * when set to true. - */ - public boolean doubleBuffer; - - /** - * Specifies a stereo surface. During context creation, - * only stereo formats are considered when set to true. - */ - public boolean stereo; - - /** - * The size in bits of the color buffer's red channel. - * During context creation, this specifies the minimum - * required red bits. - */ - public int redSize; - - /** - * The size in bits of the color buffer's green channel. - * During context creation, this specifies the minimum - * required green bits. - */ - public int greenSize; - - /** - * The size in bits of the color buffer's blue channel. - * During context creation, this specifies the minimum - * required blue bits. - */ - public int blueSize; - - /** - * The size in bits of the color buffer's alpha channel. - * During context creation, this specifies the minimum - * required alpha bits. - */ - public int alphaSize; - - /** - * The size in bits of the depth buffer. During context - * creation, the smallest depth buffer of at least the - * specified value is preferred, or zero for no depth - * buffer. - */ - public int depthSize; - - /** - * The desired number of stencil bitplanes. During - * context creation, the smallest stencil buffer of at - * least the specified value is preferred, or zero for - * no stencil buffer. - */ - public int stencilSize; - - /** - * The size in bits of the accumulation buffer's red - * channel. During context creation, this specifies the - * minimum required red bits. - */ - public int accumRedSize; - - /** - * The size in bits of the accumulation buffer's green - * channel. During context creation, this specifies the - * minimum required green bits. - */ - public int accumGreenSize; - - /** - * The size in bits of the accumulation buffer's blue - * channel. During context creation, this specifies the - * minimum required blue bits. - */ - public int accumBlueSize; - - /** - * The size in bits of the accumulation buffer's alpha - * channel. During context creation, this specifies the - * minimum required alpha bits. - */ - public int accumAlphaSize; - - /** - * The number of multisample buffers used by this context. - * During context creation, this specifies the minimum - * number of multisample buffers requested. - */ - public int sampleBuffers; - - /** - * The number of samples accepted in the multisample buffer. - * During creation, pixel formats with the smallest number of - * samples that meets or exceeds the specified minimum number - * are preferred. - */ - public int samples; - - /** - * Another GLCanvas whose texture namespace and display lists - * should be shared. - * - * @since 3.5 - */ - public GLCanvas shareContext; - -/** - * Returns a string containing a concise, human-readable - * description of the receiver. - * - * @return a string representation of the data - */ -@Override -public String toString() { - return (doubleBuffer ? "doubleBuffer," : "") + - (stereo ? "stereo," : "") + - "r:" + redSize + " g:" + greenSize + " b:" + blueSize + " a:" + alphaSize + "," + - "depth:" + depthSize + ",stencil:" + stencilSize + - ",accum r:" + accumRedSize + "g:" + accumGreenSize + "b:" + accumBlueSize + "a:" + accumAlphaSize + - ",sampleBuffers:" + sampleBuffers + ",samples:" + samples; -} +// /** +// * Specifies a double-buffered surface. During context +// * creation, only double-buffered formats are considered +// * when set to true. +// */ +// public boolean doubleBuffer; +// +// /** +// * Specifies a stereo surface. During context creation, +// * only stereo formats are considered when set to true. +// */ +// public boolean stereo; +// +// /** +// * The size in bits of the color buffer's red channel. +// * During context creation, this specifies the minimum +// * required red bits. +// */ +// public int redSize; +// +// /** +// * The size in bits of the color buffer's green channel. +// * During context creation, this specifies the minimum +// * required green bits. +// */ +// public int greenSize; +// +// /** +// * The size in bits of the color buffer's blue channel. +// * During context creation, this specifies the minimum +// * required blue bits. +// */ +// public int blueSize; +// +// /** +// * The size in bits of the color buffer's alpha channel. +// * During context creation, this specifies the minimum +// * required alpha bits. +// */ +// public int alphaSize; +// +// /** +// * The size in bits of the depth buffer. During context +// * creation, the smallest depth buffer of at least the +// * specified value is preferred, or zero for no depth +// * buffer. +// */ +// public int depthSize; +// +// /** +// * The desired number of stencil bitplanes. During +// * context creation, the smallest stencil buffer of at +// * least the specified value is preferred, or zero for +// * no stencil buffer. +// */ +// public int stencilSize; +// +// /** +// * The size in bits of the accumulation buffer's red +// * channel. During context creation, this specifies the +// * minimum required red bits. +// */ +// public int accumRedSize; +// +// /** +// * The size in bits of the accumulation buffer's green +// * channel. During context creation, this specifies the +// * minimum required green bits. +// */ +// public int accumGreenSize; +// +// /** +// * The size in bits of the accumulation buffer's blue +// * channel. During context creation, this specifies the +// * minimum required blue bits. +// */ +// public int accumBlueSize; +// +// /** +// * The size in bits of the accumulation buffer's alpha +// * channel. During context creation, this specifies the +// * minimum required alpha bits. +// */ +// public int accumAlphaSize; +// +// /** +// * The number of multisample buffers used by this context. +// * During context creation, this specifies the minimum +// * number of multisample buffers requested. +// */ +// public int sampleBuffers; +// +// /** +// * The number of samples accepted in the multisample buffer. +// * During creation, pixel formats with the smallest number of +// * samples that meets or exceeds the specified minimum number +// * are preferred. +// */ +// public int samples; +// +// /** +// * Another GLCanvas whose texture namespace and display lists +// * should be shared. +// * +// * @since 3.5 +// */ +// public GLCanvas shareContext; +// +///** +// * Returns a string containing a concise, human-readable +// * description of the receiver. +// * +// * @return a string representation of the data +// */ +//@Override +//public String toString() { +// return (doubleBuffer ? "doubleBuffer," : "") + +// (stereo ? "stereo," : "") + +// "r:" + redSize + " g:" + greenSize + " b:" + blueSize + " a:" + alphaSize + "," + +// "depth:" + depthSize + ",stencil:" + stencilSize + +// ",accum r:" + accumRedSize + "g:" + accumGreenSize + "b:" + accumBlueSize + "a:" + accumAlphaSize + +// ",sampleBuffers:" + sampleBuffers + ",samples:" + samples; +//} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/Platform.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/Platform.java new file mode 100644 index 00000000000..c9f7c04e00d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/Platform.java @@ -0,0 +1,11 @@ +package org.eclipse.swt.internal; + +public class Platform { + + public static final String PLATFORM = "swing"; + + public static boolean isLoadable() { + return Library.isLoadable(); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ArrowButton.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ArrowButton.java new file mode 100644 index 00000000000..fc4dccd91aa --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ArrowButton.java @@ -0,0 +1,87 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.basic.BasicArrowButton; +import javax.swing.plaf.metal.MetalScrollButton; + +/** + * An arrow button. + * @version 1.0 2003.08.03 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public class ArrowButton extends BasicArrowButton { + + protected BasicArrowButton arrowButton; + + /** + * Construct an arrow button using the current look and feel. + * @param direction the direction of the arrow. + */ + public ArrowButton(int direction) { + super(direction); + setBorder(LookAndFeelUtils.getButtonBorder()); + createArrowButton(); + } + + public void paint(Graphics g) { + if(arrowButton != null) { + Dimension size = getSize(); + arrowButton.setSize(size); + arrowButton.paint(g); + } else { + super.paint(g); + } + } + + /** + * Set the direction the arrow is pointing to. + * @param direction The direction of the arrow. + */ + public void setDirection(int direction) { + if(direction == getDirection()) { + return; + } + super.setDirection(direction); + createArrowButton(); + repaint(); + } + + protected void createArrowButton() { + // Scroll bar buttons are not always applicable... so we need an external parameter if the default behavior is not right. + Boolean isNotCreating = Utils.isUsingDefaultArrowButtons(); + if(isNotCreating != null && isNotCreating.booleanValue()) { + return; + } + arrowButton = null; + setPreferredSize(null); + JComponent component = new JScrollBar(); + Component[] components = component.getComponents(); + for(int i=0; i getEditorTextLimit()) { + return; + } + super.replace(fb, offset, length, text, attrs); + } +// public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { +// } + }); +// list.addItemListener(new ItemListener() { +// public void itemStateChanged(ItemEvent e) { +// handle.processEvent(e); +// } +// }); + } + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + textField.setEnabled(enabled); + list.setEnabled(enabled); + } + + public JScrollBar getHorizontalScrollBar() { + // TODO: implement + return null; + } + + public JScrollBar getVerticalScrollBar() { + // TODO: implement + return null; + } + + public Container getClientArea() { + return this; + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: { + setOpaque(true); + textField.setOpaque(true); + list.setOpaque(true); + scrollPane.setOpaque(true); + scrollPane.getViewport().setOpaque(true); + break; + } + case BACKGROUND_INHERITANCE: { + setOpaque(false); + textField.setOpaque(false); + list.setOpaque(false); + scrollPane.setOpaque(false); + scrollPane.getViewport().setOpaque(false); + break; + } + } + } + + public void addItem(Object o) { + ((DefaultListModel)list.getModel()).addElement(o); + } + + public Object getItemAt(int index) { + return list.getModel().getElementAt(index); + } + + public void removeItemAt(int index) { + ((DefaultListModel)list.getModel()).remove(index); + } + + public void removeAllItems() { + ((DefaultListModel)list.getModel()).removeAllElements(); + } + + public void insertElementAt(Object o, int index) { + ((DefaultListModel)list.getModel()).add(index, o); + } + + public int getItemCount() { + return list.getModel().getSize(); + } + + public int getSelectedIndex() { + return list.getSelectedIndex(); + } + + public void setSelectedIndex(int index) { + Object item = list.getModel().getElementAt(index); + if(item != null) { + list.setSelectedIndex(index); + } + } + + public int getMaximumRowCount() { + return list.getVisibleRowCount(); + } + + public void setMaximumRowCount(int count) { + // Do nothing? + } + + public String getEditorText() { + return textField.getText(); + } + + public void setEditorText(String text) { + textField.setText(text); + } + + public void copyEditor() { + textField.copy(); + } + + public void cutEditor() { + textField.cut(); + } + + public void pasteEditor() { + textField.paste(); + } + + public void setEditorCaretPosition(int index) { + textField.setCaretPosition(index); + } + + public int getEditorSelectionStart() { + return textField.getSelectionStart(); + } + + public void setEditorSelectionStart(int selectionStart) { + textField.setSelectionStart(selectionStart); + } + + public int getEditorSelectionEnd() { + return textField.getSelectionEnd(); + } + + public void setEditorSelectionEnd(int selectionEnd) { + textField.setSelectionEnd(selectionEnd); + } + + public void clearEditorSelection() { + textField.setSelectionStart(textField.getSelectionEnd()); + } + + public void setEditorTextLimit(int limit) { + textLimit = limit; + String text = getEditorText(); + if(text.length() > limit) { + setEditorText(text.substring(0, limit)); + } + } + + protected int textLimit = Combo.LIMIT; + + public int getEditorTextLimit() { + return textLimit; + } + + public Dimension getEditorSize() { + return textField.getSize(); + } + + public boolean isPopupVisible() { + return false; + } + +} + +class CComboImplementation extends JComboBox implements CCombo { + + protected Combo handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CComboImplementation(Combo combo, int style) { + this.handle = combo; + userAttributeHandler = new UserAttributeHandler(this); + setLightWeightPopupEnabled(Utils.isLightweightPopups()); + init(style); + } + + protected boolean isDefaultButtonHackActive; + + public boolean isPopupVisible() { + boolean isPopupVisible = super.isPopupVisible(); + if(!isPopupVisible) { + return isDefaultButtonHackActive; + } + return isPopupVisible; + } + + protected void init(int style) { + setEditable((style & SWT.READ_ONLY) == 0); + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + JTextField textField = (JTextField)getEditor().getEditorComponent(); + // We put a listener before and after all existing listeners to place and remove the hack + // The hack is there because the combo notifies the default button of the rootpane when its popup is not visible + ActionListener[] actionListeners = textField.getActionListeners(); + for(int i=actionListeners.length-1; i>=0; i--) { + textField.removeActionListener(actionListeners[i]); + } + textField.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + isDefaultButtonHackActive = false; + } + }); + for(int i=0; i getEditorTextLimit()) { + return; + } + super.replace(fb, offset, length, text, attrs); + } +// public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { +// } + }); + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + handle.processEvent(e); + } + }); + } + + public JScrollBar getHorizontalScrollBar() { + // TODO: implement + return null; + } + + public JScrollBar getVerticalScrollBar() { + // TODO: implement + return null; + } + + public Container getClientArea() { + return this; + } + + public void insertElementAt(Object anObject, int index) { + ((DefaultComboBoxModel)getModel()).insertElementAt(anObject, index); + } + + public String getEditorText() { + Object selectedItem = getSelectedItem(); + return selectedItem == null? "": String.valueOf(selectedItem); +// return ((JTextComponent)getEditor().getEditorComponent()).getText(); + } + + public void setEditorText(String text) { + setSelectedItem(text); +// ((JTextComponent)getEditor().getEditorComponent()).setText(text); + } + + public void copyEditor() { + ((JTextComponent)getEditor().getEditorComponent()).copy(); + } + + public void cutEditor() { + ((JTextComponent)getEditor().getEditorComponent()).cut(); + } + + public void pasteEditor() { + ((JTextComponent)getEditor().getEditorComponent()).paste(); + } + + public void setEditorCaretPosition(int index) { + ((JTextComponent)getEditor().getEditorComponent()).setCaretPosition(index); + } + + public int getEditorSelectionStart() { + return ((JTextComponent)getEditor().getEditorComponent()).getSelectionStart(); + } + + public void setEditorSelectionStart(int selectionStart) { + ((JTextComponent)getEditor().getEditorComponent()).setSelectionStart(selectionStart); + } + + public int getEditorSelectionEnd() { + return ((JTextComponent)getEditor().getEditorComponent()).getSelectionEnd(); + } + + public void setEditorSelectionEnd(int selectionEnd) { + ((JTextComponent)getEditor().getEditorComponent()).setSelectionEnd(selectionEnd); + } + + public void clearEditorSelection() { + JTextComponent textComponent = (JTextComponent)getEditor().getEditorComponent(); + textComponent.setSelectionStart(textComponent.getSelectionEnd()); + } + + public void setEditorTextLimit(int limit) { + textLimit = limit; + String text = getEditorText(); + if(text.length() > limit) { + setEditorText(text.substring(0, limit)); + } + } + + protected int textLimit = Combo.LIMIT; + + public int getEditorTextLimit() { + return textLimit; + } + + public Dimension getEditorSize() { + return ((JTextComponent)getEditor().getEditorComponent()).getSize(); + } + + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, getPreferredSize().height); + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: { + setOpaque(true); + ((JComponent)getEditor().getEditorComponent()).setOpaque(true); + break; + } + case BACKGROUND_INHERITANCE: { + setOpaque(false); + ((JComponent)getEditor().getEditorComponent()).setOpaque(false); + break; + } + } + } + +} + +public interface CCombo extends CComposite { + + public static class Factory { + private Factory() {} + + public static CCombo newInstance(Combo combo, int style) { + if ((style & SWT.SIMPLE) != 0) { + return new CComboSimple(combo, style); + } + return new CComboImplementation(combo, style); + } + + } + + public void addItem(Object anObject); + + public Object getItemAt(int index); + + public void removeItemAt(int anIndex); + + public void removeAllItems(); + + public void insertElementAt(Object anObject, int index); + + public int getItemCount(); + + public int getSelectedIndex(); + + public void setSelectedIndex(int index); + + public int getMaximumRowCount(); + + public void setMaximumRowCount(int count); + + public void setComponentOrientation(ComponentOrientation o); + + public String getEditorText(); + + public void setEditorText(String text); + + public void copyEditor(); + + public void cutEditor(); + + public void pasteEditor(); + + public void setEditorCaretPosition(int index); + + public int getEditorSelectionStart(); + + public void setEditorSelectionStart(int selectionStart); + + public int getEditorSelectionEnd(); + + public void setEditorSelectionEnd(int selectionEnd); + + public void clearEditorSelection(); + + public void setEditorTextLimit(int limit); + + public int getEditorTextLimit(); + + public Dimension getEditorSize(); + + public boolean isPopupVisible(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComboButton.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComboButton.java new file mode 100644 index 00000000000..25c5b134735 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComboButton.java @@ -0,0 +1,150 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +import javax.swing.BorderFactory; +import javax.swing.DefaultButtonModel; +import javax.swing.JButton; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputAdapter; + +public class CComboButton extends JButton implements SwingConstants { + + private static final int ARROW_SPACE_WIDTH = 7; + private static final int ARROW_WIDTH = 5; + + protected MouseInputAdapter mouseHandler = new MouseInputAdapter() { + public void mouseExited(MouseEvent e) { + isMouseOver = false; + isArrowMouseOver = false; + repaint(); + } + public void mouseEntered(MouseEvent e) { + isMouseOver = true; + processMouseEvent(e); + repaint(); + } + public void mouseMoved(MouseEvent e) { + processMouseEvent(e); + } + public void mouseReleased(MouseEvent e) { + processMouseEvent(e); + } + protected void processMouseEvent(MouseEvent e) { + int right = originalBorder.getBorderInsets(e.getComponent()).right + ARROW_SPACE_WIDTH; + isArrowMouseOver = e.getX() > getWidth() - right; + if(isArrowMouseOver) { + setActionCommand("Arrow"); + } else { + setActionCommand(""); + } + } + }; + + protected Border originalBorder = getBorder(); + protected boolean isMouseOver; + protected boolean isArrowMouseOver; + + public CComboButton() { + setMargin(new Insets(0, 1, 0, 1)); + setBorder(BorderFactory.createCompoundBorder(originalBorder, BorderFactory.createEmptyBorder(0, 0, 0, ARROW_SPACE_WIDTH + 1))); + setModel(new DefaultButtonModel() { + public boolean isPressed() { + return super.isPressed() && !isArrowMouseOver; + } + }); + addMouseListener(mouseHandler); + addMouseMotionListener(mouseHandler); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + boolean oldIsArrowMouseOver = isArrowMouseOver; + isArrowMouseOver = false; + getModel().setPressed(false); + isArrowMouseOver = oldIsArrowMouseOver; + } + }); + } + + public static boolean isArrowEvent(ActionEvent e) { + return "Arrow".equals(e.getActionCommand()); + } + + protected void fireActionPerformed(ActionEvent event) { + if(isArrowMouseOver == isArrowEvent(event)) { + super.fireActionPerformed(event); + } + } + + protected static Color shadow = UIManager.getColor("ComboBox.buttonShadow"); + protected static Color darkShadow = UIManager.getColor("ComboBox.buttonDarkShadow"); + protected static Color highlight = UIManager.getColor("ComboBox.buttonHighlight"); + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + int w = getWidth(); + int h = getHeight(); + Insets borderInsets = originalBorder.getBorderInsets(this); + int x = w - ARROW_SPACE_WIDTH - borderInsets.right + 1; + boolean isEnabled = isEnabled(); + if(isMouseOver && isEnabled) { + g.setColor(shadow); + g.drawLine(x, borderInsets.top + 1, x, h - borderInsets.bottom - 1); + } + Color origColor; + origColor = g.getColor(); + int size = (ARROW_WIDTH + 1) / 2; + paintTriangle(g, x - 1 + ARROW_WIDTH, (h - size) / 2, size, isEnabled); + g.setColor(origColor); + } + + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + size.height = Math.max(size.height, 12); + return size; + } + + protected void paintTriangle(java.awt.Graphics g, int x, int y, int size, boolean isEnabled) { + java.awt.Color oldColor = g.getColor(); + size = Math.max(size, 2); + int mid = (size / 2) - 1; + g.translate(x, y); + if (isEnabled) { + g.setColor(darkShadow); +// } else { +// g.setColor(shadow); + } else if (!isEnabled) { + g.translate(1, 1); + g.setColor(highlight); + int j=0; + for (int i = size - 1; i >= 0; i--) { + g.drawLine(mid - i, j, mid + i, j); + j++; + } + g.translate(-1, -1); + g.setColor(shadow); + } + int j=0; + for (int i = size - 1; i >= 0; i--) { + g.drawLine(mid - i, j, mid + i, j); + j++; + } + g.translate(-x, -y); + g.setColor(oldColor); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComposite.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComposite.java new file mode 100644 index 00000000000..3d82486a926 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CComposite.java @@ -0,0 +1,216 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.PaintEvent; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JViewport; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +class CCompositeImplementation extends JPanel implements CComposite { + + protected Composite handle; + protected JPanel contentPane; + protected JScrollPane scrollPane; + + public Container getSwingComponent() { + return contentPane; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CCompositeImplementation(Composite composite, int style) { + super(new BorderLayout(0, 0)); + this.handle = composite; + init(style); + } + + public boolean isFocusable() { + return contentPane.isFocusable(); + } + + public void requestFocus() { + contentPane.requestFocus(); + } + + public void setCursor(Cursor cursor) { + contentPane.setCursor(cursor); + } + + protected void init(int style) { + if((style & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } else { + setBorder(null); + } + JPanel panel = new JPanel(null) { + protected Graphics graphics; + public Graphics getGraphics() { + Graphics g; + if(graphics != null) { + g = graphics.create(); + } else { + g = super.getGraphics(); + } + return g; + } + public boolean isOptimizedDrawingEnabled() { + return getComponentCount() < 2 || Utils.isFlatLayout(handle); + } + public boolean isOpaque() { + return (CCompositeImplementation.this == null || backgroundImageIcon == null) && super.isOpaque(); + } + protected void paintComponent (Graphics g) { + graphics = g; + putClientProperty(Utils.SWTSwingGraphics2DClientProperty, g); + if(!(getParent() instanceof JViewport)) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + } + super.paintComponent(g); + handle.processEvent(new PaintEvent(this, PaintEvent.PAINT, null)); + putClientProperty(Utils.SWTSwingGraphics2DClientProperty, null); + graphics = null; + } + public Color getBackground() { + return CCompositeImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return CCompositeImplementation.this != null && userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return CCompositeImplementation.this != null && userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return CCompositeImplementation.this != null && userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + protected void processEvent(AWTEvent e) { + if(Utils.redispatchEvent(getSWTHandle(), e)) { + return; + } + super.processEvent(e); + } + }; + userAttributeHandler = new UserAttributeHandler(panel); + if((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) { + JScrollPane scrollPane = new UnmanagedScrollPane((style & SWT.V_SCROLL) != 0? JScrollPane.VERTICAL_SCROLLBAR_ALWAYS: JScrollPane.VERTICAL_SCROLLBAR_NEVER, (style & SWT.H_SCROLL) != 0? JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER) { + protected DisconnectedViewport createDisconnectedViewport() { + return new DisconnectedViewport() { + protected boolean isCreated = true; + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + public Color getBackground() { + return isCreated? userAttributeHandler.background: super.getBackground(); + } + }; + } + }; + this.scrollPane = scrollPane; + scrollPane.setBorder(null); + add(scrollPane, BorderLayout.CENTER); + scrollPane.getViewport().setView(panel); + } else { + add(panel, BorderLayout.CENTER); + } + contentPane = panel; + contentPane.setFocusable (true); + Utils.installMouseListener(contentPane, handle); + Utils.installKeyListener(contentPane, handle); + Utils.installFocusListener(contentPane, handle); + Utils.installComponentListener(this, handle); + } + + public Container getClientArea() { + return contentPane; + } + + public JScrollBar getVerticalScrollBar() { + return scrollPane == null? null: scrollPane.getVerticalScrollBar(); + } + + public JScrollBar getHorizontalScrollBar() { + return scrollPane == null? null: scrollPane.getHorizontalScrollBar(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: + setOpaque(true); + contentPane.setOpaque(true); + if(scrollPane != null) { + scrollPane.setOpaque(true); + scrollPane.getViewport().setOpaque(true); + } + break; + case BACKGROUND_INHERITANCE: + setOpaque(false); + contentPane.setOpaque(false); + if(scrollPane != null) { + scrollPane.setOpaque(false); + scrollPane.getViewport().setOpaque(false); + } + break; + } + } + +} + +/** + * The composite equivalent on the Swing side. + * @version 1.0 2005.08.31 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CComposite extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CComposite newInstance(Composite composite, int style) { + return new CCompositeImplementation(composite, style); + } + + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CControl.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CControl.java new file mode 100644 index 00000000000..cd93b107612 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CControl.java @@ -0,0 +1,102 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; + +import org.eclipse.swt.widgets.Control; + +/** + * The interface shared by all controls. + * @version 1.0 2005.03.13 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CControl { + + public static final int NO_BACKGROUND_INHERITANCE = 0; + public static final int PREFERRED_BACKGROUND_INHERITANCE = 1; + public static final int BACKGROUND_INHERITANCE = 2; + + public Rectangle getBounds(); + + public Point getLocation(); + + public Dimension getSize(); + + public Dimension getMinimumSize(); + + public Container getClientArea(); + + // TODO: implement so that it traverses the complete hierarchy + public String getToolTipText(); + + // TODO: implement so that it traverses the complete hierarchy + public void setToolTipText(String string); + + public void setBackgroundImage(Image backgroundImage); + + public void setBackgroundInheritance(int backgroundInheritanceType); + + public Container getSwingComponent(); + + public Control getSWTHandle(); + + public static class UserAttributeHandler { + protected Component component; + public Color background; + public Color foreground; + public Font font; + public Cursor cursor; + public UserAttributeHandler(Component component) { + this.component = component; + } + public void setBackground(Color background) { + this.background = background; + } + + public Color getBackground() { + return component.getBackground(); + } + + public void setForeground(Color foreground) { + this.foreground = foreground; + } + + public Color getForeground() { + return component.getForeground(); + } + + public void setFont(Font font) { + this.font = font; + } + + public Font getFont() { + return component.getFont(); + } + + public void setCursor(Cursor cursor) { + this.cursor = cursor; + } + + public Cursor getCursor() { + return component.getCursor(); + } + + } + + public UserAttributeHandler getUserAttributeHandler(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolBar.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolBar.java new file mode 100644 index 00000000000..54322c57bfe --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolBar.java @@ -0,0 +1,94 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Container; +import java.awt.Image; + +import javax.swing.JScrollBar; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.CoolBar; + +class CCoolBarImplementation extends JCoolBar implements CCoolBar { + + protected CoolBar handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CCoolBarImplementation(CoolBar coolBar, int style) { + handle = coolBar; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + if((style & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } + } + + public Container getClientArea() { + return this; + } + + public JScrollBar getVerticalScrollBar() { + return null; + } + + public JScrollBar getHorizontalScrollBar() { + return null; + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: setOpaque(false); break; + } + } + +} + +public interface CCoolBar extends CComposite { + + public static class Factory { + private Factory() {} + + public static CCoolBar newInstance(CoolBar coolBar, int style) { + return new CCoolBarImplementation(coolBar, style); + } + + } + + public int getItemCount(); + + public boolean isLocked(); + + public void setLocked(boolean isLocked); + + public void setWrappedIndices(int[] indices); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolItem.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolItem.java new file mode 100644 index 00000000000..eae30f7903b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CCoolItem.java @@ -0,0 +1,57 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.CoolItem; + +class CCoolItemImplementation extends JCoolBarItem implements CCoolItem { + + protected CoolItem handle; + + public CCoolItemImplementation(CoolItem coolItem, int style) { + setLayout(new BorderLayout(0, 0)); + handle = coolItem; + init(style); + } + + public Dimension getItemPreferredSize() { + Dimension preferredSize = getPreferredSize(); + if(getComponentCount() > 0) { + Dimension cPreferredSize = getComponent(0).getPreferredSize(); + Point size = ((CControl)getComponent(0)).getSWTHandle().computeSize(SWT.DEFAULT, SWT.DEFAULT); + return new Dimension(preferredSize.width, preferredSize.height - cPreferredSize.height + size.y); + } + return preferredSize; + } + + protected void init(int style) { +// getToolBar().setLayout(null); + } + +} + +public interface CCoolItem { + + public static class Factory { + private Factory() {} + + public static CCoolItem newInstance(CoolItem coolItem, int style) { + return new CCoolItemImplementation(coolItem, style); + } + } + + public boolean isWrapped(); + + public void setWrapped(boolean isWrapped); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandBar.java new file mode 100644 index 00000000000..85255af1efe --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandBar.java @@ -0,0 +1,189 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ExpandBar; + +class CExpandBarImplementation extends JScrollPane implements CExpandBar { + + protected ExpandBar handle; + protected JExpandPane expandPane; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CExpandBarImplementation(ExpandBar expandBar, int style) { + this.handle = expandBar; + expandPane = new JExpandPane() { + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + }; + userAttributeHandler = new UserAttributeHandler(expandPane); + JViewport viewport = new JViewport() { + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + public Color getBackground() { + return CExpandBarImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + }; + setViewport(viewport); + viewport.setView(expandPane); + init(style); + } + + protected void init(int style) { + setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER); + if((style & SWT.V_SCROLL) == 0) { + setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_NEVER); + } + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + expandPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + handle.processEvent(e); + } + }); + } + + public Container getClientArea() { + return expandPane; + } + + public void addExpandPaneItem(String title, Icon icon, Component component) { + expandPane.addExpandPaneItem(title, icon, component); + } + + public void insertExpandPaneItem(String title, Icon icon, Component component, int index) { + expandPane.insertExpandPaneItem(title, icon, component, index); + } + + public void removeExpandPaneItem(Component component) { + expandPane.removeExpandPaneItem(component); + } + + public void setExpanded(Component component, boolean isExpanded) { + expandPane.getExpandItem(component).setExpanded(isExpanded); + } + + public boolean isExpanded(Component component) { + return expandPane.getExpandItem(component).isExpanded(); + } + + public Dimension getTitleBarSize(Component component) { + return expandPane.getExpandItem(component).getTitleBarSize(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: { + setOpaque(true); + getViewport().setOpaque(true); + expandPane.setOpaque(true); + break; + } + case BACKGROUND_INHERITANCE: { + setOpaque(false); + getViewport().setOpaque(false); + expandPane.setOpaque(false); + break; + } + } + } + + public void setIcon(Component component, ImageIcon icon) { + expandPane.getExpandItem(component).setIcon(icon); + } + + public void setText(Component component, String text) { + expandPane.getExpandItem(component).setText(text); + } + + public void setSpacing(int spacing) { + expandPane.setSpacing(spacing); + } + + public int getSpacing() { + return expandPane.getSpacing(); + } + +} + +public interface CExpandBar extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CExpandBar newInstance(ExpandBar expandBar, int style) { + return new CExpandBarImplementation(expandBar, style); + } + + } + + public void addExpandPaneItem(String title, Icon icon, Component component); + + public void insertExpandPaneItem(String title, Icon icon, Component component, int index); + + public void removeExpandPaneItem(Component component); + + public void setExpanded(Component component, boolean isExpanded); + + public boolean isExpanded(Component component); + + public Dimension getTitleBarSize(Component component); + + public void setIcon(Component component, ImageIcon icon); + + public void setText(Component component, String text); + + public void setSpacing(int spacing); + + public int getSpacing(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandItem.java new file mode 100644 index 00000000000..6dffd138fcd --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CExpandItem.java @@ -0,0 +1,52 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Component; + +import javax.swing.JPanel; + +import org.eclipse.swt.widgets.ExpandItem; + +class CExpandItemImplementation extends JPanel implements CExpandItem { + + protected ExpandItem handle; + + public CExpandItemImplementation(ExpandItem expandItem, int style) { + super(new BorderLayout(0, 0)); + setOpaque(false); + this.handle = expandItem; + init(style); + } + + protected void init(int style) { + } + + public Component getContent() { + if(getComponentCount() > 0) { + return getComponent(0); + } + return null; + } + +} + +public interface CExpandItem { + + public static class Factory { + private Factory() {} + + public static CExpandItem newInstance(ExpandItem expandItem, int style) { + return new CExpandItemImplementation(expandItem, style); + } + } + + public Component getContent(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGC.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGC.java new file mode 100644 index 00000000000..e1ce82ba0e8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGC.java @@ -0,0 +1,250 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.RenderingHints.Key; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.image.ImageObserver; +import java.util.Map; + +public interface CGC { + + public static abstract class CGCGraphics2D implements CGC { + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + getGraphics().copyArea(x, y, width, height, dx, dy); + } + public void dispose() { + getGraphics().dispose(); + } + public void draw(Shape s) { + getGraphics().draw(s); + } + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + getGraphics().drawArc(x, y, width, height, startAngle, arcAngle); + } + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { + return getGraphics().drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + public void drawLine(int x1, int y1, int x2, int y2) { + getGraphics().drawLine(x1, y1, x2, y2); + } + public void drawOval(int x, int y, int width, int height) { + getGraphics().drawOval(x, y, width, height); + } + public void drawPolygon(int[] points, int[] points2, int points3) { + getGraphics().drawPolygon(points, points2, points3); + } + public void drawPolyline(int[] points, int[] points2, int points3) { + getGraphics().drawPolyline(points, points2, points3); + } + public void drawRect(int x, int y, int width, int height) { + getGraphics().drawRect(x, y, width, height); + } + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + getGraphics().drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + public void drawString(String str, int x, int y) { + getGraphics().drawString(str, x, y); + } + public void fill(Shape s) { + getGraphics().fill(s); + } + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + getGraphics().fillArc(x, y, width, height, startAngle, arcAngle); + } + public void fillOval(int x, int y, int width, int height) { + getGraphics().fillOval(x, y, width, height); + } + public void fillPolygon(int[] points, int[] points2, int points3) { + getGraphics().fillPolygon(points, points2, points3); + } + public void fillRect(int x, int y, int width, int height) { + getGraphics().fillRect(x, y, width, height); + } + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + getGraphics().fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + public Color getBackground() { + return getGraphics().getBackground(); + } + public Color getColor() { + return getGraphics().getColor(); + } + public Composite getComposite() { + return getGraphics().getComposite(); + } + public Font getFont() { + return getGraphics().getFont(); + } + public FontMetrics getFontMetrics() { + return getGraphics().getFontMetrics(); + } + public FontRenderContext getFontRenderContext() { + return getGraphics().getFontRenderContext(); + } + public Paint getPaint() { + return getGraphics().getPaint(); + } + public Object getRenderingHint(Key hintKey) { + return getGraphics().getRenderingHint(hintKey); + } + public RenderingHints getRenderingHints() { + return getGraphics().getRenderingHints(); + } + public Stroke getStroke() { + return getGraphics().getStroke(); + } + public AffineTransform getTransform() { + return getGraphics().getTransform(); + } + public void setBackground(Color background) { + getGraphics().setBackground(background); + } + public void setColor(Color color) { + getGraphics().setColor(color); + } + public void setComposite(Composite comp) { + getGraphics().setComposite(comp); + } + public void setFont(Font font) { + getGraphics().setFont(font); + } + public void setPaint(Paint paint) { + getGraphics().setPaint(paint); + } + public void setPaintMode() { + getGraphics().setPaintMode(); + } + public void setRenderingHint(Key hintKey, Object hintValue) { + getGraphics().setRenderingHint(hintKey, hintValue); + } + public void setRenderingHints(Map hints) { + getGraphics().setRenderingHints(hints); + } + public void setStroke(Stroke s) { + getGraphics().setStroke(s); + } + public void setTransform(AffineTransform tx) { + getGraphics().setTransform(tx); + } + public void setXORMode(Color c1) { + getGraphics().setXORMode(c1); + } + public void transform(AffineTransform tx) { + getGraphics().transform(tx); + } + protected Shape userClip; + protected Shape systemClip; + public void setUserClip(Shape userClip) { + if(this.userClip == null && userClip == null) { + return; + } + this.userClip = userClip; + Graphics2D g = getGraphics(); + if(systemClip == null) { + systemClip = g.getClip(); + } else { + g.setClip(systemClip); + } + if(userClip != null) { + g.clip(userClip); + } + } + public Shape getUserClip() { + return userClip; + } + } + + public Graphics2D getGraphics(); + + public void dispose(); + + public Color getBackground(); + public void setBackground(Color background); + + public Color getColor(); + public void setColor(Color color); + + public Paint getPaint(); + public void setPaint(Paint paint); + + public Font getFont(); + public void setFont(Font font); + + public void fill(Shape s); + + public void fillOval(int x, int y, int width, int height); + + public void fillRect(int x, int y, int width, int height); + + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight); + + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle); + + public void drawRect(int x, int y, int width, int height); + + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer); + + public void drawLine(int x1, int y1, int x2, int y2); + + public void drawOval(int x, int y, int width, int height); + + public void draw(Shape s); + + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints); + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints); + + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight); + + public FontMetrics getFontMetrics(); + public FontRenderContext getFontRenderContext(); + + public void drawString(String str, int x, int y); + + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle); + + public Object getRenderingHint(RenderingHints.Key hintKey); + public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue); + + public RenderingHints getRenderingHints(); + public void setRenderingHints(Map hints); + + public Composite getComposite(); + public void setComposite(Composite comp); + + public Stroke getStroke(); + public void setStroke(Stroke s); + + public void setXORMode(Color c1); + public void setPaintMode(); + + public void transform(AffineTransform Tx); + public AffineTransform getTransform(); + public void setTransform(AffineTransform Tx); + + public void copyArea(int x, int y, int width, int height, int dx, int dy); + + public void setUserClip(Shape s); + public Shape getUserClip(); + public Dimension getDeviceSize(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGroup.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGroup.java new file mode 100644 index 00000000000..c81ca84c3eb --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CGroup.java @@ -0,0 +1,174 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.border.TitledBorder; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; + +class CGroupImplementation extends JPanel implements CGroup { + + protected TitledBorder titledBorder; + protected Container contentPane; + protected JScrollPane scrollPane; + + protected Group handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CGroupImplementation(Group group, int style) { + super(new BorderLayout(0, 0)); + this.handle = group; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + // TODO: support styles + titledBorder = new TitledBorder("") { + public Font getTitleFont() { + return CGroupImplementation.this != null && userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getTitleFont(); + } + }; + setBorder(titledBorder); + if((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) { + JScrollPane scrollPane = new JScrollPane((style & SWT.V_SCROLL) != 0? JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED: JScrollPane.VERTICAL_SCROLLBAR_NEVER, (style & SWT.H_SCROLL) != 0? JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + this.scrollPane = scrollPane; + add(scrollPane, BorderLayout.CENTER); + contentPane = scrollPane.getViewport(); + } else { + contentPane = new JPanel(null); + ((JComponent)contentPane).setOpaque(false); + add(contentPane, BorderLayout.CENTER); + } + Utils.installMouseListener(contentPane, handle); + Utils.installKeyListener(contentPane, handle); + Utils.installFocusListener(contentPane, handle); + Utils.installComponentListener(this, handle); + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Utils.paintTiledImage(this, g, backgroundImageIcon); + } + + public Container getClientArea() { + return contentPane; + } + + public String getText () { + return titledBorder.getTitle(); + } + + public void setText(String string) { + titledBorder.setTitle(string); + repaint(); + } + + public JScrollBar getVerticalScrollBar() { + return scrollPane == null? null: scrollPane.getVerticalScrollBar(); + } + + public JScrollBar getHorizontalScrollBar() { + return scrollPane == null? null: scrollPane.getHorizontalScrollBar(); + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: + setOpaque(true); +// ((JComponent)contentPane).setOpaque(true); + if(scrollPane != null) { + scrollPane.setOpaque(true); + scrollPane.getViewport().setOpaque(true); + } + break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: + setOpaque(false); +// ((JComponent)contentPane).setOpaque(false); + if(scrollPane != null) { + scrollPane.setOpaque(false); + scrollPane.getViewport().setOpaque(false); + } + break; + } + } + +} + +/** + * The group equivalent on the Swing side. + * @version 1.0 2005.03.13 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CGroup extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CGroup newInstance(Group group, int style) { + return new CGroupImplementation(group, style); + } + + } + + public String getText(); + + public void setText(String string); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLabel.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLabel.java new file mode 100644 index 00000000000..666b70ea867 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLabel.java @@ -0,0 +1,248 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JSeparator; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +class CSeparator extends JPanel implements CLabel { + + protected Label handle; + + protected JSeparator separator; + + public Container getSwingComponent() { + return separator; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CSeparator(Label label, int style) { + this.handle = label; + userAttributeHandler = new UserAttributeHandler(this); + GridBagLayout gridBag = new GridBagLayout(); + setLayout(gridBag); + GridBagConstraints c = new GridBagConstraints(); + c.weightx = 1.0; + c.weighty = 1.0; + c.fill = (style & SWT.HORIZONTAL) != 0? GridBagConstraints.HORIZONTAL: GridBagConstraints.VERTICAL; + separator = new JSeparator((style & SWT.HORIZONTAL) != 0? JSeparator.HORIZONTAL: JSeparator.VERTICAL); + gridBag.setConstraints(separator, c); + add(separator); + init(style); + } + + protected void init(int style) { + if((style & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } + Utils.installMouseListener(separator, handle); + Utils.installKeyListener(separator, handle); + Utils.installFocusListener(separator, handle); + Utils.installComponentListener(this, handle); + } + + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + + public Container getClientArea() { + return separator; + } + + public int getPreferredWidth() { + return getPreferredSize().width; + } + + public void setText(String text, int mnemonicIndex) { + } + + public void setAlignment(int alignment) { + } + + public void setIcon(Icon icon) { + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: + setOpaque(true); + separator.setOpaque(true); + break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: + setOpaque(false); + separator.setOpaque(false); + break; + } + } + +} + +class CLabelImplementation extends JMultiLineLabel implements CLabel { + + protected Label handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CLabelImplementation(Label label, int style) { + this.handle = label; + LookAndFeelUtils.applyLabelStyle(this); + userAttributeHandler = new UserAttributeHandler(this) { + public void setForeground(Color foreground) { + super.setForeground(foreground); + adjustStyles(); + } + public void setFont(Font font) { + super.setFont(font); + adjustStyles(); + } + }; + init(style); + } + + protected void init(int style) { + setFocusable(false); + setWrapping((style & SWT.WRAP) != 0); + if((style & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } + if((style & SWT.RIGHT) != 0) { + setAlignment(JMultiLineLabel.RIGHT); + } else if((style & SWT.CENTER) != 0) { + setAlignment(JMultiLineLabel.CENTER); + } else { + setAlignment(JMultiLineLabel.LEFT); + } + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + } + + public boolean isOpaque() { + return backgroundImageIcon == null && (userAttributeHandler != null && userAttributeHandler.background != null || super.isOpaque()); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + + public Container getClientArea() { + return this; + } + + public void setAlignment(int alignment) { + setHorizontalAlignment(alignment); + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { +// switch(backgroundInheritanceType) { +// case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; +// case PREFERRED_BACKGROUND_INHERITANCE: +// case BACKGROUND_INHERITANCE: setOpaque(false); break; +// } + } + +} + +/** + * The label equivalent on the Swing side. + * @version 1.0 2005.08.20 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CLabel extends CControl { + + public static class Factory { + private Factory() {} + + public static CLabel newInstance(Label label, int style) { + if((style & SWT.SEPARATOR) != 0) { + return new CSeparator(label, style); + } + return new CLabelImplementation(label, style); + } + + } + + public int getPreferredWidth(); + + public void setText(String text, int mnemonicIndex); + + public void setAlignment(int alignment); + + public void setIcon(Icon icon); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLink.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLink.java new file mode 100644 index 00000000000..f7cae9e81c6 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CLink.java @@ -0,0 +1,266 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.util.Locale; + +import javax.swing.ImageIcon; +import javax.swing.JEditorPane; +import javax.swing.border.Border; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.View; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Link; + +class CLinkImplementation extends JEditorPane implements CLink { + + protected Link handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CLinkImplementation(Link link, int style) { + setFocusable(false); + this.handle = link; + userAttributeHandler = new UserAttributeHandler(this) { + public void setForeground(Color foreground) { + super.setForeground(foreground); + adjustStyles(); + } + public void setFont(Font font) { + super.setFont(font); + adjustStyles(); + } + }; + setContentType("text/html"); + init(style); + } + + protected void init(int style) { + setEditable(false); + putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + setOpaque(false); + adjustStyles(); + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + handle.processEvent(e); + } + } + }); + } + + public int getPreferredWidth() { + String htmlText = getText(); + setText(text); + int width = super.getPreferredSize().width; + setText(htmlText); + return width; + } + + protected void adjustStyles() { + updateUI(); + LookAndFeelUtils.applyLabelStyle(this); + setMargin(new Insets(0, 0, 0, 0)); + if((handle.getStyle() & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } + reshape(getX(), getY(), getWidth(), getHeight()); + } + + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + View globalView = getUI().getRootView(this); + if(globalView != null) { + Border border = getBorder(); + if(border != null) { + Insets insets = border.getBorderInsets(this); + w -= insets.left + insets.right; + h -= insets.top + insets.bottom; + } + globalView.setSize(w, h); + } + } + + public Dimension getMaximumSize() { + return new Dimension(Integer.MAX_VALUE, super.getMaximumSize().height); + } + + public boolean isOpaque() { + return backgroundImageIcon == null && (userAttributeHandler != null && userAttributeHandler.background != null || super.isOpaque()); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + + public Container getClientArea() { + return this; + } + + protected String text = getText(); + + public void setLinkText(String text) { + this.text = text; + super.setText("" + escapeXML(text) + ""); + adjustStyles(); + } + + public static String escapeXML(String s) { + if(s == null) { + return s; + } + int length = s.length(); + if(length == 0) { + return s; + } + StringBuffer sb = new StringBuffer((int)(length * 1.1)); + int start = -1; + int lastEndTag = -1; + for(int i=0; i': + if(start >= 0) { + String tag = s.substring(start, i); + String lTag = tag.toLowerCase(Locale.ENGLISH); + if(lTag.equals("= 0) { + String content = Utils.escapeSwingXML(s.substring(lastEndTag + 1, i - 3)); + sb.append("" + content + ""); + lastEndTag = -1; + start = -1; + break; + } + sb.append(""); + start = -1; + break; + } else if(lTag.startsWith("= 0) { + sb.append(Utils.escapeSwingXML(s.substring(start, s.length()))); + } + return sb.toString(); + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { +// switch(backgroundInheritanceType) { +// case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; +// case PREFERRED_BACKGROUND_INHERITANCE: +// case BACKGROUND_INHERITANCE: setOpaque(false); break; +// } + } + +} + +/** + * The label equivalent on the Swing side. + * @version 1.0 2005.08.20 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CLink extends CControl { + + public static class Factory { + private Factory() {} + + public static CLink newInstance(Link link, int style) { + return new CLinkImplementation(link, style); + } + + } + + public int getPreferredWidth(); + + public void setLinkText(String text); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CList.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CList.java new file mode 100644 index 00000000000..5ad466e48ca --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CList.java @@ -0,0 +1,393 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.List; + +class CListImplementation extends JScrollPane implements CList { + + protected List handle; + protected JList list; + + public Container getSwingComponent() { + return list; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CListImplementation(List list, int style) { + this.handle = list; + this.list = new JList(new DefaultListModel()) { + public Color getBackground() { + return CListImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return CListImplementation.this != null && userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return CListImplementation.this != null && userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return CListImplementation.this != null && userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + }; + this.list.setCellRenderer(new DefaultListCellRenderer() { + public boolean isOpaque() { + return CListImplementation.this.list.isOpaque() && super.isOpaque(); + } + }); + userAttributeHandler = new UserAttributeHandler(this.list); + JViewport viewport = new JViewport() { + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + public Color getBackground() { + return CListImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + }; + setViewport(viewport); + viewport.setView(this.list); + init(style); + } + + protected void init(int style) { + setFont(list.getFont()); + if((style & SWT.BORDER) == 0) { + setBorder(null); + list.setBorder(null); + } + if((style & SWT.H_SCROLL) == 0) { + setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER); + } + if((style & SWT.V_SCROLL) == 0) { + setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_NEVER); + } + list.setSelectionMode((style & SWT.MULTI) != 0? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: ListSelectionModel.SINGLE_SELECTION); + Utils.installMouseListener(list, handle); + Utils.installKeyListener(list, handle); + Utils.installFocusListener(list, handle); + Utils.installComponentListener(this, handle); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2) { + handle.processEvent(new ActionEvent(list, ActionEvent.ACTION_PERFORMED, null)); + } + } + }); + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + if(!isAdjustingSelection) { + handle.processEvent(e); + } + } + }); + } + + public boolean isFocusable() { + return list.isFocusable(); + } + + protected boolean isAdjustingSelection; + + public void requestFocus() { + list.requestFocus(); + if(list.getModel().getSize() > 0 && list.getSelectedIndex() < 0) { + isAdjustingSelection = true; + ListSelectionModel selectionModel = list.getSelectionModel(); + if(selectionModel.getLeadSelectionIndex() < 0) { + selectionModel.setAnchorSelectionIndex(0); + selectionModel.setLeadSelectionIndex(0); + selectionModel.clearSelection(); + } + isAdjustingSelection = false; + } + } + + public void setFont(Font font) { + super.setFont(font); + if(list != null) { + list.setFont(font); + } + } + + public Container getClientArea() { + return list; + } + + public Dimension getPreferredSize() { + int itemCount = getItemCount(); + int height = super.getPreferredSize().height; + if(itemCount > 0) { + Rectangle bounds = list.getCellBounds(itemCount - 1, itemCount - 1); + height = bounds.y + 2 * bounds.height + SwingUtilities.convertPoint(list, 0, 0, this).y + 1; + } + return new Dimension(super.getPreferredSize().width, height); + } + + public void addElement(Object obj) { + ((DefaultListModel)list.getModel()).addElement(obj); + } + + public void insertElementAt(Object obj, int index) { + ((DefaultListModel)list.getModel()).insertElementAt(obj, index); + } + + public void removeElementAt(int index) { + ((DefaultListModel)list.getModel()).removeElementAt(index); + } + + public void removeRange(int fromIndex, int toIndex) { + ((DefaultListModel)list.getModel()).removeRange(fromIndex, toIndex); + } + + public void removeAllElements() { + ((DefaultListModel)list.getModel()).removeAllElements(); + } + + public Object getElementAt(int index) { + return list.getModel().getElementAt(index); + } + + public void setElementAt(Object obj, int index) { + ((DefaultListModel)list.getModel()).setElementAt(obj, index); + } + + public void setElements(Object[] objects) { + removeAllElements(); + DefaultListModel model = ((DefaultListModel)list.getModel()); + for(int i=0; i= 0) { + list.setSelectedIndex(index); + } + } + } + + public void addSelectionInterval(int index0, int index1) { + list.getSelectionModel().addSelectionInterval(index0, index1); + } + + public void setSelectionInterval(int index0, int index1) { + list.getSelectionModel().setSelectionInterval(index0, index1); + } + + public void removeSelectionInterval(int index0, int index1) { + list.getSelectionModel().removeSelectionInterval(index0, index1); + } + + public void showSelection() { + int min = list.getMinSelectionIndex(); + if(min == -1) { + return; + } + int max = list.getMaxSelectionIndex(); + scrollRectToVisible(list.getCellBounds(min, max)); + } + + public int getFirstVisibleIndex() { + return list.getFirstVisibleIndex(); + } + + public void setFirstVisibleIndex(int index) { + if(index < 0) { + return; + } + if(index >= getItemCount()) { + return; + } + scrollRectToVisible(new Rectangle(0, 0, getWidth(), 0)); + scrollRectToVisible(list.getCellBounds(index, index)); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: { + setOpaque(true); + getViewport().setOpaque(true); + list.setOpaque(true); + break; + } + case BACKGROUND_INHERITANCE: { + setOpaque(false); + getViewport().setOpaque(false); + list.setOpaque(false); + break; + } + } + } + + public Rectangle getCellBounds(int index) { + return list.getCellBounds(index, index); + } + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + list.setEnabled(enabled); + } + + public int getFocusIndex() { + return list.getSelectionModel().getLeadSelectionIndex(); + } + +} + +public interface CList extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CList newInstance(List list, int style) { + return new CListImplementation(list, style); + } + + } + + public void addElement(Object obj); + + public void insertElementAt(Object obj, int index); + + public void removeElementAt(int index); + + public void removeRange(int fromIndex, int toIndex); + + public void removeAllElements(); + + public Object getElementAt(int index); + + public void setElementAt(Object obj, int index); + + public void setElements(Object[] objects); + + public int indexOf(Object obj, int index); + + public int getItemCount(); + + public int getMinSelectionIndex(); + + public int getMaxSelectionIndex(); + + public int[] getSelectionIndices(); + + public boolean isSelectedIndex(int index); + + public void setSelectedElements(Object[] elements); + + public void addSelectionInterval(int index0, int index1); + + public void setSelectionInterval(int index0, int index1); + + public void removeSelectionInterval(int index0, int index1); + + public void showSelection(); + + public int getFirstVisibleIndex(); + + public void setFirstVisibleIndex(int index); + + public Rectangle getCellBounds(int index); + + public int getFocusIndex(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CProgressBar.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CProgressBar.java new file mode 100644 index 00000000000..0ecf87bbba9 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CProgressBar.java @@ -0,0 +1,113 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Image; + +import javax.swing.JProgressBar; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ProgressBar; + +class CProgressBarImplementation extends JProgressBar implements CProgressBar { + + protected ProgressBar handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CProgressBarImplementation(ProgressBar progressBar, int style) { + handle = progressBar; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + setOrientation((style & SWT.HORIZONTAL) != 0? HORIZONTAL: VERTICAL); + setIndeterminate((style & SWT.INDETERMINATE) != 0); + // TODO: find if we have some style for non SMOOTH scrollbars. + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + } + + public Container getClientArea() { + return this; + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: setOpaque(false); break; + } + } + +} + +public interface CProgressBar extends CControl { + + public static class Factory { + private Factory() {} + + public static CProgressBar newInstance(ProgressBar progressBar, int style) { + return new CProgressBarImplementation(progressBar, style); + } + + } + + public int getMinimum(); + + public int getMaximum(); + + public int getValue(); + + public void setMinimum(int maximum); + + public void setMaximum(int maximum); + + public void setValue(int n); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSash.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSash.java new file mode 100644 index 00000000000..b7752bbcda3 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSash.java @@ -0,0 +1,173 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; + +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Sash; + +class CSashImplementation extends JPanel implements CSash { + + protected Sash handle; + + protected BasicSplitPaneDivider divider; + + public Container getSwingComponent() { + return divider; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CSashImplementation(Sash sash, int style) { + super(new BorderLayout(0, 0)); + this.handle = sash; + userAttributeHandler = new UserAttributeHandler(this); + JSplitPane splitPane = new JSplitPane((style & SWT.HORIZONTAL) != 0? JSplitPane.VERTICAL_SPLIT: JSplitPane.HORIZONTAL_SPLIT); + divider = ((BasicSplitPaneUI)splitPane.getUI()).getDivider(); + if((handle.getStyle() & SWT.SMOOTH) == 0) { + MouseInputListener mouseInputListener = new MouseInputAdapter() { + protected Window splitterWindow; + public void mousePressed(MouseEvent e) { + if((e.getButton() & MouseEvent.BUTTON1) == 0) { + return; + } + dragLocation = (handle.getStyle() & SWT.VERTICAL) != 0? getLocation().x: getLocation().y; + splitterWindow = new Window(SwingUtilities.getWindowAncestor(CSashImplementation.this)) { + public void update(Graphics g) { + paint(g); + } + public void paint(Graphics g) { + super.paint(g); + Dimension size = getSize(); + Color background = getBackground(); + for(int i=0; i= 0; i--) { + if(blockerList.get(i) == cShell) { + return true; + } + } + if(!applicationBlockerList.isEmpty()) { + for(int i=applicationBlockerList.size()-1; i>= 0; i--) { + if(applicationBlockerList.get(i) == cShell) { + return false; + } + } + return true; + } + return false; + } + + protected CShell[] getBlockers() { + if(blockerList.isEmpty() && applicationBlockerList.isEmpty()) { + return NO_BLOCKERS; + } + if(blockerList.size() + applicationBlockerList.size() == 1) { + CShell blocker = blockerList.isEmpty()? (CShell)applicationBlockerList.get(0): (CShell)blockerList.get(0); + if(blocker == cShell) { + return NO_BLOCKERS; + } + return new CShell[] {blocker}; + } + List shellList = new ArrayList(); + for(int i=blockerList.size()-1; i>= 0; i--) { + Object blocker = blockerList.get(i); + if(blocker != cShell) { + shellList.add(blocker); + } + } + if(!applicationBlockerList.contains(cShell)) { + for(int i=applicationBlockerList.size()-1; i>= 0; i--) { + Object blocker = applicationBlockerList.get(i); + shellList.add(blocker); + } + } + return (CShell[])shellList.toArray(new CShell[0]); + } + + protected Shell parent; + protected CShell cShell; + + protected ModalityHandler(CShell cShell) { + this.cShell = cShell; + } + + protected boolean isEnabled; + + protected void adjustBlockedShells() { + for(Iterator it=windowSet.iterator(); it.hasNext(); ) { + Window window = (Window)it.next(); + if(window instanceof CShell) { + CShell cShell = (CShell)window; + cShell.setModallyBlocked(cShell.getModalityHandler().isBlocked()); + } + } + } + + protected void setEnabled(boolean isEnabled) { + if(this.isEnabled == isEnabled) { + return; + } + Control handle = cShell.getSWTHandle(); + if(isEnabled) { + if(!handle.isDisposed()) { + parent = (Shell)cShell.getSWTHandle().getParent(); + this.isEnabled = isEnabled; + int style = handle.getStyle(); + if((style & SWT.APPLICATION_MODAL) != 0 || (style & SWT.SYSTEM_MODAL) != 0) { + applicationBlockerList.add(cShell); + } else if((style & SWT.PRIMARY_MODAL) != 0) { + Composite parent = handle.getParent(); + if(parent != null) { + ((CShell)parent.handle).getModalityHandler().blockerList.add(cShell); + } + } + } + } else { + applicationBlockerList.remove(cShell); + if(parent != null) { + ((CShell)parent.handle).getModalityHandler().blockerList.remove(cShell); + } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + // Empty event + } + }); + } + adjustBlockedShells(); + } + + protected void advertiseBlocker() { +// Toolkit.getDefaultToolkit().beep(); + cShell.toFront(); +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { +// final JDialog dialog = new JDialog((Window)cShell); +// dialog.setLocation(Integer.MIN_VALUE, Integer.MIN_VALUE); +// dialog.setVisible(true); +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { +// dialog.setVisible(false); +// cShell.toFront(); +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { +// dialog.setVisible(true); +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { +// dialog.dispose(); +// cShell.toFront(); +// } +// }); +// } +// }); +// } +// }); +// } +// }); + } + } + + public static int MAXIMIZED_BOTH = JFrame.MAXIMIZED_BOTH; + public static int ICONIFIED = JFrame.ICONIFIED; + public static int NORMAL = JFrame.NORMAL; + + public static class Factory { + private Factory() {} + + static { + Toolkit.getDefaultToolkit().setDynamicLayout(true); + } + + public static CShell newInstance(Shell shell, CShell parent, int style) { + if(shell instanceof CEmbeddedShell) { + return new CShellPanel(shell, style); + } + if(parent instanceof CShellFrame) { + return new CShellDialog(shell, (CShellFrame)parent, style); + } + if(parent instanceof CShellDialog) { + return new CShellDialog(shell, (CShellDialog)parent, style); + } + return new CShellFrame(shell, style); + } + + } + + public void forceActive(); + + public String getTitle(); + + public void setTitle(String title); + + public void toFront(); + + public int getExtendedState(); + + public void setExtendedState(int state); + + public void setIconImage(Image image); + + public void setIconImages(List imageList); + + public void setJMenuBar(JMenuBar menuBar); + + public void setDefaultButton(CButton button); + + public ModalityHandler getModalityHandler(); + + public void setModallyBlocked(boolean isModallyBlocked); + + public boolean isModallyBlocked(); + + public void setActivationEventsBlocked(boolean areActivationEventsBlocked); + +} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSlider.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSlider.java new file mode 100644 index 00000000000..5627d425d28 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSlider.java @@ -0,0 +1,143 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +import javax.swing.JScrollBar; +import javax.swing.JSlider; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Slider; + +class CSliderImplementation extends JScrollBar implements CSlider { + + protected Slider handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CSliderImplementation(Slider slider, int style) { + super((style & SWT.HORIZONTAL) != 0? JSlider.HORIZONTAL: JSlider.VERTICAL); + handle = slider; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + setMaximum(100); + setValue(0); + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + addAdjustmentListener(new AdjustmentListener() { + public void adjustmentValueChanged(AdjustmentEvent e) { + handle.processEvent(e); + } + }); + } + + public Container getClientArea() { + return this; + } + + public Dimension getPreferredSize() { + if(!isPreferredSizeSet()) { + return getOrientation() == JSlider.HORIZONTAL? new Dimension(170, super.getPreferredSize().height): new Dimension(super.getPreferredSize().width, 170); + } + return super.getPreferredSize(); + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: setOpaque(false); break; + } + } + +} + +public interface CSlider extends CControl { + + public static class Factory { + private Factory() {} + + public static CSlider newInstance(Slider slider, int style) { + return new CSliderImplementation(slider, style); + } + + } + + public int getMinimum(); + + public int getMaximum(); + + public int getValue(); + + public int getVisibleAmount(); + + public void setMinimum(int maximum); + + public void setMaximum(int maximum); + + public void setValue(int value); + + public void setVisibleAmount(int visibleAmount); + + public void setValues(int newValue, int newExtent, int newMin, int newMax); + + public int getUnitIncrement(); + + public void setUnitIncrement(int unitIncrement); + + public int getBlockIncrement(); + + public void setBlockIncrement(int blockIncrement); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSpinner.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSpinner.java new file mode 100644 index 00000000000..8c814c76861 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CSpinner.java @@ -0,0 +1,270 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.JFormattedTextField; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.AbstractDocument; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DocumentFilter; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Spinner; + +class CSpinnerImplementation extends JSpinner implements CSpinner { + + protected Spinner handle; + + protected SpinnerNumberModel model; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CSpinnerImplementation(Spinner spinner, int style) { + this.handle = spinner; + userAttributeHandler = new UserAttributeHandler(this); + model = new SpinnerNumberModel(0, minimum, maximum, 1.0); + setModel(model); + model.setMinimum(new Comparable() { + public int compareTo(Object o) { + return minimum - Math.round(((Number)o).floatValue() * (int)Math.pow(10, digitCount)); + } + }); + model.setMaximum(new Comparable() { + public int compareTo(Object o) { + return maximum - Math.round(((Number)o).floatValue() * (int)Math.pow(10, digitCount)); + } + }); + init(style); + } + + protected KeyEvent keyEvent = null; + + protected void init(int style) { + JFormattedTextField textField = ((DefaultEditor)getEditor()).getTextField(); + if((style & SWT.READ_ONLY) != 0) { + textField.setEditable(false); + } +// if((style & SWT.BORDER) == 0) { +// setBorder(null); +// textField.setBorder(null); +// } + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + textField.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + keyEvent = e; + } + public void keyReleased(KeyEvent e) { + keyEvent = null; + } + }); + addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + handle.processEvent(e); + } + }); + AbstractDocument document = (AbstractDocument)textField.getDocument(); + document.addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { + handle.processEvent(e); + } + public void insertUpdate(DocumentEvent e) { + handle.processEvent(e); + } + public void removeUpdate(DocumentEvent e) { + handle.processEvent(e); + } + }); + document.setDocumentFilter(new DocumentFilter() { +// public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { +// } + public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { + TextFilterEvent filterEvent = new TextFilterEvent(this, text, offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, attrs); + } + } + public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { + TextFilterEvent filterEvent = new TextFilterEvent(this, "", offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, null); + } + } + }); + } + + public Container getClientArea() { + return this; + } + + public int getStepSize() { + return Math.round(model.getStepSize().floatValue() * (int)Math.pow(10, digitCount)); + } + + public void setStepSize(int stepSize) { + model.setStepSize(new Float((float)stepSize / (int)Math.pow(10, digitCount))); + } + + protected int minimum = 0; + protected int maximum = 100; + + public int getMinimum() { + return minimum; + } + + public int getMaximum() { + return maximum; + } + + public void setMinimum(int minimum) { + this.minimum = minimum; + } + + public void setMaximum(int maximum) { + this.maximum = maximum; + } + + public void setSelectedValue(int value) { + model.setValue(new Float((float)value / (int)Math.pow(10, digitCount))); + } + + public int getSelectedValue() { + return Math.round(((Number)model.getValue()).floatValue() * (int)Math.pow(10, digitCount)); + } + + public void copy() { + ((DefaultEditor)getEditor()).getTextField().copy(); + } + + public void cut() { + ((DefaultEditor)getEditor()).getTextField().cut(); + } + + public void paste() { + ((DefaultEditor)getEditor()).getTextField().paste(); + } + + protected int digitCount; + + public void setDigitCount(int digitCount) { + if(digitCount == this.digitCount) { + return; + } + this.digitCount = digitCount; + } + + public int getDigitCount() { + return digitCount; + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: setOpaque(false); break; + } + } + +} + +/** + * The spinner equivalent on the Swing side. + * @version 1.0 2006.03.12 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CSpinner extends CControl { + + public static class Factory { + private Factory() {} + + public static CSpinner newInstance(Spinner spinner, int style) { + return new CSpinnerImplementation(spinner, style); + } + + } + + public int getStepSize(); + + public void setStepSize(int stepSize); + + public int getMinimum(); + + public int getMaximum(); + + public void setMinimum(int minimum); + + public void setMaximum(int maximum); + + public void setSelectedValue(int value); + + public int getSelectedValue(); + + public void copy(); + + public void cut(); + + public void paste(); + + public void setDigitCount(int digitCount); + + public int getDigitCount(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabFolder.java new file mode 100644 index 00000000000..f2ab4edf2c6 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabFolder.java @@ -0,0 +1,164 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Image; +import java.awt.Rectangle; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JScrollBar; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.TabFolder; + +class CTabFolderImplementation extends JTabbedPane implements CTabFolder { + + protected TabFolder handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CTabFolderImplementation(TabFolder tabFolder, int style) { + this.handle = tabFolder; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + if((style & SWT.BORDER) != 0) { + setBorder(LookAndFeelUtils.getStandardBorder()); + } else { + setBorder(null); + } + setTabPlacement((style & SWT.BOTTOM) != 0? BOTTOM: TOP); + setTabLayoutPolicy(SCROLL_TAB_LAYOUT); + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + handle.processEvent(e); + } + }); + } + + public Container getClientArea() { + return this; + } + + public JScrollBar getHorizontalScrollBar() { + return null; + } + + public JScrollBar getVerticalScrollBar() { + return null; + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: { + Object isContentOpaqueObject = UIManager.get("TabbedPane.contentOpaque"); + UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE); + updateUI(); + UIManager.put("TabbedPane.contentOpaque", isContentOpaqueObject); + setOpaque(true); + break; + } + case BACKGROUND_INHERITANCE: { + Object isContentOpaqueObject = UIManager.get("TabbedPane.contentOpaque"); + UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE); + updateUI(); + UIManager.put("TabbedPane.contentOpaque", isContentOpaqueObject); + setOpaque(false); + break; + } + } + } + + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + int count = getTabCount(); + if(count > 0) { + Rectangle bounds = getUI().getTabBounds(this, count - 1); + size.width = Math.max(size.width, bounds.x + bounds.width + 10); + } + return size; + } + +} + +public interface CTabFolder extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CTabFolder newInstance(TabFolder tabFolder, int style) { + return new CTabFolderImplementation(tabFolder, style); + } + + } + + public void setTitleAt(int index, String title); + + public void setMnemonicAt(int tabIndex, int mnemonic); + + public void setIconAt(int index, Icon icon); + + public int getSelectedIndex(); + + public void setSelectedIndex(int index); + + public void setToolTipTextAt(int index, String toolTipText); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabItem.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabItem.java new file mode 100644 index 00000000000..3839584bc04 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTabItem.java @@ -0,0 +1,73 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JPanel; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.TabItem; + +class CTabItemImplementation extends JPanel implements CTabItem { + + protected TabItem handle; + + public CTabItemImplementation(TabItem tabItem, int style) { + super(new BorderLayout(0, 0)); + this.handle = tabItem; + init(style); + } + + protected void init(int style) { + setOpaque(false); + } + + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, ((CTabFolderImplementation)handle.getParent().handle).backgroundImageIcon); + super.paintComponent(g); + } + + public Component getContent() { + if(getComponentCount() > 0) { + return getComponent(0); + } + return null; + } + + public Dimension getPreferredSize() { + if(getComponentCount() > 0) { + Control swtHandle = ((CControl)getComponent(0)).getSWTHandle(); + if(!swtHandle.isDisposed()) { + Point size = swtHandle.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + return new Dimension(size.x, size.y); + } + } + return super.getPreferredSize(); + } + +} + +public interface CTabItem { + + public static class Factory { + private Factory() {} + + public static CTabItem newInstance(TabItem tabItem, int style) { + return new CTabItemImplementation(tabItem, style); + } + } + + public Component getContent(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTable.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTable.java new file mode 100644 index 00000000000..b74c59a5a80 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTable.java @@ -0,0 +1,1029 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ItemEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.PaintEvent; +import java.util.EventObject; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListSelectionModel; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JViewport; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +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.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.internal.swing.CTableItem.TableItemObject; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Table; + +class CTableImplementation extends JScrollPane implements CTable { + + protected Table handle; + protected JTable table; + protected boolean isCheckType; + + public Container getSwingComponent() { + return table; + } + + public Control getSWTHandle() { + return handle; + } + + protected class CheckBoxCellRenderer extends JPanel { + protected JStateCheckBox checkBox = new JStateCheckBox(); + protected Component component; + public CheckBoxCellRenderer(Component component) { + super(new BorderLayout(0, 0)); + this.component = component; + setOpaque(false); + checkBox.setOpaque(false); + add(checkBox, BorderLayout.WEST); + add(component, BorderLayout.CENTER); + addNotify(); + } + public JStateCheckBox getStateCheckBox() { + return checkBox; + } + public Component getComponent() { + return component; + } + } + + public class CTableModel extends AbstractTableModel { + protected Table table; + protected CTableModel(Table table) { + this.table = table; + } + public int getRowCount() { +// if(table.isDisposed()) return 0; +// return table.getItemCount(); + return rowCount; + } + public int getColumnCount() { + return table.getColumnCount(); + } + public Object getValueAt(int rowIndex, int columnIndex) { + return table.getItem(rowIndex).handle.getTableItemObject(columnIndex); + } + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CTableImplementation(Table table, int style) { + handle = table; + JViewport viewport = new JViewport() { + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + public Color getBackground() { + return CTableImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + }; + setViewport(viewport); + this.table = new JTable(new CTableModel(table)) { + { + CTableImplementation.this.setBackground(super.getBackground()); + } + public boolean isCellSelected(int row, int column) { + return super.isCellSelected(row, column) || isRowSelected(row); + } + public boolean getScrollableTracksViewportWidth() { + if(handle.isDisposed()) { + return false; + } + return handle.getColumnCount() == 0 && getPreferredSize().width < getParent().getWidth(); + } + public boolean getScrollableTracksViewportHeight() { + if(handle.isDisposed()) { + return false; + } + return getPreferredSize().height < getParent().getHeight(); + } + public Dimension getPreferredScrollableViewportSize() { + if(handle.getColumnCount() != 0) { + return getPreferredSize(); + } + // TODO: use some caching mecanism? + int columnCount = getColumnCount(); + int width = 0; + for(int i=0; i= table.getRowCount()) { + return; + } + Rectangle bounds = getCellRect(index, 0, true); + bounds.width = table.getWidth(); + bounds.height = table.getRowHeight(index); + table.scrollRectToVisible(bounds); + } + + public void ensureColumnVisible(int index) { + if(index < 0 || index >= table.getColumnCount()) { + return; + } + Rectangle bounds = new Rectangle(); + TableColumnModel columnModel = getColumnModel(); + for(int i=0; i getTextLimit()) { + return; + } + TextFilterEvent filterEvent = new TextFilterEvent(this, text, offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, attrs); + } + } + public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { + TextFilterEvent filterEvent = new TextFilterEvent(this, "", offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, null); + } + } + }); + } + + public Container getClientArea() { + return textArea; + } + + public String getText() { + return textArea.getText(); + } + + public String getText(int offs, int len) throws BadLocationException { + return textArea.getText(offs, len); + } + + public void setText(String text) { + textArea.setText(text); + } + + public void setSelectionStart(int start) { + textArea.setSelectionStart(start); + } + + public void setSelectionEnd(int end) { + textArea.setSelectionEnd(end); + } + + public int getSelectionStart() { + return textArea.getSelectionStart(); + } + + public int getSelectionEnd() { + return textArea.getSelectionEnd(); + } + + public void selectAll() { + textArea.selectAll(); + } + + public void setEditable(boolean isEditable) { + textArea.setEditable(isEditable); + } + + public void setEchoChar(char echoChar) { + } + + public char getEchoChar() { + return '\0'; + } + + public void copy() { + textArea.copy(); + } + + public void cut() { + textArea.cut(); + } + + public void paste() { + textArea.paste(); + } + + public void setTabSize(int tabSize) { + textArea.setTabSize(tabSize); + } + + public void replaceSelection(String content) { + textArea.replaceSelection(content); + } + + public boolean isEditable() { + return textArea.isEditable(); + } + + public int getCaretPosition() { + return textArea.getCaretPosition(); + } + + public int getLineCount() { + return textArea.getLineCount(); + } + + public Point getCaretLocation() { + int caretPosition = textArea.getCaretPosition(); + try { + int line = textArea.getLineOfOffset(caretPosition); + int width = textArea.getFontMetrics(textArea.getFont()).stringWidth(textArea.getText().substring(textArea.getLineStartOffset(line), caretPosition)); + return new Point(width, line * getRowHeight()); + } catch(BadLocationException e) { + } + return null; + } + + public void showSelection() { + try { + Rectangle rec1 = textArea.modelToView(getSelectionStart()); + Rectangle rec2 = textArea.modelToView(getSelectionEnd()); + if(rec1.y < rec2.y) { + Dimension size = textArea.getSize(); + rec1.x = 0; + rec1.width = size.width; + rec2.x = 0; + rec2.width = size.width; + } + rec1.add(rec2); + scrollRectToVisible(rec1); + } catch(Exception e) { + } + } + + public int getCaretLineNumber() { + try { + return textArea.getLineOfOffset(textArea.getCaretPosition()); + } catch(Exception e) { + return -1; + } + } + + public int getRowHeight() { + return textArea.getFontMetrics(textArea.getFont()).getHeight(); + } + + public void setComponentOrientation(ComponentOrientation o) { + super.setComponentOrientation(o); + textArea.setComponentOrientation(o); + } + + public Point getViewPosition() { + return getViewport().getViewPosition(); + } + + public void setViewPosition(Point p) { + getViewport().setViewPosition(p); + } + + public void setTextLimit(int limit) { + textLimit = limit; + String text = getText(); + if(text.length() > limit) { + setText(text.substring(0, limit)); + } + } + + protected int textLimit = Text.LIMIT; + + public int getTextLimit() { + return textLimit; + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: + setOpaque(true); + getViewport().setOpaque(true); + textArea.setOpaque(true); + break; + case BACKGROUND_INHERITANCE: + setOpaque(false); + getViewport().setOpaque(false); + textArea.setOpaque(false); + break; + } + } + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + textArea.setEnabled(enabled); + } + +} + +class CTextField extends JPasswordField implements CText { + + protected Text handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CTextField(Text text, int style) { + this.handle = text; + userAttributeHandler = new UserAttributeHandler(this); + setEchoChar('\0'); + init(style); + } + + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + +// public Cursor getCursor() { +// if(!isCursorSet()) { +// return super.getCursor(); +// } +// for(Component parent = this; (parent = parent.getParent()) != null; ) { +// if(parent.isCursorSet()) { +// Cursor cursor = parent.getCursor(); +// if(!(parent instanceof Window) || cursor != Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)) { +// return cursor; +// } +// } +// } +// return super.getCursor(); +// } + + protected KeyEvent keyEvent = null; + + protected void init(int style) { + if((style & SWT.BORDER) == 0) { + setBorder(null); + } + if((style & SWT.CENTER) != 0) { + setHorizontalAlignment(CENTER); + } else if((style & SWT.RIGHT) != 0) { + setHorizontalAlignment(RIGHT); + } + setEditable((style & SWT.READ_ONLY) == 0); + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + keyEvent = e; + } + public void keyReleased(KeyEvent e) { + keyEvent = null; + } + public void keyTyped(KeyEvent e) { + } + }); + getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { + handle.processEvent(e); + } + public void insertUpdate(DocumentEvent e) { + handle.processEvent(e); + } + public void removeUpdate(DocumentEvent e) { + handle.processEvent(e); + } + }); + ((AbstractDocument)getDocument()).setDocumentFilter(new DocumentFilter() { +// public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { +// } + public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { + if(getText().length() - length + text.length() > getTextLimit()) { + return; + } + TextFilterEvent filterEvent = new TextFilterEvent(this, text, offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, attrs); + } + } + public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { + TextFilterEvent filterEvent = new TextFilterEvent(this, "", offset, length, keyEvent); + handle.processEvent(filterEvent); + String s = filterEvent.getText(); + if(s != null) { + super.replace(fb, offset, length, s, null); + } + } + }); + } + + public Container getClientArea() { + return this; + } + + public void setText(String text) { + super.setText(text.replaceAll("[\r\n]", "")); + } + + public void setEchoChar(char c) { + super.setEchoChar(c); + if(c == '\0') { + LookAndFeelUtils.applyTextFieldStyle(this); + } else { + LookAndFeelUtils.applyPasswordFieldStyle(this); + } + } + + public void setTabSize(int tabSize) { + } + + public int getLineCount() { + return 1; + } + + public Point getCaretLocation() { + return new Point(getCaretPosition(), 0); + } + + public void showSelection() { + try { + Rectangle rec1 = modelToView(getSelectionStart()); + Rectangle rec2 = modelToView(getSelectionEnd()); + rec1.add(rec2); + scrollRectToVisible(rec1); + } catch(Exception e) { + } + } + + public int getCaretLineNumber() { + return 0; + } + + public int getRowHeight() { + return getFontMetrics(getFont()).getHeight(); + } + + public Point getViewPosition() { + try { + Rectangle rec1 = modelToView(0); + return new Point(rec1.x, rec1.y); + } catch(Exception e) { + } + return new Point(0, 0); + } + + public void setViewPosition(Point p) { + try { + Rectangle rec1 = modelToView(p.x); + scrollRectToVisible(rec1); + } catch(Exception e) { + } + } + + public void setTextLimit(int limit) { + textLimit = limit; + String text = getText(); + if(text.length() > limit) { + setText(text.substring(0, limit)); + } + } + + protected int textLimit = Text.LIMIT; + + public int getTextLimit() { + return textLimit; + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(userAttributeHandler == null) { + return super.getCursor(); + } + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + for(Control parent = handle; parent != null && parent.handle != null; parent = parent.getParent()) { + Cursor cursor = ((CControl)parent.handle).getUserAttributeHandler().cursor; + if(cursor != null) { + return cursor; + } + } + return super.getCursor(); + } + + protected ImageIcon backgroundImageIcon; + + public void setBackgroundImage(Image backgroundImage) { + this.backgroundImageIcon = backgroundImage == null? null: new ImageIcon(backgroundImage); + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case PREFERRED_BACKGROUND_INHERITANCE: + case NO_BACKGROUND_INHERITANCE: + setOpaque(true); + break; + case BACKGROUND_INHERITANCE: + setOpaque(false); + break; + } + } + + public JScrollBar getHorizontalScrollBar() { + // No support for scrolling in SIMPLE style. + return null; + } + + public JScrollBar getVerticalScrollBar() { + // No support for scrolling in SIMPLE style. + return null; + } + +} + +/** + * The text equivalent on the Swing side. + * @version 1.0 2005.08.30 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public interface CText extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CText newInstance(Text text, int style) { + if((style & SWT.MULTI) != 0) { + return new CTextMulti(text, style); + } + return new CTextField(text, style); + } + + } + + public String getText(); + + public String getText(int offs, int len) throws BadLocationException; + + public void setText(String text); + + public void setSelectionStart(int start); + + public void setSelectionEnd(int end); + + public int getSelectionStart(); + + public int getSelectionEnd(); + + public void selectAll(); + + public void setEditable(boolean isEditable); + + public void setEchoChar(char echoChar); + + public char getEchoChar(); + + public void copy(); + + public void cut(); + + public void paste(); + + public void setTabSize(int tabSize); + + public void replaceSelection(String content); + + public boolean isEditable(); + + public int getCaretPosition(); + + public int getLineCount(); + + public Point getCaretLocation(); + + public void showSelection(); + + public int getCaretLineNumber(); + + public int getRowHeight(); + + public void setComponentOrientation(ComponentOrientation o); + + public Point getViewPosition(); + + public void setViewPosition(Point p); + + public void setTextLimit(int limit); + + public int getTextLimit(); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolBar.java new file mode 100644 index 00000000000..fbf9cf0972f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolBar.java @@ -0,0 +1,121 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Image; + +import javax.swing.JScrollBar; +import javax.swing.JToolBar; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; + +class CToolBarImplementation extends JToolBar implements CToolBar { + + protected ToolBar handle; + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CToolBarImplementation(ToolBar toolBar, int style) { + super((style & SWT.VERTICAL) != 0? JToolBar.VERTICAL: JToolBar.HORIZONTAL); + this.handle = toolBar; + userAttributeHandler = new UserAttributeHandler(this); + init(style); + } + + protected void init(int style) { + setFloatable(false); + if((style & SWT.BORDER) != 0) { + setBorder(javax.swing.BorderFactory.createEtchedBorder()); + } + if((style & SWT.WRAP) != 0) { + setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0)); +// } else { +// setLayout(null); + } + Utils.installMouseListener(this, handle); + Utils.installKeyListener(this, handle); + Utils.installFocusListener(this, handle); + Utils.installComponentListener(this, handle); + } + + public Container getClientArea() { + return this; + } + + public JScrollBar getHorizontalScrollBar() { + return null; + } + + public JScrollBar getVerticalScrollBar() { + return null; + } + + public Color getBackground() { + return userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + public Color getForeground() { + return userAttributeHandler != null && userAttributeHandler.foreground != null? userAttributeHandler.foreground: super.getForeground(); + } + public Font getFont() { + return userAttributeHandler != null && userAttributeHandler.font != null? userAttributeHandler.font: super.getFont(); + } + public Cursor getCursor() { + if(Utils.globalCursor != null) { + return Utils.globalCursor; + } + return userAttributeHandler != null && userAttributeHandler.cursor != null? userAttributeHandler.cursor: super.getCursor(); + } + + public void setBackgroundImage(Image backgroundImage) { + // TODO: implement + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + switch(backgroundInheritanceType) { + case NO_BACKGROUND_INHERITANCE: setOpaque(true); break; + case PREFERRED_BACKGROUND_INHERITANCE: + case BACKGROUND_INHERITANCE: setOpaque(false); break; + } + } + + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, getComponentCount() == 0? h: getPreferredSize().height); + } + +} + +public interface CToolBar extends CScrollable { + + public static class Factory { + private Factory() {} + + public static CToolBar newInstance(ToolBar toolBar, int style) { + return new CToolBarImplementation(toolBar, style); + } + + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolItem.java new file mode 100644 index 00000000000..bf78d28fcec --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CToolItem.java @@ -0,0 +1,264 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JToggleButton; +import javax.swing.JToolBar.Separator; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.ToolItem; + +class CToolItemPush extends JButton implements CToolItem { + + protected ToolItem handle; + + public CToolItemPush(ToolItem toolItem, int style) { + handle = toolItem; + init(style); + } + + protected void init(int style) { + setFocusable(false); + setHorizontalTextPosition(CENTER); + setVerticalTextPosition(BOTTOM); + setMargin(new Insets(0, 1, 0, 1)); + Utils.installMouseListener(this, handle.getParent()); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handle.processEvent(e); + } + }); + } + + public void setWidth(int width) { + } + +} + +class CToolItemCheck extends JToggleButton implements CToolItem { + + protected ToolItem handle; + + public CToolItemCheck(ToolItem toolItem, int style) { + handle = toolItem; + init(style); + } + + protected void init(int style) { + setFocusable(false); +// setHorizontalTextPosition(CENTER); +// setVerticalTextPosition(BOTTOM); + setMargin(new Insets(0, 1, 0, 1)); + Utils.installMouseListener(this, handle.getParent()); + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + handle.processEvent(e); + } + }); + } + + public void setWidth(int width) { + } + +} + +class CToolItemRadio extends JToggleButton implements CToolItem { + + protected ToolItem handle; + + public CToolItemRadio(ToolItem toolItem, int style) { + handle = toolItem; + init(style); + } + + protected void init(int style) { + setFocusable(false); + setHorizontalTextPosition(CENTER); + setVerticalTextPosition(BOTTOM); + setMargin(new Insets(0, 1, 0, 1)); + Utils.installMouseListener(this, handle.getParent()); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handle.processEvent(e); + } + }); + } + + public void setWidth(int width) { + } + +} + +class CToolItemDropDown extends CComboButton implements CToolItem { + + protected ToolItem handle; + + public CToolItemDropDown(ToolItem toolItem, int style) { + handle = toolItem; + init(style); + } + + protected void init(int style) { + setFocusable(false); + setHorizontalTextPosition(CENTER); + setVerticalTextPosition(BOTTOM); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handle.processEvent(e); + } + }); + } + + public boolean isSelected() { + return false; + } + + public void setSelected(boolean isSelected) { + } + + public void setWidth(int width) { + } + +} + +class CToolItemSeparator extends Separator implements CToolItem { + + protected ToolItem handle; + + public CToolItemSeparator(ToolItem toolItem, int style) { + handle = toolItem; + init(style); + } + + protected void init(int style) { + setLayout(null); + Utils.installMouseListener(this, handle.getParent()); + } + + public Dimension getMaximumSize() { + Dimension size = super.getMaximumSize(); + if(getComponentCount() == 1) { + return new Dimension(size.width, getComponent(0).getHeight()); + } + return size; + } + + public Dimension getMinimumSize() { + Dimension size = super.getMinimumSize(); + if(getComponentCount() == 1) { + return new Dimension(size.width, getComponent(0).getHeight()); + } + return size; + } + + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + if(getComponentCount() == 1) { + return new Dimension(size.width, getComponent(0).getHeight()); + } + return size; + } + +// public Dimension getMinimumSize() { +// if(getComponentCount() == 1) { +// return getComponent(0).getSize(); +// } +// return super.getMinimumSize(); +// } + +// public Dimension getPreferredSize() { +// if(getComponentCount() == 1) { +// return getComponent(0).getSize(); +// } +// return super.getPreferredSize(); +// } + + public boolean isSelected() { + return false; + } + + public void setSelected(boolean isSelected) { + } + + public void setIcon(Icon icon) { + } + + public void setDisabledIcon(Icon disabledIcon) { + } + + public void setRolloverIcon(Icon rolloverIcon) { + } + + public void setText(String text) { + } + + public void setMnemonic(char mnemonic) { + } + + public void setWidth(int width) { + setSeparatorSize(new Dimension(width, getSize().height)); + } + +} + +public interface CToolItem { + + public static class Factory { + private Factory() {} + + public static CToolItem newInstance(ToolItem toolItem, int style) { + if((style & SWT.PUSH) != 0) { + return new CToolItemPush(toolItem, style); + } + if((style & SWT.CHECK) != 0) { + return new CToolItemCheck(toolItem, style); + } + if((style & SWT.RADIO) != 0) { + return new CToolItemRadio(toolItem, style); + } + if((style & SWT.DROP_DOWN) != 0) { + return new CToolItemDropDown(toolItem, style); + } + if((style & SWT.SEPARATOR) != 0) { + return new CToolItemSeparator(toolItem, style); + } + return null; + } + + } + + public boolean isSelected(); + + public void setSelected(boolean isSelected); + + public String getToolTipText(); + + public void setToolTipText(String toolTipText); + + public void setIcon(Icon icon); + + public void setDisabledIcon(Icon disabledIcon); + + public void setRolloverIcon(Icon rolloverIcon); + + public void setText(String text); + + public void setMnemonic(char mnemonic); + + public void setWidth(int width); + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTree.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTree.java new file mode 100644 index 00000000000..cd197d6d49c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/CTree.java @@ -0,0 +1,964 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ItemEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.PaintEvent; +import java.util.EventObject; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JViewport; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.event.TableColumnModelListener; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Tree; + +class CTreeImplementation extends JScrollPane implements CTree { + + protected Tree handle; + protected JTreeTable treeTable; + protected DefaultMutableTreeTableNode rootNode; + protected boolean isCheckType; + + public Container getSwingComponent() { + return treeTable; + } + + public Control getSWTHandle() { + return handle; + } + + protected class CheckBoxCellRenderer extends JPanel { + protected JStateCheckBox checkBox = new JStateCheckBox(); + protected Component component; + public CheckBoxCellRenderer(Component component) { + super(new BorderLayout(0, 0)); + this.component = component; + setOpaque(false); + checkBox.setOpaque(false); + add(checkBox, BorderLayout.WEST); + add(component, BorderLayout.CENTER); + addNotify(); + } + public JStateCheckBox getStateCheckBox() { + return checkBox; + } + public Component getComponent() { + return component; + } + } + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public CTreeImplementation(Tree tree, int style) { + handle = tree; + setViewport(new JViewport() { + public boolean isOpaque() { + return backgroundImageIcon == null && super.isOpaque(); + } + protected void paintComponent(Graphics g) { + Utils.paintTiledImage(this, g, backgroundImageIcon); + super.paintComponent(g); + } + public Color getBackground() { + return CTreeImplementation.this != null && userAttributeHandler != null && userAttributeHandler.background != null? userAttributeHandler.background: super.getBackground(); + } + }); + rootNode = new DefaultMutableTreeTableNode() { + public void insert(MutableTreeNode newChild, int childIndex) { + super.insert(newChild, childIndex); + getModel().nodesWereInserted(this, new int[] {childIndex}); + treeTable.expandPath(new TreePath(rootNode.getPath())); + } + }; + treeTable = new JTreeTable(new DefaultTreeModel(rootNode)) { + protected JTableHeader createDefaultTableHeader() { + return new JTableHeader(getColumnModel()) { + public String getToolTipText(MouseEvent e) { + int index = columnModel.getColumnIndexAtX(e.getX()); + if(index < 0) { + return null; + } + return ((CTreeColumn)columnModel.getColumn(index)).getToolTipText(); + } + public void paint(Graphics g) { + super.paint(g); + if(handle.getSortDirection() != SWT.NONE) { + org.eclipse.swt.widgets.TreeColumn sortColumn = handle.getSortColumn(); + if(sortColumn != null) { + Rectangle bounds = getCellRect(-1, CTreeImplementation.this.treeTable.convertColumnIndexToView(handle.indexOf(sortColumn)), false); + TableColumn draggedColumn = getDraggedColumn(); + Shape clip = g.getClip(); + if(draggedColumn != null) { + int draggedDistance = getDraggedDistance(); + if(((CTreeColumn)draggedColumn).getTreeColumn() == sortColumn) { + bounds.x += draggedDistance; + } else { + Rectangle dragBounds = getCellRect(-1, CTreeImplementation.this.treeTable.convertColumnIndexToView(handle.indexOf(((CTreeColumn)draggedColumn).getTreeColumn())), true); + dragBounds.x += draggedDistance; + bounds.height = getHeight(); + if(bounds.x < dragBounds.x) { + g.clipRect(0, 0, dragBounds.x, bounds.height); + } else { + int x = dragBounds.x + dragBounds.width; + g.clipRect(x, 0, getWidth() - x, bounds.height); + } + } + } + paintSortArrow(g, bounds); + g.setClip(clip); + } + } + } + protected void paintSortArrow(Graphics g, Rectangle bounds) { +// Color color = new Color(11, 80, 48); + Color color = getBackground().darker(); + int priority = 0; + int height = Math.round(getHeight() / 1.5f); + int x = bounds.x + bounds.width; + int y = 1; + boolean descending = handle.getSortDirection() == SWT.DOWN; + // In a compound sort, make each succesive triangle 20% + // smaller than the previous one. + int dx = (int)(height/2*Math.pow(0.8, priority)); + if(bounds.width < dx * 3) { + return; + } + x -= dx * 2; + if(dx % 2 != 0) { + dx++; + } + int dy = descending ? dx / 2 : -dx / 2; + // Align icon (roughly) with font baseline. + y = y + 4*height/6 + (descending ? -dy : 0); + int shift = descending ? 1 : -1; + g.translate(x, y); + + g.setColor(color); + g.fillPolygon(new int[] {0, dx / 2, dx, 0}, new int[] {0, dy, 0, 0}, 4); + + // Right diagonal. + g.setColor(color.darker()); + g.drawLine(dx / 2, dy, 0, 0); + g.drawLine(dx / 2, dy + shift, 0, shift); + + // Left diagonal. + g.setColor(color.brighter()); + g.drawLine(dx / 2, dy, dx, 0); + g.drawLine(dx / 2, dy + shift, dx, shift); + + // Horizontal line. + if (descending) { + g.setColor(color.darker().darker()); + } else { +// g.setColor(color.brighter().brighter()); + g.setColor(color.brighter()); + } + g.drawLine(dx, 0, 0, 0); + + g.setColor(color); + g.translate(-x, -y); + } + }; + } + public boolean getScrollableTracksViewportWidth() { + return handle.isDisposed()? false: handle.getColumnCount() == 0 && getPreferredSize().width < getParent().getWidth(); + } + public boolean getScrollableTracksViewportHeight() { + return getPreferredSize().height < getParent().getHeight(); + } + public Dimension getPreferredScrollableViewportSize() { + if(handle.getColumnCount() != 0) { + return getPreferredSize(); + } + // TODO: use some caching mecanism? + int columnCount = treeTable.getColumnModel().getColumnCount(); + int width = 0; + for(int i=0; i= treeTable.getRowCount()) { + return; + } + Rectangle bounds = getCellRect(index, 0, true); + bounds.width = treeTable.getWidth(); + bounds.height = treeTable.getRowHeight(index); + treeTable.scrollRectToVisible(bounds); + } + + public void ensureColumnVisible(int index) { + if(index < 0 || index >= treeTable.getColumnCount()) { + return; + } + Rectangle bounds = new Rectangle(); + TableColumnModel columnModel = getColumnModel(); + for(int i=0; i= 0; + public static final boolean IS_JAVA_5_OR_GREATER = IS_JAVA_6_OR_GREATER || JAVA_VERSION.compareTo("1.5") >= 0; + + /** + * When a class does not exist on a certain version of Java, it would generate a + * NoClassDefFoundError simply when the surrounding class gets loaded. The fix is to + * surround the access by an intermediate class. Using this particular ProtectedCode + * class is not mandatory but allows a better tracking of such compatibility issues. + * Here is an example:
    + *
    +   * if(Compatibility.IS_JAVA_5_OR_GREATER) {
    +   *   new Compatibility.ProtectedCode() {{
    +   *     // Code accessing classes that only exist in Java 5.0+
    +   *   }};
    +   * }
    +   * 
    + * Note that in the example above, the code is invoked in the constructor of this + * intermediate class. + */ + public static abstract class ProtectedCode { + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ComponentBorderResizer.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ComponentBorderResizer.java new file mode 100644 index 00000000000..a9d1801b8cf --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/ComponentBorderResizer.java @@ -0,0 +1,154 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.event.MouseInputAdapter; + +public class ComponentBorderResizer { + + protected ComponentBorderResizer() {} + + public static void handle(final Component component, final JComponent borderedComponent) { + MouseInputAdapter windowMouseInputAdapter = new MouseInputAdapter() { + protected boolean moveTop; + protected boolean moveLeft; + protected boolean moveBottom; + protected boolean moveRight; + protected Point originalLocation; + protected static final int MIN_WIDTH = 100; + protected static final int MIN_HEIGHT = 60; + public void mousePressed(MouseEvent e) { + if(e.getButton() != MouseEvent.BUTTON1) { + return; + } +// if(isMaximized()) { +// return; +// } + originalLocation = e.getPoint(); + } + public void mouseReleased(MouseEvent e) { + if(e.getButton() != MouseEvent.BUTTON1) { + return; + } + originalLocation = null; + } + public void mouseDragged(MouseEvent e) { + if(originalLocation == null) { + return; + } + Rectangle bounds = component.getBounds(); + if(moveLeft) { + int diffX = e.getX() - originalLocation.x; + bounds.x += diffX; + bounds.width -= diffX; + Insets borderInsets = borderedComponent.getBorder().getBorderInsets(borderedComponent); + int minWidth = MIN_WIDTH + borderInsets.left + borderInsets.right; + if(bounds.width < minWidth) { + bounds.x -= minWidth - bounds.width; + bounds.width = minWidth; + } + component.setBounds(bounds); + } else if(moveRight) { + int diffX = e.getX() - originalLocation.x; + originalLocation.x += diffX; + bounds.width += diffX; + Insets borderInsets = borderedComponent.getBorder().getBorderInsets(borderedComponent); + int minWidth = MIN_WIDTH + borderInsets.left + borderInsets.right; + if(bounds.width < minWidth) { + originalLocation.x += minWidth - bounds.width; + bounds.width = minWidth; + } + component.setBounds(bounds); + } + if(moveTop) { + int diffY = e.getY() - originalLocation.y; + bounds.y += diffY; + bounds.height -= diffY; + Insets borderInsets = borderedComponent.getBorder().getBorderInsets(borderedComponent); + int minHeight = MIN_HEIGHT + borderInsets.top + borderInsets.bottom; + if(bounds.height < minHeight) { + bounds.y -= minHeight - bounds.height; + bounds.height = minHeight; + } + component.setBounds(bounds); + } else if(moveBottom) { + int diffY = e.getY() - originalLocation.y; + originalLocation.y += diffY; + bounds.height += diffY; + Insets borderInsets = borderedComponent.getBorder().getBorderInsets(borderedComponent); + int minHeight = MIN_HEIGHT + borderInsets.top + borderInsets.bottom; + if(bounds.height < minHeight) { + originalLocation.y += minHeight - bounds.height; + bounds.height = minHeight; + } + component.setBounds(bounds); + } + } + public void mouseMoved(MouseEvent e) { + adjustResizing(e.getPoint()); + } + public void mouseEntered(MouseEvent e) { + adjustResizing(e.getPoint()); + } + public void mouseExited(MouseEvent e) { + adjustResizing(e.getPoint()); + } + protected int THRESHOLD = 20; + protected void adjustResizing(Point point) { + if(originalLocation != null) { + return; + } + moveTop = false; + moveLeft = false; + moveBottom = false; + moveRight = false; + Insets borderInsets = borderedComponent.getBorder().getBorderInsets(borderedComponent); + Dimension size = borderedComponent.getSize(); + if(!new Rectangle(borderInsets.left, borderInsets.top, size.width - borderInsets.left - borderInsets.right, size.height - borderInsets.top - borderInsets.bottom).contains(point)) { +// if(isMaximized()) { +// rootPane.setCursor(null); +// return; +// } + if(point.x < THRESHOLD) { + moveLeft = true; + } else if(point.x > size.width - THRESHOLD) { + moveRight = true; + } + if(point.y < THRESHOLD) { + moveTop = true; + } else if(point.y >= size.height - borderInsets.bottom) { + moveBottom = true; + } + } + if(moveTop && moveLeft || moveBottom && moveRight) { + borderedComponent.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)); + } else if(moveTop && moveRight || moveBottom && moveLeft) { + borderedComponent.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)); + } else if(moveTop || moveBottom) { + borderedComponent.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); + } else if(moveLeft || moveRight) { + borderedComponent.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); + } else { + borderedComponent.setCursor(null); + } + } + }; + borderedComponent.addMouseListener(windowMouseInputAdapter); + borderedComponent.addMouseMotionListener(windowMouseInputAdapter); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultMutableTreeTableNode.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultMutableTreeTableNode.java new file mode 100644 index 00000000000..7ac7e340664 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultMutableTreeTableNode.java @@ -0,0 +1,85 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import javax.swing.tree.DefaultMutableTreeNode; + +public class DefaultMutableTreeTableNode extends DefaultMutableTreeNode implements TreeTableNode { + + protected Object[] userObjects; + + public DefaultMutableTreeTableNode() { + this(null); + } + + public DefaultMutableTreeTableNode(Object[] userObjects) { + this(userObjects, true); + } + + public DefaultMutableTreeTableNode(Object[] userObjects, boolean allowsChildren) { + super(null, allowsChildren); + setUserObjects(userObjects); + } + + + public void setUserObjects(Object[] objects) { + if(objects == null || objects.length == 0) { + setUserObject(null); + userObjects = null; + return; + } + setUserObject(objects[0]); + if(objects.length == 1) { + userObjects = null; + } else { + userObjects = new Object[objects.length - 1]; + System.arraycopy(objects, 1, userObjects, 0, userObjects.length); + } + } + + public Object[] getUserObjects() { + if(userObjects == null) { + return new Object[] {getUserObject()}; + } + Object[] objects = new Object[userObjects.length + 1]; + System.arraycopy(userObjects, 0, objects, 1, userObjects.length); + objects[0] = getUserObject(); + return objects; + } + + public Object getUserObject(int index) { + if(index == 0) { + return getUserObject(); + } + index--; + if(userObjects == null || userObjects.length <= index) { + return null; + } + return userObjects[index]; + } + + public void setUserObject(int index, Object object) { + if(index == 0) { + setUserObject(object); + } else { + index--; + if(userObjects == null) { + userObjects = new Object[index + 1]; + userObjects[index] = object; + } else { + if(userObjects.length <= index) { + Object[] newUserObjects = new Object[index + 1]; + System.arraycopy(userObjects, 0, newUserObjects, 0, userObjects.length); + userObjects = newUserObjects; + } + userObjects[index] = object; + } + } + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultTreeTableCellRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultTreeTableCellRenderer.java new file mode 100644 index 00000000000..cf79ee16db6 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DefaultTreeTableCellRenderer.java @@ -0,0 +1,53 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Component; +import java.awt.Graphics; + +import javax.swing.JLabel; +import javax.swing.tree.DefaultTreeCellRenderer; + +public class DefaultTreeTableCellRenderer implements TreeTableCellRenderer { + + static interface CellPainter { + public void paintCell(Graphics g); + } + + protected class InnerTreeCellRenderer extends DefaultTreeCellRenderer implements CellPainter { + protected void paintComponent(Graphics g) { + DefaultTreeTableCellRenderer.this.paintComponent(renderer, g); + } + public void paintCell(Graphics g) { + super.paintComponent(g); + } + } + + protected InnerTreeCellRenderer renderer = createInnerTreeCellRenderer(); + + protected InnerTreeCellRenderer createInnerTreeCellRenderer() { + return new InnerTreeCellRenderer(); + } + + protected void paintComponent(CellPainter c, Graphics g) { + c.paintCell(g); + } + + public Component getTreeTableCellRendererComponent(JTreeTable treeTable, Object value, boolean selected, boolean expanded, boolean leaf, int row, int column, boolean hasFocus) { + if(column == 0) { +// treeTable.getVModel().getValueAt(row, column); +// value = treeTable.getInnerTable().getValueAt(row, treeTable.convertColumnIndexToView(0)); + } + Component component = renderer.getTreeCellRendererComponent(treeTable.getInnerTree(), value, selected, expanded, leaf, row, hasFocus); + if(column != 0 && component instanceof JLabel) { + ((JLabel)component).setIcon(null); + } + return component; + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DisabledStatePanel.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DisabledStatePanel.java new file mode 100644 index 00000000000..6f9d091c20c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/DisabledStatePanel.java @@ -0,0 +1,150 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.RootPaneContainer; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public class DisabledStatePanel extends JPanel { + + protected Control control; + + protected HierarchyListener hierarchyListener = new HierarchyListener() { + public void hierarchyChanged(HierarchyEvent e) { + long changedFlags = e.getChangeFlags(); + if((changedFlags & HierarchyEvent.HIERARCHY_CHANGED) != 0) { + Component component = control.handle; + Container parent = component.getParent(); + boolean isRevalidationNeeded = false; + if(parent != null) { + parent.add(component); + checkFocus(); + isRevalidationNeeded = true; + } else { + parent = getParent(); + if(parent != null) { + parent.remove(DisabledStatePanel.this); + isRevalidationNeeded = true; + } + } + if(isRevalidationNeeded) { + if(parent instanceof JComponent) { + ((JComponent)parent).revalidate(); + } else { + parent.invalidate(); + parent.validate(); + parent.repaint(); + } + } + } + } + }; + + protected ComponentListener componentListener = new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + adjustBounds(); + } + public void componentMoved(ComponentEvent e) { + adjustBounds(); + } + }; + + public DisabledStatePanel(Control control) { + super(null); + this.control = control; + enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.KEY_EVENT_MASK); + setOpaque(false); + adjustBounds(); + Component component = control.handle; + Container parent = component.getParent(); + if(parent != null) { + if(parent instanceof RootPaneContainer) { + ((RootPaneContainer)parent).getContentPane().add(this, 0); + } else { + parent.add(this, 0); + } + revalidate(); + checkFocus(); + } + component.addHierarchyListener(hierarchyListener); + component.addComponentListener(componentListener); + } + + protected void checkFocus() { + Component component = control.handle; + Container parent = component.getParent(); + if(component.isFocusOwner()) { + parent.transferFocus(); + } else if(component instanceof Container) { + Window window = SwingUtilities.getWindowAncestor(parent); + if(window != null) { + Component focusOwner = window.getFocusOwner(); + if(focusOwner != null && ((Container)component).isAncestorOf(focusOwner)) { + parent.transferFocus(); + } + } + } + } + + protected void processEvent(AWTEvent e) { + if(control.isDisposed()) { + return; + } + Composite parent = control.getParent(); + if(e instanceof MouseEvent) { + MouseEvent me = (MouseEvent)e; + Point point = SwingUtilities.convertPoint(control.handle, me.getPoint(), parent.handle); + if(e instanceof MouseWheelEvent) { + MouseWheelEvent mwe = (MouseWheelEvent)e; + parent.processEvent(new MouseWheelEvent(parent.handle, mwe.getID(), mwe.getWhen(), mwe.getModifiersEx(), point.x, point.y, mwe.getClickCount(), mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation())); + } else { + parent.processEvent(new MouseEvent(parent.handle, me.getID(), me.getWhen(), me.getModifiersEx(), point.x, point.y, me.getClickCount(), me.isPopupTrigger(), me.getButton())); + } + } else if(e instanceof KeyEvent) { + KeyEvent ke = (KeyEvent)e; + parent.processEvent(new KeyEvent(parent.handle, ke.getID(), ke.getWhen(), ke.getModifiersEx(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation())); + } + } + + protected void adjustBounds() { + if(control != null && control.handle != null) { + setBounds(control.handle.getBounds()); + } + } + + public void release() { + Component component = control.handle; + Container parent = component.getParent(); + if(parent != null) { + parent.remove(this); + revalidate(); + } + component.removeHierarchyListener(hierarchyListener); + component.removeComponentListener(componentListener); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBar.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBar.java new file mode 100644 index 00000000000..8805a099458 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JCoolBar.java @@ -0,0 +1,517 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.util.Vector; + +import javax.swing.JPanel; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; + +public class JCoolBar extends JPanel { + + protected static final int FLOATING_MARGIN = 10; + + public JCoolBar() { +// setComponentOrientation(java.awt.ComponentOrientation.ComponentOrientation.RIGHT_TO_LEFT); + setLayout(new JCoolBarLayout()); + } + + protected boolean isLocked; + + public boolean isLocked() { + return isLocked; + } + + public void setLocked(boolean isLocked) { + this.isLocked = isLocked; + int componentCount = getComponentCount(); + for (int i = 0; i < componentCount; i++) { + ((JCoolBarItem)getComponent(i)).setLocked(isLocked); + } + } + + public void setWrappedIndices(int[] wrappedIndices) { + int componentCount = getComponentCount(); + boolean[] wrappedArray = new boolean[componentCount]; + for(int i=0; i= 0 && wrappedIndex < componentCount) { + wrappedArray[wrappedIndex] = true; + } + } + for (int i = 0; i < wrappedArray.length; i++) { + ((JCoolBarItem)getComponent(i)).setWrapped(wrappedArray[i]); + } + revalidate(); + repaint(); + } + + public int getRowCount() { + int rowCount = getItemCount()>0? 1: 0; + for(int i=0; i size.width + FLOATING_MARGIN || mouseLocation.y > size.height + FLOATING_MARGIN)) { + Point itemLocation = item.getLocation(); + SwingUtilities.convertPointToScreen(itemLocation, this); + SwingUtilities.convertPointToScreen(mouseLocation, this); + SwingUtilities.convertPointToScreen(this.mouseLocation, this); + mouseLocation = new Point(itemLocation.x - this.mouseLocation.x + mouseLocation.x, itemLocation.y - this.mouseLocation.y + mouseLocation.y); + setFloating(itemIndex, mouseLocation); + this.mouseLocation = null; + break; + } + int offsetX = mouseLocation.x - this.mouseLocation.x; + if(mouseLocation.y < item.getY()) { + if(getLineItems(itemIndex).length > 1) { + moveUp(itemIndex); + } else { + mergeUp(itemIndex); + } + } else if(mouseLocation.y > item.getY() + item.getHeight()) { + if(getLineItems(itemIndex).length > 1) { + moveDown(itemIndex); + } else { + mergeDown(itemIndex); + } + } + itemIndex = getItemIndex(item); + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + if(offsetX < 0) { + if(isLeftToRight) { + moveLeading(itemIndex, -offsetX); + } else { + moveTrailing(itemIndex, -offsetX); + } + } else if(offsetX > 0) { + if(isLeftToRight) { + moveTrailing(itemIndex, offsetX); + } else { + moveLeading(itemIndex, offsetX); + } + } + this.mouseLocation = mouseLocation; + break; + } + case MouseEvent.MOUSE_RELEASED: { + this.mouseLocation = null; + JCoolBarItem item = (JCoolBarItem)mouseEvent.getComponent(); + item.setXSpacing(Math.max(0, item.getXSpacing())); + break; + } + } + } + + + protected JCoolBarItem[] getLineItems(int itemIndex) { + if(itemIndex < 0) { + return new JCoolBarItem[0]; + } + int count = getItemCount(); + if(itemIndex >= count) { + return new JCoolBarItem[0]; + } + JCoolBarItem item = getItem(itemIndex); + if(itemIndex != 0 && !item.isWrapped()) { + return getLineItems(itemIndex - 1); + } + Vector itemList = new Vector(); + for(int i=itemIndex; i= item.getX()) { + break; + } + } else { + if(nextItem.getX() + nextItem.getWidth() <= item.getX() + item.getWidth()) { + break; + } + } + offset++; + nextItem = null; + } + if(offset == lineItems.length) { + item.setWrapped(false); + } else { + remove(item); + add(item, itemIndex - lineItems.length + offset); + if(offset == 0) { + item.setWrapped(true); + lineItems[0].setWrapped(false); + } else { + item.setWrapped(false); + } + } + if(offset > 0) { + JCoolBarItem previousLineItem = lineItems[offset - 1]; + if(isLeftToRight) { + item.setXSpacing(item.getX() - previousLineItem.getX() - previousLineItem.getPreferredSize().width); + } else { + item.setXSpacing(previousLineItem.getX() + previousLineItem.getWidth() - previousLineItem.getPreferredSize().width - item.getX() - item.getWidth()); + } + } else { + int xSpacing = item.getXSpacing(); + int newXSpacing; + if(isLeftToRight) { + newXSpacing = item.getX(); + } else { + newXSpacing = getWidth() - item.getX() - item.getWidth(); + } + if(xSpacing < 0) { + newXSpacing += xSpacing; + } + item.setXSpacing(newXSpacing); + } + if(offset < lineItems.length) { + JCoolBarItem nextLineItem = lineItems[offset]; + if(isLeftToRight) { + nextItem.setXSpacing(nextLineItem.getX() - item.getX() - item.getPreferredSize().width); + } else { + nextItem.setXSpacing(item.getX() + item.getWidth() - item.getPreferredSize().width - nextLineItem.getX() - nextLineItem.getWidth()); + } + } + revalidate(); + repaint(); + setSize(new Dimension(getSize().width, getPreferredSize().height)); + } + + protected void moveDown(int itemIndex) { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + JCoolBarItem item = getItem(itemIndex); + JCoolBarItem[] lineItems = getLineItems(itemIndex); + JCoolBarItem lineItem0 = lineItems[0]; + if(lineItem0 == item) { + lineItems[1].setWrapped(true); + } + item.setWrapped(true); + JCoolBarItem lineItemN = lineItems[lineItems.length - 1]; + if(lineItemN != item) { + JCoolBarItem nextItem = getItem(itemIndex + 1); + nextItem.setXSpacing(Math.max(0, item.getXSpacing())); + } + int index = getItemIndex(lineItemN); + remove(item); + add(item, index); + int xSpacing = item.getXSpacing(); + int newXSpacing; + if(isLeftToRight) { + newXSpacing = item.getX(); + } else { + newXSpacing = getWidth() - item.getX() - item.getWidth(); + } + if(xSpacing < 0) { + newXSpacing += xSpacing; + } + item.setXSpacing(newXSpacing); + revalidate(); + repaint(); + setSize(new Dimension(getSize().width, getPreferredSize().height)); + } + + protected void mergeDown(int itemIndex) { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + JCoolBarItem[] lineItems = getLineItems(itemIndex+1); + if(lineItems.length == 0) { + return; + } + JCoolBarItem item = getItem(itemIndex); + JCoolBarItem nextItem = null; + int offset = 0; + for(int i=0; i= item.getX()) { + break; + } + } else { + if(nextItem.getX() + nextItem.getWidth() <= item.getX() + item.getWidth()) { + break; + } + } + offset++; + nextItem = null; + } + if(offset == 0) { + item.setWrapped(true); + lineItems[0].setWrapped(false); + } else { + remove(item); + add(item, itemIndex + offset); + item.setWrapped(false); + JCoolBarItem previousLineItem = lineItems[offset - 1]; + if(isLeftToRight) { + item.setXSpacing(item.getX() - previousLineItem.getX() - previousLineItem.getPreferredSize().width); + } else { + item.setXSpacing(previousLineItem.getX() + previousLineItem.getWidth() - previousLineItem.getPreferredSize().width - item.getX() - item.getWidth()); + } + } + if(offset < lineItems.length) { + JCoolBarItem nextLineItem = lineItems[offset]; + if(isLeftToRight) { + nextItem.setXSpacing(nextLineItem.getX() - item.getX() - item.getPreferredSize().width); + } else { + nextItem.setXSpacing(item.getX() + item.getWidth() - item.getPreferredSize().width - nextLineItem.getX() - nextLineItem.getWidth()); + } + } + revalidate(); + repaint(); + setSize(new Dimension(getSize().width, getPreferredSize().height)); + } + + protected void moveLeading(int itemIndex, int offsetX) { + offsetX = -offsetX; + JCoolBarItem item = getItem(itemIndex); + int xSpacing = item.getXSpacing(); + int newXSpacing = xSpacing + offsetX; + offsetX += Math.max(0, xSpacing); + int shift = 0; + int lineStartIndex = itemIndex - 1; + if(!item.isWrapped()) { + for(; offsetX < 0 && lineStartIndex>=0; lineStartIndex--) { + JCoolBarItem previousItem = (JCoolBarItem)getComponent(lineStartIndex); + int previousXSpacing = previousItem.getXSpacing(); + int diff = Math.min(-offsetX, previousXSpacing); + offsetX += diff; + shift += diff; + previousItem.setXSpacing(previousXSpacing - diff); + newXSpacing += diff; + if(previousItem.isWrapped()) { + lineStartIndex--; + break; + } + } + } + lineStartIndex++; + if(itemIndex + 1 < getComponentCount()) { + JCoolBarItem nextItem = (JCoolBarItem)getComponent(itemIndex + 1); + if(!nextItem.isWrapped()) { + nextItem.setXSpacing(nextItem.getXSpacing() - newXSpacing + xSpacing + shift + Math.min(0, offsetX)); + } + } + if(newXSpacing < 0) { + item.setXSpacing(newXSpacing); + revalidate(); + int x = item.getX(); + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + for(int i = lineStartIndex; i= x + newXSpacing) { + remove(item); + add(item, i); + newXSpacing += x - pX; + if(i == lineStartIndex) { + item.setWrapped(true); + previousItem.setWrapped(false); + } + break; + } + } else { + int pX = previousItem.getX(); + if(pX + previousItem.getWidth() <= x + item.getWidth() - newXSpacing) { + remove(item); + add(item, i); + newXSpacing += pX + previousItem.getWidth() - x - item.getWidth(); + if(i == lineStartIndex) { + item.setWrapped(true); + previousItem.setWrapped(false); + } + break; + } + } + } + } + item.setXSpacing(newXSpacing); + revalidate(); + repaint(); + } + + protected void moveTrailing(int itemIndex, int offsetX) { + JCoolBarItem item = getItem(itemIndex); + int xSpacing = item.getXSpacing(); + int newXSpacing = xSpacing + offsetX; + int componentCount = getComponentCount(); + if(newXSpacing >= 0) { + for(int i = itemIndex + 1; offsetX > 0 && i= getComponentCount()) { + return; + } + ((JExpandPaneItem)getComponent(index)).setExpanded(isExpanded); + } + + public void addChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); + } + + public void removeChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); + } + + public ChangeListener[] getChangeListeners() { + return (ChangeListener[])listenerList.getListeners(ChangeListener.class); + } + + public JExpandPaneItem getExpandItem(int index) { + return (JExpandPaneItem)getComponent(index); + } + + public JExpandPaneItem getExpandItem(Component component) { + int componentCount = getComponentCount(); + for(int i=0; i=0; i--) { + InnerLabel innerLabel = (InnerLabel)getComponent(i); + String text = innerLabel.getText(); + String nonHtmlText = innerLabel.getNonHtmlText(); + innerLabel.setText(nonHtmlText); + width = Math.max(width, innerLabel.getPreferredSize().width); + innerLabel.setText(text); + } + return width; + } + + public int getMnemonicIndex() { + return mnemonicIndex; + } + + public void setText(String text, int mnemonicIndex) { + if(text == null) { + text = ""; + } + if(this.text.equals(text) && this.mnemonicIndex == mnemonicIndex) { + return; + } + this.text = text; + this.mnemonicIndex = mnemonicIndex; + createContent(); + } + + protected void createContent() { + removeAll(); + String[] labels = text.split("\n"); + int count = 0; + for(int i=0; i"; + } + InnerLabel innerLabel = new InnerLabel(label, alignment, nonHtmlLabel); + innerLabel.setHorizontalAlignment(alignment); + if(!isWrapping) { + innerLabel.putClientProperty("html", null); + } + innerLabel.setText(label); + int newCount = count + label.length() + 1; + // TODO: check with HTML style what to do with mnemonics + if(count < mnemonicIndex && newCount > mnemonicIndex) { + innerLabel.setDisplayedMnemonicIndex(mnemonicIndex - count); + } + count = newCount; + add(innerLabel); + } + adjustStyles(); + revalidate(); + repaint(); + } + + protected boolean isWrapping; + + public void setWrapping(boolean isWrapping) { + if(this.isWrapping == isWrapping) { + return; + } + this.isWrapping = isWrapping; + createContent(); + } + + public boolean isWrapping() { + return isWrapping; + } + + protected int alignment = JLabel.LEFT; + + public void setHorizontalAlignment(int alignment) { + this.alignment = alignment; + for(int i=getComponentCount()-1; i>=0; i--) { + ((InnerLabel)getComponent(i)).setHorizontalAlignment(alignment); + } + } + + public void setIcon(Icon icon) { + if(getComponentCount() > 0) { + ((InnerLabel)getComponent(0)).setIcon(icon); + } + } + +// public void reshape(int x, int y, int w, int h) { +// super.reshape(x, y, w, h); +// for(int i=getComponentCount()-1; i>=0; i--) { +// getComponent(i).invalidate(); +// } +// validate(); +// } + + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + for(int i=getComponentCount()-1; i>=0; i--) { + getComponent(i).invalidate(); + } + validate(); + } + + public Dimension getPreferredSize() { + Dimension d = new Dimension(0, 0); + for(int i=getComponentCount()-1; i>=0; i--) { + Dimension preferredSize = getComponent(i).getPreferredSize(); + d.height += preferredSize.height; + d.width = Math.max(d.width, preferredSize.width); + } + Insets insets = getInsets(); + d.width += insets.left + insets.right; + d.height += insets.top + insets.bottom; + return d; + } + + public void setFont(Font font) { + super.setFont(font); + adjustStyles(); + } + + public void adjustStyles() { + if(!isWrapping()) { + return; + } + for(int i=getComponentCount()-1; i>=0; i--) { + InnerLabel innerLabel = (InnerLabel)getComponent(i); + innerLabel.updateUI(); + innerLabel.reshape(getX(), getY(), getWidth(), getHeight()); + } + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JStateCheckBox.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JStateCheckBox.java new file mode 100644 index 00000000000..710742527ae --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JStateCheckBox.java @@ -0,0 +1,78 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JCheckBox; + +public class JStateCheckBox extends JCheckBox { + + public JStateCheckBox() { + init(); + } + + public JStateCheckBox(Action a) { + super(a); + init(); + } + + public JStateCheckBox(Icon icon) { + super(icon); + init(); + } + + public JStateCheckBox(Icon icon, boolean selected) { + super(icon, selected); + init(); + } + + public JStateCheckBox(String text) { + super(text); + init(); + } + + public JStateCheckBox(String text, boolean selected) { + super(text, selected); + init(); + } + + public JStateCheckBox(String text, Icon icon) { + super(text, icon); + init(); + } + + public JStateCheckBox(String text, Icon icon, boolean selected) { + super(text, icon, selected); + init(); + } + + + protected void init() { + setModel(new ToggleButtonModel() { + public boolean isPressed() { + return isGrayed || super.isPressed(); + } + public boolean isArmed() { + return isGrayed || super.isArmed(); + } + }); + } + + protected boolean isGrayed; + + public void setGrayed(boolean isGrayed) { + this.isGrayed = isGrayed; + repaint(); + } + + public boolean isGrayed() { + return isGrayed; + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JTracker.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JTracker.java new file mode 100644 index 00000000000..16ee7608a77 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/JTracker.java @@ -0,0 +1,515 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.MenuComponent; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.EventListener; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.event.EventListenerList; + +public class JTracker { + + public static class TrackerEvent { + + protected int x; + protected int y; + + TrackerEvent(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + } + + public static interface TrackerListener extends EventListener { + public void trackerMoved(TrackerEvent e); + public void trackerResized(TrackerEvent e); + } + + public static final int SINGLE_LINE_APPEARANCE = 0; + public static final int THICK_BORDER_APPEARANCE = 1; + + public static final int UP_MASK = 1 << 0; + public static final int LEFT_MASK = 1 << 1; + public static final int DOWN_MASK = 1 << 2; + public static final int RIGHT_MASK = 1 << 3; + + protected Window[][] windowsArray = new Window[0][]; + protected Rectangle[] rectangles; + + protected boolean isResizeType; + protected Point offset; + protected Rectangle clipBounds; + + public JTracker(boolean isResizeType) { + this(null, isResizeType); + } + + public JTracker(Component component, boolean isResizeType) { + this.isResizeType = isResizeType; + if(component != null) { + offset = component.getLocationOnScreen(); + clipBounds = new Rectangle(component.getSize()); + Graphics g = component.getGraphics(); + if(g != null) { + Rectangle gClipBounds = g.getClipBounds(); + if(gClipBounds != null) { + clipBounds = gClipBounds.intersection(clipBounds); + } + } + clipBounds.x += offset.x; + clipBounds.y += offset.y; + } + } + + protected Window sharedOwnerWindow; + + public void setRectangles(Rectangle[] rectangles) { + if(rectangles != null) { + Rectangle[] rectanglesCopy = new Rectangle[rectangles.length]; + for(int i=0; i 0) { + if((constraints & RIGHT_MASK) != 0) { + edgeReiszeMask |= RIGHT_MASK; + } + } else if((constraints & LEFT_MASK) != 0) { + edgeReiszeMask |= LEFT_MASK; + } + } + if(dy != 0 && (edgeReiszeMask & (UP_MASK | DOWN_MASK)) == 0) { + if(dy > 0) { + if((constraints & DOWN_MASK) != 0) { + edgeReiszeMask |= DOWN_MASK; + } + } else if((constraints & UP_MASK) != 0) { + edgeReiszeMask |= UP_MASK; + } + } + } else { + if(dx < 0) { + if((constraints & LEFT_MASK) == 0) { + dx = 0; + } + } else if((constraints & RIGHT_MASK) == 0) { + dx = 0; + } + if(dy < 0) { + if((constraints & UP_MASK) == 0) { + dy = 0; + } + } else if((constraints & DOWN_MASK) == 0) { + dy = 0; + } + } + if(dx == 0 && dy == 0 || isResizeType && edgeReiszeMask == 0) { + return; + } + for(int i=0; i 0 && ((constraints & RIGHT_MASK) != 0)) { + rectangle.x += dx; + } + if(dy < 0 && ((constraints & UP_MASK) != 0) || dy > 0 && ((constraints & DOWN_MASK) != 0)) { + rectangle.y += dy; + } + } + } + postAdjustWindows(); + Object[] listeners = listenerList.getListenerList(); + TrackerEvent e = null; + for(int i=listeners.length-2; i>=0; i-=2) { + if(listeners[i] == TrackerListener.class) { + if(e == null) { + e = new TrackerEvent(lastMouseLocation.x, lastMouseLocation.y); + } + if(isResizeType) { + ((TrackerListener)listeners[i + 1]).trackerResized(e); + } else { + ((TrackerListener)listeners[i + 1]).trackerMoved(e); + } + } + } + } + + protected int appearance = SINGLE_LINE_APPEARANCE; + + public void setAppearance(int appearance) { + this.appearance = appearance; + postAdjustWindows(); + } + + protected boolean isAdjusmentPending; + + protected void postAdjustWindows() { + if(isAdjusmentPending) { + return; + } + isAdjusmentPending = true; + new Thread() { + public void run() { + try { + sleep(10); + } catch(Exception e) {} + SwingUtilities.invokeLater(new Runnable() { + public void run() { + adjustWindows(); + } + }); + } + }.start(); + } + + protected void adjustWindows() { + isAdjusmentPending = false; +// if(!Compatibility.IS_JAVA_5_OR_GREATER) { +// return; +// } + if(!isVisible || rectangles.length == 0) { + return; + } + int borderWidth = appearance == THICK_BORDER_APPEARANCE? 3: 1; + for(int i=0; i index1; + if(isReversed) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + TreePath[] treePaths = new TreePath[index1 + 1 - index0]; + for(int i=index0; i<=index1; i++) { + treePaths[i - index0] = tree.getPathForRow(isReversed? index1 + index0 - i: i); + } + tree.getSelectionModel().addSelectionPaths(treePaths); + } + public void clearSelection() { + super.clearSelection(); + tree.getSelectionModel().clearSelection(); + } + public void setSelectionInterval(int index0, int index1) { + super.setSelectionInterval(index0, index1); + boolean isReversed = index0 > index1; + if(isReversed) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + TreePath[] treePaths = new TreePath[index1 + 1 - index0]; + for(int i=index0; i<=index1; i++) { + treePaths[i - index0] = tree.getPathForRow(isReversed? index1 + index0 - i: i); + } + tree.getSelectionModel().setSelectionPaths(treePaths); + } + public void removeSelectionInterval(int index0, int index1) { + super.removeSelectionInterval(index0, index1); + boolean isReversed = index0 > index1; + if(isReversed) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + if(index1 + 1 - index0 < 0) { + // Possible with Java 4: if an index is close to the boundaries of Integer.MAX/MIN_VALUE + return; + } + TreePath[] treePaths = new TreePath[index1 + 1 - index0]; + for(int i=index0; i<=index1; i++) { + treePaths[i - index0] = tree.getPathForRow(isReversed? index1 + index0 - i: i); + } + tree.getSelectionModel().removeSelectionPaths(treePaths); + } + public int getMinSelectionIndex() { + return tree.getSelectionModel().getMinSelectionRow(); + } + public int getMaxSelectionIndex() { + return tree.getSelectionModel().getMaxSelectionRow(); + } + public boolean isSelectedIndex(int index) { + return tree.getSelectionModel().isRowSelected(index); + } + }; + + protected class TreeTableModel implements TableModel { + + public int getRowCount() { + return tree.getRowCount(); + } + + public int getColumnCount() { + return getColumnModel().getColumnCount(); + } + + public String getColumnName(int columnIndex) { + return null; +// Object headerValue = getColumnModel().getColumn(columnIndex).getHeaderValue(); +// return headerValue == null? null: headerValue.toString(); + } + + public Class getColumnClass(int columnIndex) { + return null; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + public Object getValueAt(int rowIndex, int columnIndex) { + TreePath path = tree.getPathForRow(rowIndex); + TreeNode node = (TreeNode)path.getLastPathComponent(); + if(node instanceof TreeTableNode) { + return ((TreeTableNode)node).getUserObject(columnIndex); + } + if(columnIndex == 0 && node instanceof DefaultMutableTreeNode) { + return ((DefaultMutableTreeNode)node).getUserObject(); + } + return null; + } + + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + } + + protected EventListenerList listenerList = new EventListenerList(); + + public void addTableModelListener(TableModelListener l) { + listenerList.add(TableModelListener.class, l); + } + + public void removeTableModelListener(TableModelListener l) { + listenerList.remove(TableModelListener.class, l); + } + + public void fireTableChanged(TableModelEvent e) { + Object[] listeners = listenerList.getListenerList(); + for(int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==TableModelListener.class) { + ((TableModelListener)listeners[i+1]).tableChanged(e); + } + } + } + + }; + + protected TreeTableModel tableModel = new TreeTableModel(); + + protected TableCellRenderer tableCellRenderer = new TableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + final TreePath path = tree.getPathForRow(row); + if(column == 0) { + class FirstColumnComponent extends JComponent implements CellPainter { + public void paintComponent(Graphics g) { + if(renderer instanceof DefaultTreeTableCellRenderer) { + ((DefaultTreeTableCellRenderer)renderer).paintComponent(this, g); + } else { + paintCell(g); + } + } + public void paintCell(Graphics g) { + int row = tree.getRowForPath(path); + Rectangle rowBounds = tree.getRowBounds(row); + rowBounds.width += rowBounds.x; + rowBounds.x = 0; + g = g.create(); + int width = JTreeTable.this.table.getColumnModel().getColumn(0).getWidth(); + g.clipRect(0, 0, width, rowBounds.height); + if(isFullLineSelection() && JTreeTable.this.table.isRowSelected(row)) { + g.setColor(JTreeTable.this.table.getSelectionBackground()); + g.fillRect(0, 0, width, rowBounds.height); + } + g.translate(0, -rowBounds.y); + tree.paint(g); + g.dispose(); + } + } + return new FirstColumnComponent(); + } + TreeNode node = (TreeNode)path.getLastPathComponent(); + if(node instanceof TreeTableNode) { + value = ((TreeTableNode)node).getUserObject(table.convertColumnIndexToModel(column)); + } + hasFocus = false; + if(!isFullLineSelection()) { + isSelected = false; + } + return renderer.getTreeTableCellRendererComponent(JTreeTable.this, value, isSelected, tree.isExpanded(row), node.isLeaf(), row, column, hasFocus); + } + }; + + class InternalTable extends JTable { + + protected InternalTable() { + enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); + setSelectionModel(tableSelectionModel); + JTreeTable.this.setBackground(super.getBackground()); + } + + public Color getBackground() { + return JTreeTable.this != null? JTreeTable.this.getBackground(): super.getBackground(); + } + + public boolean isOpaque() { + return JTreeTable.this.isOpaque(); + } + + public Rectangle getCellRect(int row, int column, boolean includeSpacing) { + Rectangle cellBounds = super.getCellRect(row, column, includeSpacing); + Rectangle rowBounds = tree.getRowBounds(row); +// rowBounds.width += rowBounds.x; +// rowBounds.x = 0; + if(rowBounds == null) { + return cellBounds; + } + cellBounds.y = rowBounds.y; + cellBounds.y += row * getIntercellSpacing().height; + return cellBounds; + } + + public TableCellRenderer getCellRenderer(int row, int column) { + return tableCellRenderer; + } + + public int getRowHeight(int row) { + return tree.getRowBounds(row).height + getRowMargin(); + } + + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + TableColumnModel columnModel = getColumnModel(); + if(columnModel.getColumnCount() > 0) { + tree.setSize(columnModel.getColumn(0).getWidth(), h); + } else { + tree.setSize(w, h); + } + } + + public int rowAtPoint(Point point) { + int row = tree.getClosestRowForLocation(0, point.y); + if(row == -1) { + return -1; + } + Rectangle rect = getCellRect(getRowCount() - 1, 0, false); + if(point.y > rect.y + rect.height) { + return -1; + } + while(getCellRect(row, 0, false).y > point.y) { + row--; + if(row == -1) { + return -1; + } + } + return row; + } + + protected void processEvent(AWTEvent e) { + if(e instanceof MouseEvent) { + if(e.getID() == MouseWheelEvent.MOUSE_WHEEL) { + super.processEvent(e); + return; + } + if(e.getID() == MouseEvent.MOUSE_PRESSED && isFocusable() && !hasFocus()) { + requestFocus(); + } + MouseEvent me = (MouseEvent)e; + Point point = me.getPoint(); + int row = rowAtPoint(point); + Rectangle treeRect = getCellRect(row, 0, false); + if(!treeRect.contains(point)) { + if(isFullLineSelection()) { + super.processEvent(e); + } + return; + } + int xOffset = treeRect.x; + int yOffset = row * getIntercellSpacing().height; + int x = me.getX() - xOffset; + int y = me.getY() - yOffset; + Rectangle rowBounds = tree.getRowBounds(row); + if(rowBounds != null) { + if(!rowBounds.contains(x, y)) { + me = new MouseEvent(tree, me.getID(), me.getWhen(), me.getModifiers(), x, y, me.getClickCount(), me.isPopupTrigger(), me.getButton()); + boolean isExpanded = tree.isExpanded(row); + tree.dispatchEvent(me); + if(isFullLineSelection() && tree.isExpanded(row) == isExpanded) { + super.processEvent(e); + } + } else { + if(processMouseOnTreeRenderer(row, new MouseEvent(tree, me.getID(), me.getWhen(), me.getModifiers(), x - rowBounds.x, y - rowBounds.y, me.getClickCount(), me.isPopupTrigger(), me.getButton()), new Dimension(rowBounds.width, rowBounds.height))) { +// System.err.println(me.getPoint() + ", " + xOffset + ", " + x + ", " + rowBounds); + super.processEvent(e); + } + } + } else { + super.processEvent(e); + } +// if(!rowBounds.contains(x, y)) { +// super.processEvent(e); +// } +// if(me.getID() != MouseEvent.MOUSE_DRAGGED) { +// } + } else if(e instanceof KeyEvent) { + tree.dispatchEvent(e); + super.processEvent(e); + } else { + super.processEvent(e); + } + repaint(); + } + + } + + public JTreeTable(TreeModel newModel) { + this(); + setModel(newModel); + } + + public JTreeTable() { + super(new BorderLayout(0, 0)); + table = new InternalTable(); + table.setTableHeader(createDefaultTableHeader()); +// setBackground(table.getBackground()); + add(table, BorderLayout.CENTER); + tree = new JTree() { + public boolean hasFocus() { + // this happens when the look and feel queries the focus owner and the object is not yet constructed. + if(JTreeTable.this == null) { + return false; + } + return table.hasFocus(); + } + }; + tree.setOpaque(false); + tree.setCellRenderer(new TreeCellRenderer() { + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + if(value instanceof TreeTableNode) { + if(getColumnCount() > 0) { + value = ((TreeTableNode)value).getUserObject(convertColumnIndexToModel(0)); + } + } else if(value instanceof DefaultMutableTreeNode) { + value = ((DefaultMutableTreeNode)value).getUserObject(); + } + return renderer.getTreeTableCellRendererComponent(JTreeTable.this, value, selected, expanded, leaf, row, 0, !isFullLineSelection() && hasFocus); + } + }); + tree.addTreeExpansionListener(new TreeExpansionListener() { + protected int countNodeElements(TreePath treePath) { + int count = 1; + if(tree.hasBeenExpanded(treePath)) { + TreeNode node = (TreeNode)treePath.getLastPathComponent(); + Object[] path = treePath.getPath(); + for(int i=0; i 0) { + tree.setSelectionInterval(0, rowCount - 1); + } + } + + public void expandPath(TreePath treePath) { + tree.expandPath(treePath); + } + + public void collapsePath(TreePath treePath) { + tree.collapsePath(treePath); + } + + public boolean isExpanded(TreePath path) { + return tree.isExpanded(path); + } + + public void setSelectionMode(int mode) { + tree.getSelectionModel().setSelectionMode(mode); + switch(mode) { + case TreeSelectionModel.SINGLE_TREE_SELECTION: + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + break; + case TreeSelectionModel.CONTIGUOUS_TREE_SELECTION: + table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + break; + case TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION: + table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + break; + } + } + + public TreePath getPathForRow(int row) { + return tree.getPathForRow(row); + } + + public boolean isRowSelected(int row) { + return tree.isRowSelected(row); + } + + /** + * @return True if the event should be dispatched as if it was not processed by the tree renderer. + */ + protected boolean processMouseOnTreeRenderer(int row, MouseEvent e, Dimension cellSize) { + return true; + } + + public Dimension getPreferredSize() { +// System.err.println(table.getPreferredSize()); +// return table.getPreferredSize(); + Dimension preferredSize = super.getPreferredSize(); + if(getTableHeader().isVisible()) { + return preferredSize; + } + TableColumnModel columnModel = getColumnModel(); + if(columnModel.getColumnCount() > 0) { + return new Dimension(preferredSize.width - columnModel.getColumn(0).getPreferredWidth() + getPreferredColumnWidth(0), preferredSize.height); + } + return preferredSize; + } + + public Rectangle getCellRect(int row, int column, boolean includeSpacing) { + return table.getCellRect(row, column, includeSpacing); + } + + public int getRowForPath(TreePath path) { + return tree.getRowForPath(path); + } + + public void setAutoResizeMode(int mode) { + table.setAutoResizeMode(mode); + } + + public int getAutoResizeMode() { + return table.getAutoResizeMode(); + } + + public int convertColumnIndexToModel(int viewColumnIndex) { + return table.convertColumnIndexToModel(viewColumnIndex); + } + + public int convertColumnIndexToView(int modelColumnIndex) { + return table.convertColumnIndexToView(modelColumnIndex); + } + + public void addTreeExpansionListener(TreeExpansionListener tel) { + tree.addTreeExpansionListener(tel); + } + + public void addTreeSelectionListener(TreeSelectionListener tsl) { + tree.addTreeSelectionListener(tsl); + } + + public void addTreeWillExpandListener(TreeWillExpandListener tel) { + tree.addTreeWillExpandListener(tel); + } + + public void removeTreeExpansionListener(TreeExpansionListener tel) { + tree.removeTreeExpansionListener(tel); + } + + public void removeTreeSelectionListener(TreeSelectionListener tsl) { + tree.removeTreeSelectionListener(tsl); + } + + public void removeTreeWillExpandListener(TreeWillExpandListener tel) { + tree.removeTreeWillExpandListener(tel); + } + + public int getRowForLocation(int x, int y) { + Point point = new Point(x, y); + int row = table.rowAtPoint(point); + if(row == -1) { + return -1; + } + int column = table.columnAtPoint(point); + if(column == 0) { + Rectangle bounds = tree.getRowBounds(row); + return bounds.x <= x && x < bounds.x + bounds.width? row: -1; + } + return row; + } + + public TreePath getPathForLocation(int x, int y) { + int row = getRowForLocation(x, y); + if(row == -1) { + return null; + } + return getPathForRow(row); + } + + public int getPreferredColumnWidth(int columnIndex) { + if(columnIndex == 0) { + return tree.getPreferredSize().width; + } + int count = getRowCount(); + int newWidth = Math.max(getColumnModel().getColumn(columnIndex).getMinWidth(), 10); + // TODO: is there a better way than this hack? + TreeTableCellRenderer renderer = getCellRenderer(); + for(int i=0; i 0) { + skippedThreadCount--; + } else { + isExit = false; + } + } + } + if(isExit) { + System.exit(0); + } + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/UnmanagedScrollPane.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/UnmanagedScrollPane.java new file mode 100644 index 00000000000..213859420a5 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/UnmanagedScrollPane.java @@ -0,0 +1,39 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.Point; + +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.event.ChangeListener; + +class UnmanagedScrollPane extends JScrollPane { + + public UnmanagedScrollPane(int vsbPolicy, int hsbPolicy) { + super(vsbPolicy, hsbPolicy); + } + + protected static class DisconnectedViewport extends JViewport { + public void setViewPosition(Point p) { + // Do nothing to prevent auto scrolling + } + public void addChangeListener(ChangeListener l) { + // Do nothing to prevent auto scrolling + } + } + + protected final JViewport createViewport() { + return createDisconnectedViewport(); + } + + protected DisconnectedViewport createDisconnectedViewport() { + return new DisconnectedViewport(); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/Utils.java b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/Utils.java new file mode 100644 index 00000000000..e1ac2393b9e --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/swing/org/eclipse/swt/internal/swing/Utils.java @@ -0,0 +1,568 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.internal.swing; + +import java.awt.AWTEvent; +import java.awt.Canvas; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.dnd.DnDConstants; +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.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.util.Collections; + +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.LookAndFeel; +import javax.swing.RepaintManager; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Shell; + +/** + * General util methods. + * @version 1.0 2005.03.18 + * @author Christopher Deckers (chrriis@nextencia.net) + */ +public class Utils { + + protected Utils() {} + + protected static final String LIGHTPOPUPS_PROPERTY = "swt.swing.lightpopups"; + protected static final String LOOK_AND_FEEL_PROPERTY = "swt.swing.laf"; + protected static final String LOOK_AND_FEEL_DECORATED_PROPERTY = "swt.swing.laf.decorated"; + protected static final String DEFAULT_ARROW_BUTTONS_PROPERTY = "swt.swing.defaultarrowbuttons"; + protected static final String APPLEMENUBAR_PROPERTY = "apple.laf.useScreenMenuBar"; + + public static final String SWTSwingGraphics2DClientProperty = "SWTSwingGraphics2DClientProperty"; + + public static boolean isLightweightPopups() { + return "true".equals(System.getProperty(LIGHTPOPUPS_PROPERTY)); + } + + public static void initializeProperties() { + if(Compatibility.IS_JAVA_5_OR_GREATER) { + // Specific Sun property to prevent heavyweight components from erasing their background. + // Used to enhance visual appearance of the tracker. On Java 1.4, tracker is not always on top so this helps to see it. + System.setProperty("sun.awt.noerasebackground", "true"); + } + if(System.getProperty(APPLEMENUBAR_PROPERTY) == null) { + System.setProperty(APPLEMENUBAR_PROPERTY, "true"); + } + } + + protected static String getLookAndFeel() { + return System.getProperty(LOOK_AND_FEEL_PROPERTY); + } + + public static void installDefaultLookAndFeel() { + boolean isLookAndFeelInstalled = false; + String lafName = getLookAndFeel(); + if(lafName != null) { + LookAndFeel lookAndFeel = javax.swing.UIManager.getLookAndFeel(); + if(lookAndFeel != null && lafName.equals(lookAndFeel.getClass().getName())) { + isLookAndFeelInstalled = true; + } else { + try { + javax.swing.UIManager.setLookAndFeel(lafName); + isLookAndFeelInstalled = true; + Boolean isLookAndFeelDecorated = isLookAndFeelDecorated(); + if(isLookAndFeelDecorated != null) { + boolean isLafDecorated = isLookAndFeelDecorated.booleanValue(); + JFrame.setDefaultLookAndFeelDecorated(isLafDecorated); + JDialog.setDefaultLookAndFeelDecorated(isLafDecorated); + } + } catch(Exception e) {e.printStackTrace();} + } + } + // If no look and feel is specified, install one that looks native. + if(!isLookAndFeelInstalled) { + try { + javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); + } catch(Exception e) {} + } + } + + + protected static Boolean isLookAndFeelDecorated() { + String value = System.getProperty(LOOK_AND_FEEL_DECORATED_PROPERTY); + return value == null? null: new Boolean(value); + } + + public static Boolean isUsingDefaultArrowButtons() { + String value = System.getProperty(DEFAULT_ARROW_BUTTONS_PROPERTY); + return value == null? null: new Boolean(value); + } + + protected static Canvas panel = new Canvas(); + + public static Component getDefaultComponent() { + return panel; + } + + static void installMouseListener(Component component, final Control control) { + component.addMouseListener(new MouseListener() { + public void mousePressed(MouseEvent e) { + control.processEvent(e); + } + public void mouseReleased(MouseEvent e) { + control.processEvent(e); + } + public void mouseClicked(MouseEvent e) { + control.processEvent(e); + } + public void mouseEntered(MouseEvent e) { + control.processEvent(e); + } + public void mouseExited(MouseEvent e) { + control.processEvent(e); + } + }); + component.addMouseMotionListener(new MouseMotionListener() { + public void mouseDragged(MouseEvent e) { + control.processEvent(e); + } + public void mouseMoved(MouseEvent e) { + control.processEvent(e); + } + }); + component.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + control.processEvent(e); + } + }); + } + + static void installKeyListener(Component component, final Control control) { + component.setFocusTraversalKeysEnabled(false); + component.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); + component.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); + component.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + control.processEvent(e); + } + public void keyReleased(KeyEvent e) { + control.processEvent(e); + } + public void keyTyped(KeyEvent e) { + control.processEvent(e); + } + }); + } + + static void installFocusListener(Component component, final Control control) { + component.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + control.processEvent(e); + } + public void focusLost(FocusEvent e) { + control.processEvent(e); + } + }); + } + + static void installComponentListener(Component component, final Control control) { + component.addComponentListener(new ComponentListener() { + public void componentHidden(ComponentEvent e) { + control.processEvent(e); + } + public void componentShown(ComponentEvent e) { + control.processEvent(e); + } + public void componentResized(ComponentEvent e) { + control.processEvent(e); + } + public void componentMoved(ComponentEvent e) { + control.processEvent(e); + } + }); + } + + public static String escapeSwingXML(String s) { + if(s == null) { + return s; + } + int length = s.length(); + if(length == 0) { + return s; + } + StringBuffer sb = new StringBuffer((int)(length * 1.1)); + for(int i=0; i < length; i++) { + char c = s.charAt(i); + switch(c) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; +// case '\'': +// sb.append("'"); +// break; + case '\"': + sb.append("""); + break; + default: + sb.append(c); + break; + } + } + return sb.toString(); + } + + public static String unescapeXML(String s) { + if(s == null) { + return s; + } + int length = s.length(); + if(length < 3) { + return s; + } + char[] chars = new char[length]; + int pos = 0; + for (int i = 0; i < length; i++) { + char c = s.charAt(i); + if(c == '&') { + String right = s.substring(i + 1); + if(right.startsWith("lt;")) { + chars[pos] = '<'; + i += 3; + } else if(right.startsWith("gt;")) { + chars[pos] = '>'; + i += 3; + } else if(right.startsWith("amp;")) { + chars[pos] = '&'; + i += 4; + } else if(right.startsWith("apos;")) { + chars[pos] = '\''; + i += 5; + } else if(right.startsWith("quot;")) { + chars[pos] = '\"'; + i += 5; + } else { + chars[pos++] = c; + } + } else { + chars[pos++] = c; + } + } + if(pos == chars.length) { + return s; + } + return new String(chars, 0, pos); + } + + public static String convertStringToHTML(String string) { + if (string == null) { + return null; + } + StringBuffer sb = new StringBuffer(""); + for(int i=0; i"); + break; + case '\n': + sb.append("

    "); + break; + default: + sb.append(Utils.escapeSwingXML(String.valueOf(c))); + break; + } + } + sb.append(""); + return sb.toString(); + } + + public static int convertDnDActionsToSWT(int actions) { + if(actions == 0) { + return 0; + } + int swtActions = 0; + if((actions & DnDConstants.ACTION_COPY) != 0) { + swtActions |= DND.DROP_COPY; + } + if((actions & DnDConstants.ACTION_MOVE) != 0) { + swtActions |= DND.DROP_MOVE; + } + if((actions & DnDConstants.ACTION_LINK) != 0) { + swtActions |= DND.DROP_LINK; + } + return swtActions; + } + + public static int convertDnDActionsToSwing(int actions) { + if(actions == 0) { + return 0; + } + int swingActions = 0; + if((actions & DND.DROP_COPY) != 0) { + swingActions |= DnDConstants.ACTION_COPY; + } + if((actions & DND.DROP_MOVE) != 0) { + swingActions |= DnDConstants.ACTION_MOVE; + } + if((actions & DND.DROP_LINK) != 0) { + swingActions |= DnDConstants.ACTION_LINK; + } + return swingActions; + } + + static long timeStamp = System.currentTimeMillis(); + + public static int getCurrentTime () { + return (int)(System.currentTimeMillis() - timeStamp); + } + + public static boolean isFlatLayout(Control control) { + if(!(control instanceof Composite)) { + return false; + } + Layout layout = ((Composite)control).getLayout(); + if(layout == null) { + return false; + } + if(layout instanceof FillLayout || layout instanceof RowLayout || layout instanceof StackLayout) { + return true; + } + return false; + } + + /** + * Get the line number for debuggin purposes. + * @return The line number of the caller, or a negative number if it could not be obtained. + */ + public static int getLineNumber() { + StackTraceElement[] stackTraceElements; + if(Compatibility.IS_JAVA_5_OR_GREATER) { + stackTraceElements = Thread.currentThread().getStackTrace(); + } else { + stackTraceElements = new Exception().getStackTrace(); + } + int i = 0; + for(; i 0) { + int count = depth; + if(control == referenceControl) { + sb.append("> "); + count--; + } + while(count-- > 0) { + sb.append(" "); + } + } + sb.append(control); + Rectangle bounds = control.getBounds(); + sb.append(" - [").append(bounds.x).append(", ").append(bounds.y).append(", ").append(bounds.width).append(", ").append(bounds.height).append(']'); + if(control instanceof Composite) { + Layout layout = ((Composite)control).getLayout(); + if(layout != null) { + sb.append(" - ").append(layout.getClass().getName()); + } + } + System.out.println(sb.toString()); + if(control instanceof Composite) { + Control[] children = ((Composite)control).getChildren(); + for(int i=0; i + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class PrintDialog extends Dialog { + int scope = PrinterData.ALL_PAGES; + int startPage = 1, endPage = 1; + boolean printToFile = false; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public PrintDialog (Shell parent) { + this (parent, SWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public PrintDialog (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns the print job scope that the user selected + * before pressing OK in the dialog. This will be one + * of the following values: + *
    + *
    ALL_PAGES
    + *
    Print all pages in the current document
    + *
    PAGE_RANGE
    + *
    Print the range of pages specified by startPage and endPage
    + *
    SELECTION
    + *
    Print the current selection
    + *
    + * + * @return the scope setting that the user selected + */ +public int getScope() { + return scope; +} + +/** + * Sets the scope of the print job. The user will see this + * setting when the dialog is opened. This can have one of + * the following values: + *
    + *
    ALL_PAGES
    + *
    Print all pages in the current document
    + *
    PAGE_RANGE
    + *
    Print the range of pages specified by startPage and endPage
    + *
    SELECTION
    + *
    Print the current selection
    + *
    + * + * @param scope the scope setting when the dialog is opened + */ +public void setScope(int scope) { + this.scope = scope; +} + +/** + * Returns the start page setting that the user selected + * before pressing OK in the dialog. + *

    + * Note that this value is one based and only valid if the scope is + * PAGE_RANGE. + *

    + * + * @return the start page setting that the user selected + */ +public int getStartPage() { + return startPage; +} + +/** + * Sets the start page that the user will see when the dialog + * is opened. + *

    + * Note that this value is one based and only valid if the scope is + * PAGE_RANGE. + *

    + * + * @param startPage the startPage setting when the dialog is opened + */ +public void setStartPage(int startPage) { + this.startPage = startPage; +} + +/** + * Returns the end page setting that the user selected + * before pressing OK in the dialog. + *

    + * Note that this value is one based and only valid if the scope is + * PAGE_RANGE. + *

    + * + * @return the end page setting that the user selected + */ +public int getEndPage() { + return endPage; +} + +/** + * Sets the end page that the user will see when the dialog + * is opened. + *

    + * Note that this value is one based and only valid if the scope is + * PAGE_RANGE. + *

    + * + * @param endPage the end page setting when the dialog is opened + */ +public void setEndPage(int endPage) { + this.endPage = endPage; +} + +/** + * Returns the 'Print to file' setting that the user selected + * before pressing OK in the dialog. + * + * @return the 'Print to file' setting that the user selected + */ +public boolean getPrintToFile() { + return printToFile; +} + +/** + * Sets the 'Print to file' setting that the user will see + * when the dialog is opened. + * + * @param printToFile the 'Print to file' setting when the dialog is opened + */ +public void setPrintToFile(boolean printToFile) { + this.printToFile = printToFile; +} + +@Override +protected void checkSubclass() { + String name = getClass().getName(); + String validName = PrintDialog.class.getName(); + if (!validName.equals(name)) { + SWT.error(SWT.ERROR_INVALID_SUBCLASS); + } +} + +/** + * Makes the receiver visible and brings it to the front + * of the display. + * + * @return a printer data object describing the desired print job parameters + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public PrinterData open() { + PrinterJob printerJob = PrinterJob.getPrinterJob(); + java.util.List printRequestAttributeList = new ArrayList(); + if(printToFile) { + printRequestAttributeList.add(new Destination(new File("out.prn").toURI())); + } + if(scope == PrinterData.PAGE_RANGE) { + printRequestAttributeList.add(new PageRanges(startPage, endPage)); + } + HashPrintRequestAttributeSet hashPrintRequestAttributeSet = new HashPrintRequestAttributeSet((PrintRequestAttribute[])printRequestAttributeList.toArray(new PrintRequestAttribute[0])); + if(!printerJob.printDialog(hashPrintRequestAttributeSet)) { + return null; + } + Destination destination = (Destination)hashPrintRequestAttributeSet.get(Destination.class); + printToFile = destination != null; + PageRanges pageRanges = (PageRanges)hashPrintRequestAttributeSet.get(PageRanges.class); + if(pageRanges == null) { + scope = PrinterData.ALL_PAGES; + } else { + scope = PrinterData.PAGE_RANGE; + int[][] members = pageRanges.getMembers(); + startPage = members[0][0]; + endPage = members[0][1]; + } + PrintService printService = printerJob.getPrintService(); + PrinterData printerData = new PrinterData(printService.getClass().getName(), printService.getName()); +// Copies copies = (Copies)hashPrintRequestAttributeSet.get(Copies.class); + printerData.copyCount = 1;//copies != null? copies.getValue(): 1; + printerData.collate = false;//hashPrintRequestAttributeSet.get(SheetCollate.class) == SheetCollate.COLLATED; + printerData.startPage = startPage; + printerData.endPage = endPage; + printerData.scope = scope; + printerData.printToFile = printToFile; + printerData.fileName = destination != null? destination.getURI().toString(): null; +// printerData.otherData = hashPrintRequestAttributeSet; //TODO implement + return printerData; +// PRINTDLG pd = new PRINTDLG(); +// pd.lStructSize = PRINTDLG.sizeof; +// Control parent = getParent(); +// if (parent != null) pd.hwndOwner = parent.handle; +// pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE; +// if (printToFile) pd.Flags |= OS.PD_PRINTTOFILE; +// switch (scope) { +// case PrinterData.PAGE_RANGE: pd.Flags |= OS.PD_PAGENUMS; break; +// case PrinterData.SELECTION: pd.Flags |= OS.PD_SELECTION; break; +// default: pd.Flags |= OS.PD_ALLPAGES; +// } +// pd.nMinPage = 1; +// pd.nMaxPage = -1; +// pd.nFromPage = (short) Math.min (0xFFFF, Math.max (1, startPage)); +// pd.nToPage = (short) Math.min (0xFFFF, Math.max (1, endPage)); +// +// Display display = parent.getDisplay(); +// Shell [] shells = display.getShells(); +// if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) { +// for (int i=0; inew GC(printer) + * and then draw on the printer GC using the usual graphics calls. + *

    + * A Printer object may be constructed by providing + * a PrinterData object which identifies the printer. + * A PrintDialog presents a print dialog to the user + * and returns an initialized instance of PrinterData. + * Alternatively, calling new Printer() will construct a + * printer object for the user's default printer. + *

    + * Application code must explicitly invoke the Printer.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @see PrinterData + * @see PrintDialog + */ +public final class Printer extends Device { + /** + * the handle to the printer DC + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public PrinterJob handle; + + /** + * the printer data describing this printer + */ + PrinterData data; + + /** + * whether or not a GC was created for this printer + */ + boolean isGCCreated = false; + +/** + * Returns an array of PrinterData objects + * representing all available printers. + * + * @return the list of available printers + */ +public static PrinterData[] getPrinterList() { + PrintService[] printServices = PrinterJob.lookupPrintServices(); + PrinterData[] result = new PrinterData[printServices.length]; + for(int i=0; iPrinterData object representing + * the default printer or null if there is no + * printer available on the System. + * + * @return the default printer data or null + * + * @since 2.1 + */ +public static PrinterData getDefaultPrinterData() { + PrintService printService = PrinterJob.getPrinterJob().getPrintService(); + if(printService == null) return null; + return new PrinterData(printService.getClass().getName(), printService.getName()); +} + +static DeviceData checkNull (PrinterData data) { + if (data == null) data = new PrinterData(); + if (data.driver == null || data.name == null) { + PrinterData defaultPrinter = getDefaultPrinterData(); + if (defaultPrinter == null) SWT.error(SWT.ERROR_NO_HANDLES); + data.driver = defaultPrinter.driver; + data.name = defaultPrinter.name; + } + return data; +} + +/** + * Constructs a new printer representing the default printer. + *

    + * You must dispose the printer when it is no longer required. + *

    + * + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if there are no valid printers + *
    + * + * @see Device#dispose + */ +public Printer() { + this(null); +} + +/** + * Constructs a new printer given a PrinterData + * object representing the desired printer. + *

    + * You must dispose the printer when it is no longer required. + *

    + * + * @param data the printer data for the specified printer + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the specified printer data does not represent a valid printer + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if there are no valid printers + *
    + * + * @see Device#dispose + */ +public Printer(PrinterData data) { + super(checkNull(data)); + initPrinterData(); +} + +protected void initPrinterData() { + if(referencePageFormat != null) { + return; + } + dpiX = 72; + dpiY = 72; + HashPrintRequestAttributeSet hashPrintRequestAttributeSet = getHashPrintRequestAttributeSet(); + PageFormat pageFormat; + if(Compatibility.IS_JAVA_6_OR_GREATER) { + pageFormat = handle.getPageFormat(hashPrintRequestAttributeSet); + } else { + pageFormat = handle.defaultPage(); + } + Paper paper = pageFormat.getPaper(); + paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight()); + pageFormat.setPaper(paper); + referencePageFormat = handle.validatePage(pageFormat); + PrinterJob initPrinterJob = PrinterJob.getPrinterJob(); + try { + // Should not happen since the handle has it. + initPrinterJob.setPrintService(handle.getPrintService()); + } catch(Exception e) { + e.printStackTrace(); + } + initPrinterJob.setPageable(new Pageable() { + @Override + public int getNumberOfPages() { + return UNKNOWN_NUMBER_OF_PAGES; + } + @Override + public Printable getPrintable(int pageIndex) { + return (g, pageFormat1, pageIndex1) -> { + Graphics2D g2D = (Graphics2D)g; + AffineTransform transform = g2D.getTransform(); + dpiX = (int)Math.round(72 * transform.getScaleX()); + dpiY = (int)Math.round(72 * transform.getScaleY()); +// int iX = (int)Math.round(pageFormat.getImageableX()); +// int iY = (int)Math.round(pageFormat.getImageableY()); +// g.translate(iX, iY); +// referencePageFormat = pageFormat; + initialState = new State(); + Font font = g2D.getFont(); + font = font.deriveFont(font.getSize2D() * getDPI_().y / 72); +// g2D.setFont(font); + initialState.transform = g2D.getTransform(); + initialState.transform.setToScale(1, 1); + g2D.setTransform(initialState.transform); + initialState.font = font; + initialState.background = g2D.getBackground(); + initialState.color = g2D.getColor(); + initialState.userClip = null; + initialState.composite = g2D.getComposite(); + initialState.renderingHints = g2D.getRenderingHints(); + initialState.stroke = g2D.getStroke(); + initialState.fontRenderContext = g2D.getFontRenderContext(); + handle.cancel(); + return Printable.NO_SUCH_PAGE; + }; + } + @Override + public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException { + return referencePageFormat; + } + }); + try { + initPrinterJob.print(hashPrintRequestAttributeSet); + } catch(Exception e) { +// e.printStackTrace(); + } +} + +protected int dpiX; +protected int dpiY; + +/** + * Creates the printer handle. + * This method is called internally by the instance creation + * mechanism of the Device class. + * @param deviceData the device data + */ +@Override +protected void create(DeviceData deviceData) { + data = (PrinterData)deviceData; + PrintService selectedPrintService = null; + PrintService[] printServices = PrinterJob.lookupPrintServices(); + for(int i=0; i 0) { + if(lastRecorder != recorder) { + lastRecorder = recorder; + addCommand(recorder, recorder.getStateCommand()); + } + ((List)pageCommandList.get(pageCount - 1)).add(command); + } +} + +class State { + Font font; + Color background; + Color color; + Shape userClip; + Composite composite; + RenderingHints renderingHints; + Stroke stroke; + AffineTransform transform; + FontRenderContext fontRenderContext; +} + +class CGCRecorder extends CGC.CGCGraphics2D { + protected Graphics2D graphics2D = new NullGraphics2D(); + @Override +public Graphics2D getGraphics() { + return graphics2D; + } + public void setState(State state) { + super.setFont(state.font); + super.setBackground(state.background); + super.setColor(state.color); + super.setUserClip(state.userClip); + super.setComposite(state.composite); + super.setRenderingHints(state.renderingHints); + super.setStroke(state.stroke); + super.setTransform(state.transform); + setFontRenderContext(state.fontRenderContext); + } + public State getState() { + State state = new State(); + state.font = super.getFont(); + state.background = super.getBackground(); + state.color = super.getColor(); + state.userClip = super.getUserClip(); + state.composite = super.getComposite(); + state.renderingHints = super.getRenderingHints(); + state.stroke = super.getStroke(); + state.fontRenderContext = super.getFontRenderContext(); + state.transform = super.getTransform(); + return state; + } + public CGCCommand getStateCommand() { + final State state = getState(); + return new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setFont(state.font); + cgc.setColor(state.color); + cgc.setBackground(state.background); + cgc.setUserClip(state.userClip); + cgc.setComposite(state.composite); + cgc.setRenderingHints(state.renderingHints); + cgc.setStroke(state.stroke); + if(cgc instanceof CGCRecorder) { + ((CGCRecorder)cgc).setFontRenderContext(state.fontRenderContext); + } + cgc.setTransform(state.transform); + } + }; + } + @Override +public void copyArea(final int x, final int y, final int width, final int height, final int dx, final int dy) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + copyArea(x, y, width, height, dx, dy); + } + }); + super.copyArea(x, y, width, height, dx, dy); + } + @Override +public void dispose() { +// addCommand(this, new CGCCommand() { +// public void run(CGC cgc) { +// cgc.dispose(); +// } +// }); + super.dispose(); + } + @Override +public void draw(final Shape s) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.draw(s); + } + }); + super.draw(s); + } + @Override +public void drawArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawArc(x, y, width, height, startAngle, arcAngle); + } + }); + super.drawArc(x, y, width, height, startAngle, arcAngle); + } + @Override +public boolean drawImage(Image img, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2, final ImageObserver observer) { + final BufferedImage image = new BufferedImage(sx2 - sx1, sy2 - sy1, BufferedImage.TYPE_INT_ARGB); + image.getGraphics().drawImage(img, 0, 0, image.getWidth(), image.getHeight(), sx1, sy1, sx2, sy2, observer); + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawImage(image, dx1, dy1, dx2, dy2, 0, 0, image.getWidth(), image.getHeight(), observer); + } + }); + return super.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + @Override +public void drawLine(final int x1, final int y1, final int x2, final int y2) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawLine(x1, y1, x2, y2); + } + }); + super.drawLine(x1, y1, x2, y2); + } + @Override +public void drawOval(final int x, final int y, final int width, final int height) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawOval(x, y, width, height); + } + }); + super.drawOval(x, y, width, height); + } + @Override +public void drawPolygon(final int[] points, final int[] points2, final int points3) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawPolygon(points, points2, points3); + } + }); + super.drawPolygon(points, points2, points3); + } + @Override +public void drawPolyline(final int[] points, final int[] points2, final int points3) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawPolyline(points, points2, points3); + } + }); + super.drawPolyline(points, points2, points3); + } + @Override +public void drawRect(final int x, final int y, final int width, final int height) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawRect(x, y, width, height); + } + }); + super.drawRect(x, y, width, height); + } + @Override +public void drawRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + }); + super.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + @Override +public void drawString(final String str, final int x, final int y) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.drawString(str, x, y); + } + }); + super.drawString(str, x, y); + } + @Override +public void fill(final Shape s) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fill(s); + } + }); + super.fill(s); + } + @Override +public void fillArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fillArc(x, y, width, height, startAngle, arcAngle); + } + }); + super.fillArc(x, y, width, height, startAngle, arcAngle); + } + @Override +public void fillOval(final int x, final int y, final int width, final int height) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fillOval(x, y, width, height); + } + }); + super.fillOval(x, y, width, height); + } + @Override +public void fillPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fillPolygon(xPoints, yPoints, nPoints); + } + }); + super.fillPolygon(xPoints, yPoints, nPoints); + } + @Override +public void fillRect(final int x, final int y, final int width, final int height) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fillRect(x, y, width, height); + } + }); + super.fillRect(x, y, width, height); + } + @Override +public void fillRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + }); + super.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + @Override +public Color getBackground() { + return super.getBackground(); + } + @Override +public Color getColor() { + return super.getColor(); + } + @Override +public Composite getComposite() { + return super.getComposite(); + } + @Override +public Font getFont() { + return super.getFont(); + } + @Override +public FontMetrics getFontMetrics() { + return super.getFontMetrics(); + } + protected FontRenderContext fontRenderContext; + public void setFontRenderContext(FontRenderContext fontRenderContext) { + this.fontRenderContext = fontRenderContext; + } + @Override +public FontRenderContext getFontRenderContext() { + if(fontRenderContext != null) { + return fontRenderContext; + } + return super.getFontRenderContext(); + } + @Override +public Paint getPaint() { + return super.getPaint(); + } + @Override +public Object getRenderingHint(Key hintKey) { + return super.getRenderingHint(hintKey); + } + @Override +public RenderingHints getRenderingHints() { + return super.getRenderingHints(); + } + @Override +public Stroke getStroke() { + return super.getStroke(); + } + @Override +public AffineTransform getTransform() { + return super.getTransform(); + } + @Override +public void setBackground(final Color background) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setBackground(background); + } + }); + super.setBackground(background); + } + @Override +public void setColor(final Color color) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setColor(color); + } + }); + super.setColor(color); + } + @Override +public void setComposite(final Composite comp) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setComposite(comp); + } + }); + super.setComposite(comp); + } + @Override +public void setFont(final Font font) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setFont(font); + } + }); + super.setFont(font); + } + @Override +public void setPaint(final Paint paint) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setPaint(paint); + } + }); + super.setPaint(paint); + } + @Override +public void setPaintMode() { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setPaintMode(); + } + }); + super.setPaintMode(); + } + @Override +public void setRenderingHint(final Key hintKey, final Object hintValue) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setRenderingHint(hintKey, hintValue); + } + }); + super.setRenderingHint(hintKey, hintValue); + } + @Override +public void setRenderingHints(final Map hints) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setRenderingHints(hints); + } + }); + super.setRenderingHints(hints); + } + @Override +public void setStroke(final Stroke s) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setStroke(s); + } + }); + super.setStroke(s); + } + @Override +public void setTransform(final AffineTransform tx) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setTransform(tx); + } + }); + super.setTransform(tx); + } + @Override +public void setXORMode(final Color c1) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setXORMode(c1); + } + }); + super.setXORMode(c1); + } + @Override +public void transform(final AffineTransform tx) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.transform(tx); + } + }); + super.transform(tx); + } + @Override +public void setUserClip(final Shape userClip) { + addCommand(this, new CGCCommand() { + @Override + public void run(CGC cgc) { + cgc.setUserClip(userClip); + } + }); + super.setUserClip(userClip); + } + @Override +public Shape getUserClip() { + return super.getUserClip(); + } + @Override +public Dimension getDeviceSize() { + Rectangle bounds = getBounds(); + return new Dimension(bounds.width, bounds.height); + } +} + +/** + * Invokes platform specific functionality to allocate a new GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Printer. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param data the platform specific GC data + * @return the platform specific GC handle + */ +@Override +public CGC internal_new_GC (GCData data) { + if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES); + CGCRecorder recorder = new CGCRecorder(); + recorder.setState(initialState); + return recorder; +// if (data != null) { +// if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; +// if ((data.style & mask) != 0) { +// data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0; +// } else { +// data.style |= SWT.LEFT_TO_RIGHT; +// } +// data.device = this; +// data.hFont = OS.GetCurrentObject(handle, OS.OBJ_FONT); +// +// isGCCreated = true; +// } +// return handle; +} + +/** + * Invokes platform specific functionality to dispose a GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Printer. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param hDC the platform specific GC handle + * @param data the platform specific GC data + */ +@Override +public void internal_dispose_GC (CGC hDC, GCData data) { + if (data != null) hDC.dispose(); +} + +HashPrintRequestAttributeSet getHashPrintRequestAttributeSet() { + java.util.List printRequestAttributeList = new ArrayList(); + if(data.printToFile) { + printRequestAttributeList.add(new Destination(new File(data.fileName).toURI())); + } + if(data.scope == PrinterData.PAGE_RANGE) { + printRequestAttributeList.add(new PageRanges(data.startPage, data.endPage)); + } + HashPrintRequestAttributeSet hashPrintRequestAttributeSet = new HashPrintRequestAttributeSet(); + // TODO (visjee): SWING +// if(data.otherData != null) { +// hashPrintRequestAttributeSet.addAll(data.otherData); +// } + hashPrintRequestAttributeSet.addAll(new HashPrintRequestAttributeSet((PrintRequestAttribute[])printRequestAttributeList.toArray(new PrintRequestAttribute[0]))); + return hashPrintRequestAttributeSet; +} + +/** + * Starts a print job and returns true if the job started successfully + * and false otherwise. + *

    + * This must be the first method called to initiate a print job, + * followed by any number of startPage/endPage calls, followed by + * endJob. Calling startPage, endPage, or endJob before startJob + * will result in undefined behavior. + *

    + * + * @param jobName the name of the print job to start + * @return true if the job started successfully and false otherwise. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #startPage + * @see #endPage + * @see #endJob + */ +public boolean startJob(String jobName) { + checkDevice(); + handle.setJobName(jobName); +// handle.setCopies(data.copyCount); + pageCount = 0; + pageCommandList = new ArrayList(); + // TODO: Check conditions that return false; + return true; +// DOCINFO di = new DOCINFO(); +// di.cbSize = DOCINFO.sizeof; +// int hHeap = OS.GetProcessHeap(); +// int lpszDocName = 0; +// if (jobName != null && jobName.length() != 0) { +// /* Use the character encoding for the default locale */ +// TCHAR buffer = new TCHAR(0, jobName, true); +// int byteCount = buffer.length() * TCHAR.sizeof; +// lpszDocName = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory(lpszDocName, buffer, byteCount); +// di.lpszDocName = lpszDocName; +// } +// int lpszOutput = 0; +// if (data.printToFile && data.fileName != null) { +// /* Use the character encoding for the default locale */ +// TCHAR buffer = new TCHAR(0, data.fileName, true); +// int byteCount = buffer.length() * TCHAR.sizeof; +// lpszOutput = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory(lpszOutput, buffer, byteCount); +// di.lpszOutput = lpszOutput; +// } +// int rc = OS.StartDoc(handle, di); +// if (lpszDocName != 0) OS.HeapFree(hHeap, 0, lpszDocName); +// if (lpszOutput != 0) OS.HeapFree(hHeap, 0, lpszOutput); +// return rc > 0; +} + +/** + * Ends the current print job. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #startJob + * @see #startPage + * @see #endPage + */ +public void endJob() { + checkDevice(); + handle.setPageable(new Pageable() { + @Override + public int getNumberOfPages() { + return pageCount; + } + @Override + public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException { + return (g, pageFormat, pageIndex1) -> { + if(pageIndex1 < 0 || pageIndex1 >= pageCount) { + return Printable.NO_SUCH_PAGE; + } + final Graphics2D g2D = ((Graphics2D)g); + CGC cgc = new CGC.CGCGraphics2D() { + @Override + public Graphics2D getGraphics() { + return g2D; + } + @Override + public Dimension getDeviceSize() { + Rectangle bounds = getBounds(); + return new Dimension(bounds.width, bounds.height); + } + }; + List commandList = (List)pageCommandList.get(pageIndex1); +// int iX = (int)Math.round(referencePageFormat.getImageableX()); +// int iY = (int)Math.round(referencePageFormat.getImageableY()); +// g.translate(iX, iY); + for(int i=0; i + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + */ +public void cancelJob() { + checkDevice(); + handle.cancel(); + pageCommandList = null; +// OS.AbortDoc(handle); +} + +/** + * Starts a page and returns true if the page started successfully + * and false otherwise. + *

    + * After calling startJob, this method may be called any number of times + * along with a matching endPage. + *

    + * + * @return true if the page started successfully and false otherwise. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #endPage + * @see #startJob + * @see #endJob + */ +public boolean startPage() { + checkDevice(); + pageCount++; + pageCommandList.add(new ArrayList()); + lastRecorder = null; + // TODO: find if false can happen + return true; +} + +/** + * Ends the current page. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #startPage + * @see #startJob + * @see #endJob + */ +public void endPage() { + checkDevice(); + //TODO: set the default attributes for the next page? +} + +/** + * Returns a point whose x coordinate is the horizontal + * dots per inch of the printer, and whose y coordinate + * is the vertical dots per inch of the printer. + * + * @return the horizontal and vertical DPI + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +@Override +protected Point getDPI_() { + checkDevice(); + initPrinterData(); +// int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); +// int dpi = (int)Math.round(Math.pow(72, 2) / resolution); +// return new Point(dpi, dpi); + return new Point(dpiX, dpiY); +// int dpiX = OS.GetDeviceCaps(handle, OS.LOGPIXELSX); +// int dpiY = OS.GetDeviceCaps(handle, OS.LOGPIXELSY); +// return new Point(dpiX, dpiY); +} + +/** + * Returns a rectangle describing the receiver's size and location. + * For a printer, this is the size of a page, in pixels. + * + * @return the bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getClientArea + * @see #computeTrim + */ +@Override +public Rectangle getBounds() { + checkDevice(); +// return getClientArea(); + Point dpi = getDPI_(); + int width = (int)Math.round(referencePageFormat.getImageableWidth() * dpi.x / 72.0); + int height = (int)Math.round(referencePageFormat.getImageableHeight() * dpi.y / 72.0); + return new Rectangle(0, 0, width, height); +// int width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH); +// int height = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT); +// return new Rectangle(0, 0, width, height); +} + +PageFormat referencePageFormat; + +/** + * Returns a rectangle which describes the area of the + * receiver which is capable of displaying data. + * For a printer, this is the size of the printable area + * of a page, in pixels. + * + * @return the client area + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getBounds + * @see #computeTrim + */ +@Override +public Rectangle getClientArea() { + checkDevice(); + return getBounds(); +// int width = (int)Math.round(referencePageFormat.getImageableWidth()); +// int height = (int)Math.round(referencePageFormat.getImageableHeight()); +// return new Rectangle(0, 0, width, height); +} + +/** + * Given a desired client area for the receiver + * (as described by the arguments), returns the bounding + * rectangle which would be required to produce that client + * area. + *

    + * In other words, it returns a rectangle such that, if the + * receiver's bounds were set to that rectangle, the area + * of the receiver which is capable of displaying data + * (that is, not covered by the "trimmings") would be the + * rectangle described by the arguments (relative to the + * receiver's parent). + *

    + * Note that there is no setBounds for a printer. This method + * is usually used by passing in the client area (the 'printable + * area') of the printer. It can also be useful to pass in 0, 0, 0, 0. + * + * @param x the desired x coordinate of the client area + * @param y the desired y coordinate of the client area + * @param width the desired width of the client area + * @param height the desired height of the client area + * @return the required bounds to produce the given client area + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getBounds + * @see #getClientArea + */ +public Rectangle computeTrim(int x, int y, int width, int height) { + checkDevice(); + return new Rectangle(x, y, width, height); +} + +/** + * Returns a PrinterData object representing the + * target printer for this print job. + * + * @return a PrinterData object describing the receiver + */ +public PrinterData getPrinterData() { + return data; +} + +/** + * Checks the validity of this device. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +@Override +protected void checkDevice() { + if (handle == null) SWT.error(SWT.ERROR_DEVICE_DISPOSED); +} + +/** + * Releases any internal state prior to destroying this printer. + * This method is called internally by the dispose + * mechanism of the Device class. + */ +@Override +protected void release() { + super.release(); + data = null; +} + +/** + * Destroys the printer handle. + * This method is called internally by the dispose + * mechanism of the Device class. + */ +@Override +protected void destroy() { + handle = null; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Program/swing/org/eclipse/swt/program/Program.java b/bundles/org.eclipse.swt/Eclipse SWT Program/swing/org/eclipse/swt/program/Program.java new file mode 100644 index 00000000000..c92485533de --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Program/swing/org/eclipse/swt/program/Program.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.program; + + +import java.awt.Desktop; +import java.io.File; +import java.net.URI; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class represent programs and + * their associated file extensions in the operating + * system. + */ +public final class Program { + String name; + String command; + String iconName; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Program () { +} + +/** + * Finds the program that is associated with an extension. + * The extension may or may not begin with a '.'. Note that + * a Display must already exist to guarantee that + * this method returns an appropriate result. + * + * @param extension the program extension + * @return the program or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when extension is null
    • + *
    + */ +public static Program findProgram (String extension) { + if (extension == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (extension.length () == 0) return null; + if (extension.charAt (0) != '.') extension = "." + extension; //$NON-NLS-1$ + Utils.notImplemented(); return null; +} + +/** + * Answer all program extensions in the operating system. Note + * that a Display must already exist to guarantee + * that this method returns an appropriate result. + * + * @return an array of extensions + */ +public static String [] getExtensions () { + Utils.notImplemented(); return new String[0]; +} + +/** + * Answers all available programs in the operating system. Note + * that a Display must already exist to guarantee + * that this method returns an appropriate result. + * + * @return an array of programs + */ +public static Program [] getPrograms () { + Utils.notImplemented(); return new Program[0]; +} + +/** + * Launches the executable associated with the file in + * the operating system. If the file is an executable, + * then the executable is launched. Note that a Display + * must already exist to guarantee that this method returns + * an appropriate result. + * + * @param fileName the file or program name + * @return true if the file is launched, otherwise false + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when fileName is null
    • + *
    + */ +public static boolean launch (String fileName) { + if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if(!Compatibility.IS_JAVA_6_OR_GREATER) { + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + try { + Runtime.getRuntime().exec(fileName); + return true; + } catch(Exception e) { + } + return false; + } + ProcessBuilder pb = new ProcessBuilder(new String[] {fileName}); + try { + pb.start(); + return true; + } catch(Exception e) { + } + return false; + } + Desktop desktop = Desktop.getDesktop(); + try { + desktop.open(new File(fileName)); + return true; + } catch(Exception e) { + try { + URI uri = new URI(fileName); + if(fileName.startsWith("mailto:")) { + desktop.mail(uri); + } else if(fileName.startsWith("http:") || fileName.startsWith("https:") || fileName.startsWith("ftp:")) { + desktop.browse(uri); + } + } catch(Exception ex) { + } + } + return false; +} + +/** + * Executes the program with the file as the single argument + * in the operating system. It is the responsibility of the + * programmer to ensure that the file contains valid data for + * this program. + * + * @param fileName the file or program name + * @return true if the file is launched, otherwise false + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT when fileName is null
    • + *
    + */ +public boolean execute (String fileName) { + if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + try { + Runtime.getRuntime().exec(fileName); + return true; + } catch(Exception e) { + } + return false; + } + ProcessBuilder pb = new ProcessBuilder(new String[] {fileName}); + try { + pb.start(); + return true; + } catch(Exception e) { + return false; + } +} + +/** + * Returns the receiver's image data. This is the icon + * that is associated with the receiver in the operating + * system. + * + * @return the image data for the program, may be null + */ +public ImageData getImageData () { + Utils.notImplemented(); return null; +// int nIconIndex = 0; +// String fileName = iconName; +// int index = iconName.indexOf (','); +// if (index != -1) { +// fileName = iconName.substring (0, index); +// String iconIndex = iconName.substring (index + 1, iconName.length ()).trim (); +// try { +// nIconIndex = Integer.parseInt (iconIndex); +// } catch (NumberFormatException e) {} +// } +// /* Use the character encoding for the default locale */ +// TCHAR lpszFile = new TCHAR (0, fileName, true); +// int [] phiconSmall = new int[1], phiconLarge = null; +// OS.ExtractIconEx (lpszFile, nIconIndex, phiconLarge, phiconSmall, 1); +// if (phiconSmall [0] == 0) return null; +// Image image = Image.win32_new (null, SWT.ICON, phiconSmall[0]); +// ImageData imageData = image.getImageData (); +// image.dispose (); +// return imageData; +} + +/** + * Returns the receiver's name. This is as short and + * descriptive a name as possible for the program. If + * the program has no descriptive name, this string may + * be the executable name, path or empty. + * + * @return the name of the program + */ +public String getName () { + return name; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param other the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode() + */ +public boolean equals(Object other) { + if (this == other) return true; + if (other instanceof Program) { + final Program program = (Program) other; + return name.equals(program.name) && command.equals(program.command) + && iconName.equals(program.iconName); + } + return false; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals(Object) + */ +public int hashCode() { + return name.hashCode() ^ command.hashCode() ^ iconName.hashCode(); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the program + */ +public String toString () { + return "Program {" + name + "}"; //$NON-NLS-1$ //$NON-NLS-2$ +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Swing/swing/org/eclipse/swt/swtswing/SWT_Swing.java b/bundles/org.eclipse.swt/Eclipse SWT Swing/swing/org/eclipse/swt/swtswing/SWT_Swing.java new file mode 100644 index 00000000000..235d34a7916 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Swing/swing/org/eclipse/swt/swtswing/SWT_Swing.java @@ -0,0 +1,172 @@ +/* + * Christopher Deckers (chrriis@nextencia.net) + * http://www.nextencia.net + * + * See the file "readme.txt" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +package org.eclipse.swt.swtswing; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Image; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.CShell; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.LookAndFeelUtils; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public class SWT_Swing { + + public static class EmbeddedShell extends Shell implements CShell.CEmbeddedShell { + + static { + System.setProperty("swt.swing.laf", LookAndFeelUtils.getLookAndFeel().getClass().getName()); + } + + protected EmbeddedShell() { + super(Display.getDefault()); + ((CShell)handle).getClientArea().setLayout(new BorderLayout()); + } + + public Component getComponent() { + return handle; + } + + protected void checkSubclass () { + // Do nothing: subclassing is allowed. + } + + protected boolean isLayoutManaged() { + return true; + } + + } + + /** + * @return A parent for any SWT Control, from which a Component can be obtained and used in Swing interfaces. + */ + public static EmbeddedShell newEmbeddedShell() { + EmbeddedShell parent = new EmbeddedShell(); + manageEventDispatch(parent); + return parent; + } + + protected static class EmbeddedPanel extends JPanel implements CControl { + + protected Control handle; + + protected UserAttributeHandler userAttributeHandler; + + public UserAttributeHandler getUserAttributeHandler() { + return userAttributeHandler; + } + + public EmbeddedPanel(Control control) { + super(new BorderLayout(0, 0)); + handle = control; + userAttributeHandler = new UserAttributeHandler(this); + } + + public void setComponent(JComponent component) { + add(component, BorderLayout.CENTER); + } + + public Container getClientArea() { + return this; + } + + public void setBackgroundImage(Image backgroundImage) { + } + + public void setBackgroundInheritance(int backgroundInheritanceType) { + } + + public Container getSwingComponent() { + return this; + } + + public Control getSWTHandle() { + return handle; + } + + } + + /** + * @return A control that contains the component. + */ + public static Control newEmbeddedComponent(Composite parent, JComponent component) { + Control control = new Control(parent, SWT.NONE) { + protected void checkSubclass() { + // Trick to get the handle set before the end of the constructor of Control + handle = new EmbeddedPanel(this); + } + }; + ((EmbeddedPanel)control.handle).setComponent(component); + return control; + } + + protected static List managedCompositeList = new ArrayList(); + + /** + * Add the indicated composite to the list of composites managed by the automatic process. + * Composite must be disposed when not used anymore, to get removed from this handling. + */ + protected static void manageEventDispatch(Composite composite) { + synchronized(managedCompositeList) { + if(managedCompositeList.contains(composite)) { + return; + } + managedCompositeList.add(composite); + if(managedCompositeList.size() == 1) { + Display.swtExec(new Runnable() { + public void run() { + // We invoke later from the UI thread to make sure the queue has run once and is considered a valid thread. + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + Display display = Display.getDefault(); + boolean hasElements = true; + while(hasElements) { + if(!display.readAndDispatch ()) { + display.sleep (); + } + synchronized(managedCompositeList) { + for(Iterator it=managedCompositeList.iterator(); it.hasNext(); ) { + if(((Composite)it.next()).isDisposed()) { + it.remove(); + } + } + hasElements = !managedCompositeList.isEmpty(); + } + } + } + catch(Throwable t) { + t.printStackTrace(); + } + } + }); + } + }); + } + } + } + + public static void runSafe(Runnable runnable) { + UIThreadUtils.swtSync(Display.getDefault(), runnable); + } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java index f46baba95d5..9c589f66439 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java @@ -1,18 +1,17 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 + * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.graphics; +import org.eclipse.swt.internal.swing.CGC; + /** * Implementers of Drawable can have a graphics context (GC) @@ -20,7 +19,7 @@ * their associated GC. SWT images, and device objects such as the Display * device and the Printer device, are drawables. *

    - * IMPORTANT: This interface is not part of the SWT + * IMPORTANT: This class is not part of the SWT * public API. It is marked public only so that it can be shared * within the packages provided by SWT. It should never be * referenced from application code. @@ -44,11 +43,9 @@ public interface Drawable { * * @param data the platform specific GC data * @return the platform specific GC handle - * - * @noreference This method is not intended to be referenced by clients. */ -long internal_new_GC (GCData data); +public CGC /*long*/ internal_new_GC (GCData data); /** * Invokes platform specific functionality to dispose a GC handle. @@ -62,10 +59,8 @@ public interface Drawable { * * @param handle the platform specific GC handle * @param data the platform specific GC data - * - * @noreference This method is not intended to be referenced by clients. */ -void internal_dispose_GC (long handle, GCData data); +public void internal_dispose_GC (CGC handle, GCData data); /** * Returns true iff coordinates can be auto-scaled on this @@ -80,5 +75,4 @@ public interface Drawable { default boolean isAutoScalable () { return true; } - } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/_Drawable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/_Drawable.java new file mode 100644 index 00000000000..72a8e67fe9b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/_Drawable.java @@ -0,0 +1,84 @@ +///******************************************************************************* +// * Copyright (c) 2000, 2016 IBM Corporation and others. +// * +// * This program and the accompanying materials +// * are made available under the terms of the Eclipse Public License 2.0 +// * which accompanies this distribution, and is available at +// * https://www.eclipse.org/legal/epl-2.0/ +// * +// * SPDX-License-Identifier: EPL-2.0 +// * +// * Contributors: +// * IBM Corporation - initial API and implementation +// *******************************************************************************/ +//package org.eclipse.swt.graphics; +// +// +///** +// * Implementers of Drawable can have a graphics context (GC) +// * created for them, and then they can be drawn on by sending messages to +// * their associated GC. SWT images, and device objects such as the Display +// * device and the Printer device, are drawables. +// *

    +// * IMPORTANT: This interface is not part of the SWT +// * public API. It is marked public only so that it can be shared +// * within the packages provided by SWT. It should never be +// * referenced from application code. +// *

    +// * +// * @see Device +// * @see Image +// * @see GC +// */ +//public interface Drawable { +// +///** +// * Invokes platform specific functionality to allocate a new GC handle. +// *

    +// * IMPORTANT: This method is not part of the public +// * API for Drawable. It is marked public only so that it +// * can be shared within the packages provided by SWT. It is not +// * available on all platforms, and should never be called from +// * application code. +// *

    +// * +// * @param data the platform specific GC data +// * @return the platform specific GC handle +// * +// * @noreference This method is not intended to be referenced by clients. +// */ +// +//long internal_new_GC (GCData data); +// +///** +// * Invokes platform specific functionality to dispose a GC handle. +// *

    +// * IMPORTANT: This method is not part of the public +// * API for Drawable. It is marked public only so that it +// * can be shared within the packages provided by SWT. It is not +// * available on all platforms, and should never be called from +// * application code. +// *

    +// * +// * @param handle the platform specific GC handle +// * @param data the platform specific GC data +// * +// * @noreference This method is not intended to be referenced by clients. +// */ +//void internal_dispose_GC (long handle, GCData data); +// +///** +// * Returns true iff coordinates can be auto-scaled on this +// * drawable and false if not. E.g. a {@link GC} method should not +// * auto-scale the bounds of a figure drawn on a Printer device, but it may have +// * to auto-scale when drawing on a high-DPI Display monitor. +// * +// * @return true if auto-scaling is enabled for this drawable +// * +// * @noreference This method is not intended to be referenced by clients. +// */ +//default boolean isAutoScalable () { +// return true; +//} +// +//} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/printing/_PrinterData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/printing/_PrinterData.java new file mode 100644 index 00000000000..6c004d773f6 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/printing/_PrinterData.java @@ -0,0 +1,164 @@ +///******************************************************************************* +// * Copyright (c) 2000, 2004 IBM Corporation and others. +// * All rights reserved. This program and the accompanying materials +// * are made available under the terms of the Eclipse Public License v1.0 +// * which accompanies this distribution, and is available at +// * http://www.eclipse.org/legal/epl-v10.html +// * +// * Contributors: +// * IBM Corporation - initial API and implementation +// *******************************************************************************/ +//package org.eclipse.swt.printing; +// +// +//import javax.print.attribute.HashPrintRequestAttributeSet; +// +//import org.eclipse.swt.graphics.DeviceData; +// +///** +// * Instances of this class are descriptions of a print job +// * in terms of the printer, and the scope and type of printing +// * that is desired. For example, the number of pages and copies +// * can be specified, as well as whether or not the print job +// * should go to a file. +// *

    +// * Application code does not need to explicitly release the +// * resources managed by each instance when those instances are no longer +// * required, and thus no dispose() method is provided. +// *

    +// * +// * @see Printer +// * @see Printer#getPrinterList +// * @see PrintDialog#open +// */ +// +//public final class PrinterData extends DeviceData { +// +// /** +// * the printer driver +// * On Windows systems, this is the name of the driver (often "winspool"). +// * On X/Window systems, this is the name of a display connection to the +// * Xprt server (the default is ":1"). +// */ +// public String driver; +// +// /** +// * the name of the printer +// * On Windows systems, this is the name of the 'device'. +// * On X/Window systems, this is the printer's 'name'. +// */ +// public String name; +// +// /** +// * the scope of the print job, expressed as one of the following values: +// *
    +// *
    ALL_PAGES
    +// *
    Print all pages in the current document
    +// *
    PAGE_RANGE
    +// *
    Print the range of pages specified by startPage and endPage
    +// *
    SELECTION
    +// *
    Print the current selection
    +// *
    +// */ +// public int scope = ALL_PAGES; +// +// /** +// * the start page of a page range, used when scope is PAGE_RANGE +// */ +// public int startPage = 0; +// +// /** +// * the end page of a page range, used when scope is PAGE_RANGE +// */ +// public int endPage = 0; +// +// /** +// * whether or not the print job should go to a file +// */ +// public boolean printToFile = false; +// +// /** +// * the name of the file to print to if printToFile is true. +// * Note that this field is ignored if printToFile is false. +// */ +// public String fileName; +// +// /** +// * the number of copies to print. +// * Note that this field may be controlled by the printer driver +// * In other words, the printer itself may be capable of printing +// * multiple copies, and if so, the value of this field will always be 1. +// */ +// public int copyCount = 1; +// +// /** +// * whether or not the printer should collate the printed paper +// * Note that this field may be controlled by the printer driver. +// * In other words, the printer itself may be capable of doing the +// * collation, and if so, the value of this field will always be false. +// */ +// public boolean collate = false; +// +// /** +// * scope field value indicating that +// * all pages should be printed +// */ +// public static final int ALL_PAGES = 0; +// +// /** +// * scope field value indicating that +// * the range of pages specified by startPage and endPage +// * should be printed +// */ +// public static final int PAGE_RANGE = 1; +// +// /** +// * scope field value indicating that +// * the current selection should be printed +// */ +// public static final int SELECTION = 2; +// +// /** +// * private, platform-specific data +// * On Windows, this contains a copy of the DEVMODE struct +// * returned from the PrintDialog. +// * This field is not currently used on the X/Window System. +// */ +// HashPrintRequestAttributeSet otherData; +// +// /** +// * Constructs an instance of this class that can be +// * used to print to the default printer. +// * +// * @see Printer#getDefaultPrinterData +// */ +// public PrinterData() { +// } +// +// /** +// * Constructs an instance of this class with the given +// * printer driver and printer name. +// * +// * @param driver the printer driver for the printer +// * @param name the name of the printer +// * +// * @see #driver +// * @see #name +// */ +// public PrinterData(String driver, String name) { +// this.driver = driver; +// this.name = name; +// } +// +// /** +// * Returns a string containing a concise, human-readable +// * description of the receiver. +// * +// * @return a string representation of the receiver +// */ +// public String toString() { +// return "PrinterData {" + "driver = " + driver + ", name = " + name + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ +// } +//} + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java index 386a51a44fb..83f89545bd7 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java @@ -16,8 +16,6 @@ import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; -import org.eclipse.swt.internal.*; - /** * This class is the abstract superclass of all non-windowed * user interface objects that occur within specific controls. @@ -198,30 +196,32 @@ public void setImage (Image image) { * */ public void setText (String string) { - checkWidget (); - if (string == null) error (SWT.ERROR_NULL_ARGUMENT); - text = string; - if ((state & HAS_AUTO_DIRECTION) != 0) { - updateTextDirection (AUTO_TEXT_DIRECTION); - } +// checkWidget (); +// if (string == null) error (SWT.ERROR_NULL_ARGUMENT); +// text = string; +// if ((state & SWT.HAS_AUTO_DIRECTION) != 0) { +// updateTextDirection (AUTO_TEXT_DIRECTION); +// } + throw new UnsupportedOperationException("Not implemented yet"); } boolean updateTextDirection(int textDirection) { - /* - * textDirection argument passed here is either (1) AUTO_TEXT_DIRECTION, or - * (2) 0 (i.e. match orientation) or FLIP_TEXT_DIRECTION (mismatch orientation). - */ - if (textDirection == AUTO_TEXT_DIRECTION) { - state |= HAS_AUTO_DIRECTION; - textDirection = (style ^ BidiUtil.resolveTextDirection (text)) == 0 ? 0 : SWT.FLIP_TEXT_DIRECTION; - } else { - state &= ~HAS_AUTO_DIRECTION; - } - if (((style & SWT.FLIP_TEXT_DIRECTION) ^ textDirection) != 0) { - style ^= SWT.FLIP_TEXT_DIRECTION; - return true; - } - return textDirection == AUTO_TEXT_DIRECTION; +// /* +// * textDirection argument passed here is either (1) AUTO_TEXT_DIRECTION, or +// * (2) 0 (i.e. match orientation) or FLIP_TEXT_DIRECTION (mismatch orientation). +// */ +// if (textDirection == AUTO_TEXT_DIRECTION) { +// state |= HAS_AUTO_DIRECTION; +// textDirection = (style ^ BidiUtil.resolveTextDirection (text)) == 0 ? 0 : SWT.FLIP_TEXT_DIRECTION; +// } else { +// state &= ~HAS_AUTO_DIRECTION; +// } +// if (((style & SWT.FLIP_TEXT_DIRECTION) ^ textDirection) != 0) { +// style ^= SWT.FLIP_TEXT_DIRECTION; +// return true; +// } +// return textDirection == AUTO_TEXT_DIRECTION; + throw new UnsupportedOperationException("Not implemented yet"); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java index b27a1b790dd..f8e83b14830 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java @@ -1,34 +1,30 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 + * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.widgets; -import org.eclipse.swt.graphics.*; +import java.awt.*; + +import org.eclipse.swt.graphics.Rectangle; /** * Instances of this class are descriptions of monitors. * * @see Display - * @see
    Monitor snippets - * @see Sample code and further information * * @since 3.0 */ public final class Monitor { - long handle; + GraphicsConfiguration handle; int x, y, width, height; int clientX, clientY, clientWidth, clientHeight; - int zoom = 100; /** * Prevents uninitialized instances from being created outside the package. @@ -49,14 +45,14 @@ public final class Monitor { @Override public boolean equals (Object object) { if (object == this) return true; - if (!(object instanceof Monitor monitor)) return false; - return handle == monitor.handle; + if (!(object instanceof Monitor)) return false; + Monitor monitor = (Monitor) object; + return handle.equals(monitor.handle); } /** * Returns a rectangle describing the receiver's size and location - * relative to its device. Note that on multi-monitor systems the - * origin can be negative. + * relative to its device. * * @return the receiver's bounding rectangle */ @@ -74,31 +70,6 @@ public Rectangle getClientArea () { return new Rectangle (clientX, clientY, clientWidth, clientHeight); } -/** - * Returns the zoom value for the monitor - * - * @return monitor's zoom value - * - * @since 3.107 - */ -public int getZoom () { - return zoom; -} - -void setBounds (Rectangle rect) { - x = rect.x; - y = rect.y; - width = rect.width; - height = rect.height; -} - -void setClientArea (Rectangle rect) { - clientX = rect.x; - clientY = rect.y; - clientWidth = rect.width; - clientHeight = rect.height; -} - /** * Returns an integer hash code for the receiver. Any two * objects that return true when passed to @@ -111,7 +82,7 @@ void setClientArea (Rectangle rect) { */ @Override public int hashCode () { - return (int)handle; + return handle.hashCode(); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java index f171a0041ec..117109c4863 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java @@ -17,7 +17,6 @@ import java.util.concurrent.*; import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; /** * Instances of this class provide synchronization support @@ -120,29 +119,30 @@ boolean runAsyncMessages () { } boolean runAsyncMessages (boolean all) { - boolean run = false; - do { - RunnableLock lock = removeFirst (); - if (lock == null) return run; - run = true; - synchronized (lock) { - syncThread = lock.thread; - display.sendPreEvent(SWT.None); - try { - lock.run (display); - } catch (Throwable t) { - lock.throwable = t; - SWT.error (SWT.ERROR_FAILED_EXEC, t); - } finally { - if (display != null && !display.isDisposed()) { - display.sendPostEvent(SWT.None); - } - syncThread = null; - lock.notifyAll (); - } - } - } while (all); - return run; + throw new UnsupportedOperationException("Not implemented yet"); +// boolean run = false; +// do { +// RunnableLock lock = removeFirst (); +// if (lock == null) return run; +// run = true; +// synchronized (lock) { +// syncThread = lock.thread; +// display.sendPreEvent(SWT.None); +// try { +// lock.run (display); +// } catch (Throwable t) { +// lock.throwable = t; +// SWT.error (SWT.ERROR_FAILED_EXEC, t); +// } finally { +// if (display != null && !display.isDisposed()) { +// display.sendPostEvent(SWT.None); +// } +// syncThread = null; +// lock.notifyAll (); +// } +// } +// } while (all); +// return run; } /** @@ -160,55 +160,56 @@ boolean runAsyncMessages (boolean all) { * @see #asyncExec */ protected void syncExec (Runnable runnable) { - RunnableLock lock = null; - synchronized (Device.class) { - if (display == null || display.isDisposed ()) SWT.error (SWT.ERROR_DEVICE_DISPOSED); - if (!display.isValidThread ()) { - if (runnable == null) { - display.wake (); - return; - } - lock = new RunnableLock (runnable); - /* - * Only remember the syncThread for syncExec. - */ - lock.thread = Thread.currentThread(); - addLast (lock); - } - } - if (lock == null) { - if (runnable != null) { - display.sendPreEvent(SWT.None); - try { - runnable.run(); - } catch (RuntimeException exception) { - display.getRuntimeExceptionHandler ().accept (exception); - } catch (Error error) { - display.getErrorHandler ().accept (error); - } finally { - if (display != null && !display.isDisposed()) { - display.sendPostEvent(SWT.None); - } - } - } - return; - } - synchronized (lock) { - boolean interrupted = false; - while (!lock.done ()) { - try { - lock.wait (); - } catch (InterruptedException e) { - interrupted = true; - } - } - if (interrupted) { - Thread.currentThread().interrupt(); - } - if (lock.throwable != null) { - SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable); - } - } + throw new UnsupportedOperationException("Not implemented yet"); +// RunnableLock lock = null; +// synchronized (Device.class) { +// if (display == null || display.isDisposed ()) SWT.error (SWT.ERROR_DEVICE_DISPOSED); +// if (!display.isValidThread ()) { +// if (runnable == null) { +// display.wake (); +// return; +// } +// lock = new RunnableLock (runnable); +// /* +// * Only remember the syncThread for syncExec. +// */ +// lock.thread = Thread.currentThread(); +// addLast (lock); +// } +// } +// if (lock == null) { +// if (runnable != null) { +// display.sendPreEvent(SWT.None); +// try { +// runnable.run(); +// } catch (RuntimeException exception) { +// display.getRuntimeExceptionHandler ().accept (exception); +// } catch (Error error) { +// display.getErrorHandler ().accept (error); +// } finally { +// if (display != null && !display.isDisposed()) { +// display.sendPostEvent(SWT.None); +// } +// } +// } +// return; +// } +// synchronized (lock) { +// boolean interrupted = false; +// while (!lock.done ()) { +// try { +// lock.wait (); +// } catch (InterruptedException e) { +// interrupted = true; +// } +// } +// if (interrupted) { +// Thread.currentThread().interrupt(); +// } +// if (lock.throwable != null) { +// SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable); +// } +// } } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/__Monitor.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/__Monitor.java new file mode 100644 index 00000000000..6f647204d9f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/__Monitor.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2000, 2016 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; +// +//import org.eclipse.swt.graphics.*; +// +///** +// * Instances of this class are descriptions of monitors. +// * +// * @see Display +// * @see Monitor snippets +// * @see Sample code and further information +// * +// * @since 3.0 +// */ +//public final class Monitor { +// long handle; +// int x, y, width, height; +// int clientX, clientY, clientWidth, clientHeight; +// int zoom = 100; +// +///** +// * Prevents uninitialized instances from being created outside the package. +// */ +//Monitor () { +//} +// +///** +// * Compares the argument to the receiver, and returns true +// * if they represent the same object using a class +// * specific comparison. +// * +// * @param object the object to compare with this object +// * @return true if the object is the same as this object and false otherwise +// * +// * @see #hashCode() +// */ +//@Override +//public boolean equals (Object object) { +// if (object == this) return true; +// if (!(object instanceof Monitor monitor)) return false; +// return handle == monitor.handle; +//} +// +///** +// * Returns a rectangle describing the receiver's size and location +// * relative to its device. Note that on multi-monitor systems the +// * origin can be negative. +// * +// * @return the receiver's bounding rectangle +// */ +//public Rectangle getBounds () { +// return new Rectangle (x, y, width, height); +//} +// +///** +// * Returns a rectangle which describes the area of the +// * receiver which is capable of displaying data. +// * +// * @return the client area +// */ +//public Rectangle getClientArea () { +// return new Rectangle (clientX, clientY, clientWidth, clientHeight); +//} +// +///** +// * Returns the zoom value for the monitor +// * +// * @return monitor's zoom value +// * +// * @since 3.107 +// */ +//public int getZoom () { +// return zoom; +//} +// +//void setBounds (Rectangle rect) { +// x = rect.x; +// y = rect.y; +// width = rect.width; +// height = rect.height; +//} +// +//void setClientArea (Rectangle rect) { +// clientX = rect.x; +// clientY = rect.y; +// clientWidth = rect.width; +// clientHeight = rect.height; +//} +// +///** +// * Returns an integer hash code for the receiver. Any two +// * objects that return true when passed to +// * equals must return the same value for this +// * method. +// * +// * @return the receiver's hash +// * +// * @see #equals(Object) +// */ +//@Override +//public int hashCode () { +// return (int)handle; +//} +// +//} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Color.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Color.java new file mode 100644 index 00000000000..cf8ffb4fd1d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Color.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import org.eclipse.swt.*; + +/** + * Instances of this class manage the operating system resources that + * implement SWT's RGB color model. To create a color you can either + * specify the individual color components as integers in the range + * 0 to 255 or provide an instance of an RGB. + *

    + * Application code must explicitly invoke the Color.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @see RGB + * @see Device#getSystemColor + */ + +public final class Color extends Resource { + + /** + * the handle to the OS color resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public java.awt.Color handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Color() { +} + +/** + * Constructs a new instance of this class given a device and the + * desired red, green and blue values expressed as ints in the range + * 0 to 255 (where 0 is black and 255 is full brightness). On limited + * color devices, the color instance created by this call may not have + * the same RGB values as the ones specified by the arguments. The + * RGB values on the returned instance will be the color values of + * the operating system color. + *

    + * You must dispose the color when it is no longer required. + *

    + * + * @param device the device on which to allocate the color + * @param red the amount of red in the color + * @param green the amount of green in the color + * @param blue the amount of blue in the color + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255
    • + *
    + * + * @see #dispose + */ +public Color (Device device, int red, int green, int blue) { + if (device == null) device = Device.getDevice (); + if (device == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + init (device, red, green, blue); + if (device.tracking) device.new_Object (this); +} + +/** + * Constructs a new instance of this class given a device and an + * RGB describing the desired red, green and blue values. + * On limited color devices, the color instance created by this call + * may not have the same RGB values as the ones specified by the + * argument. The RGB values on the returned instance will be the color + * values of the operating system color. + *

    + * You must dispose the color when it is no longer required. + *

    + * + * @param device the device on which to allocate the color + * @param rgb the RGB values of the desired color + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the rgb argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255
    • + *
    + * + * @see #dispose + */ +public Color (Device device, RGB rgb) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init (device, rgb.red, rgb.green, rgb.blue); + if (device.tracking) device.new_Object(this); +} + +public Color(int red, int green, int blue) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +public Color(RGB closeFill) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +private void init (Device device, int red, int green, int blue) { + if (!(0 <= red && red <= 255) || !(0 <= green && green <= 255) + || !(0 <= blue && blue <= 255)) + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + this.device = device; + this.handle = new java.awt.Color (red, green, blue); +} + +/** + * Disposes of the operating system resources associated with + * the color. Applications must dispose of all colors which + * they allocate. + */ +@Override +public void dispose() { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +@Override +public boolean equals (Object object) { + if (object == this) return true; + if (!(object instanceof Color)) return false; + Color color = (Color) object; + return device == color.device && handle.equals(color.handle); +} + +/** + * Returns the amount of blue in the color, from 0 to 255. + * + * @return the blue component of the color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getBlue () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.getBlue(); +} + +/** + * Returns the amount of green in the color, from 0 to 255. + * + * @return the green component of the color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getGreen () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.getGreen(); +} + +/** + * Returns the amount of red in the color, from 0 to 255. + * + * @return the red component of the color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getRed () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.getRed(); +} + +/** + * Returns an RGB representing the receiver. + * + * @return the RGB for the color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public RGB getRGB () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return new RGB(handle.getRed(), handle.getGreen(), handle.getBlue()); +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects which return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +@Override +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +/** + * Returns true if the color has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the color. + * When a color has been disposed, it is an error to + * invoke any other method using the color. + * + * @return true when the color is disposed and false otherwise + */ +@Override +public boolean isDisposed() { + return handle == null; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +@Override +public String toString () { + if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$ + return "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ +} + +/** + * Invokes platform specific functionality to allocate a new color. + *

    + * IMPORTANT: This method is not part of the public + * API for Color. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param device the device on which to allocate the color + * @param handle the handle for the color + * @return a new color object containing the specified device and handle + */ +public static Color swing_new(Device device, java.awt.Color handle) { + if (device == null) device = Device.getDevice(); + Color color = new Color(); + color.handle = handle; + color.device = device; + return color; +} + +public int getAlpha() { + throw new UnsupportedOperationException("Not implemented yet"); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java new file mode 100644 index 00000000000..9a3f04868a2 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java @@ -0,0 +1,446 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.MissingResourceException; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import javax.swing.ImageIcon; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; + +/** + * Instances of this class manage operating system resources that + * specify the appearance of the on-screen pointer. To create a + * cursor you specify the device and either a simple cursor style + * describing one of the standard operating system provided cursors + * or the image and mask data for the desired appearance. + *

    + * Application code must explicitly invoke the Cursor.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + *
    + *
    Styles:
    + *
    + * CURSOR_ARROW, CURSOR_WAIT, CURSOR_CROSS, CURSOR_APPSTARTING, CURSOR_HELP, + * CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE, + * CURSOR_SIZEN, CURSOR_SIZES, CURSOR_SIZEE, CURSOR_SIZEW, CURSOR_SIZENE, CURSOR_SIZESE, + * CURSOR_SIZESW, CURSOR_SIZENW, CURSOR_UPARROW, CURSOR_IBEAM, CURSOR_NO, CURSOR_HAND + *
    + *
    + *

    + * Note: Only one of the above styles may be specified. + *

    + */ + +public final class Cursor extends Resource { + + /** + * the handle to the OS cursor resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public java.awt.Cursor handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Cursor() { +} + +/** + * Constructs a new cursor given a device and a style + * constant describing the desired cursor appearance. + *

    + * You must dispose the cursor when it is no longer required. + *

    + * + * @param device the device on which to allocate the cursor + * @param style the style of cursor to allocate + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_INVALID_ARGUMENT - when an unknown style is specified
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
    • + *
    + * + * @see SWT#CURSOR_ARROW + * @see SWT#CURSOR_WAIT + * @see SWT#CURSOR_CROSS + * @see SWT#CURSOR_APPSTARTING + * @see SWT#CURSOR_HELP + * @see SWT#CURSOR_SIZEALL + * @see SWT#CURSOR_SIZENESW + * @see SWT#CURSOR_SIZENS + * @see SWT#CURSOR_SIZENWSE + * @see SWT#CURSOR_SIZEWE + * @see SWT#CURSOR_SIZEN + * @see SWT#CURSOR_SIZES + * @see SWT#CURSOR_SIZEE + * @see SWT#CURSOR_SIZEW + * @see SWT#CURSOR_SIZENE + * @see SWT#CURSOR_SIZESE + * @see SWT#CURSOR_SIZESW + * @see SWT#CURSOR_SIZENW + * @see SWT#CURSOR_UPARROW + * @see SWT#CURSOR_IBEAM + * @see SWT#CURSOR_NO + * @see SWT#CURSOR_HAND + */ +public Cursor(Device device, int style) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + switch (style) { + case SWT.CURSOR_HAND: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR); break; + case SWT.CURSOR_ARROW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); break; + case SWT.CURSOR_WAIT: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR); break; + case SWT.CURSOR_CROSS: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.CROSSHAIR_CURSOR); break; + case SWT.CURSOR_SIZEALL: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.MOVE_CURSOR); break; + case SWT.CURSOR_SIZEN: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.N_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZES: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.S_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZEE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.E_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZEW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.W_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZENE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NE_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZESE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.SE_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZESW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.SW_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZENW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NW_RESIZE_CURSOR); break; + case SWT.CURSOR_IBEAM: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.TEXT_CURSOR); break; + // Cursor that do not fit exactly with the description: + case SWT.CURSOR_APPSTARTING: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR); break; + case SWT.CURSOR_SIZEWE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.E_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZENS: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.N_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZENESW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NE_RESIZE_CURSOR); break; + case SWT.CURSOR_SIZENWSE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NW_RESIZE_CURSOR); break; + // Custom cursors + case SWT.CURSOR_UPARROW: + case SWT.CURSOR_NO: + case SWT.CURSOR_HELP: + handle = createCursor(style); + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (device.tracking) device.new_Object(this); +} + +java.awt.Cursor createCursor(int type) { + String name = ""; + switch(type) { + case SWT.CURSOR_UPARROW: name = "UpCursor"; break; + case SWT.CURSOR_NO: name = "NoCursor"; break; + case SWT.CURSOR_HELP: name = "HelpCursor"; break; + default: return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR); + } + // Get the Property file + InputStream is = getClass().getResourceAsStream("resources/" + name + ".properties"); + if (is == null) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } + String gifFile = null; + String hotspot = null; + try { + ResourceBundle resource = new PropertyResourceBundle(is); + gifFile = "resources/" + resource.getString("Cursor.File"); + hotspot = resource.getString("Cursor.HotSpot"); + } catch (MissingResourceException e) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } catch (IOException e2) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } + // Create the icon + byte[] buffer = null; + try { + InputStream resource = getClass().getResourceAsStream(gifFile); + if (resource == null) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } + BufferedInputStream in = new BufferedInputStream(resource); + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + buffer = new byte[1024]; + int n; + while ((n = in.read(buffer)) > 0) { + out.write(buffer, 0, n); + } + in.close(); + out.flush(); + buffer = out.toByteArray(); + if (buffer.length == 0) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } + } catch (IOException ioe) { + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } + ImageIcon icon = new ImageIcon(buffer); + // create the point + int k = hotspot.indexOf(','); + java.awt.Point point = new java.awt.Point(Integer.parseInt(hotspot.substring(0, k)), Integer.parseInt(hotspot.substring(k + 1))); + try { + return Toolkit.getDefaultToolkit().createCustomCursor(icon.getImage(), point, name); + } catch (NoSuchMethodError err) { + // return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); + } +} + +/** + * Constructs a new cursor given a device, image and mask + * data describing the desired cursor appearance, and the x + * and y coordinates of the hotspot (that is, the point + * within the area covered by the cursor which is considered + * to be where the on-screen pointer is "pointing"). + *

    + * The mask data is allowed to be null, but in this case the source + * must be an ImageData representing an icon that specifies both + * color data and mask data. + *

    + * You must dispose the cursor when it is no longer required. + *

    + * + * @param device the device on which to allocate the cursor + * @param source the color data for the cursor + * @param mask the mask data for the cursor (or null) + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the source is null
    • + *
    • ERROR_NULL_ARGUMENT - if the mask is null and the source does not have a mask
    • + *
    • ERROR_INVALID_ARGUMENT - if the source and the mask are not the same + * size, or if the hotspot is outside the bounds of the image
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
    • + *
    + */ +public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (mask == null) { + if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + mask = source.getTransparencyMask(); + } + /* Check the bounds. Mask must be the same size as source */ + if (mask.width != source.width || mask.height != source.height) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + /* Check the hotspots */ + if (hotspotX >= source.width || hotspotX < 0 || + hotspotY >= source.height || hotspotY < 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + /* Convert depth to 1 */ + mask = ImageData.convertMask(mask); + source = ImageData.convertMask(source); + + BufferedImage image = new BufferedImage(source.width, source.height, BufferedImage.TYPE_INT_ARGB); + PaletteData palette = source.palette; + if (palette.isDirect) { + for(int x=0; x 0) { + pixel = pixel & 0x00FFFFFF | alpha << 24; + image.setRGB(x, y, pixel); + } + } + } + } + } else { + for(int x=0; x 0) { + image.setRGB(x, y, 0xFFFFFFFF); + } else { + image.setRGB(x, y, 0xFF000000); + } + } + } + } + } + +// /* Make sure source and mask scanline pad is 2 */ +// byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2); +// byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2); + createCursor(image, hotspotX, hotspotY); + if (device.tracking) device.new_Object(this); +} + +protected void createCursor(BufferedImage image, int hotspotX, int hotspotY) { + handle = Toolkit.getDefaultToolkit().createCustomCursor(image, new java.awt.Point(hotspotX, hotspotY), "Custom Cursor"); +} + +/** + * Constructs a new cursor given a device, image data describing + * the desired cursor appearance, and the x and y coordinates of + * the hotspot (that is, the point within the area + * covered by the cursor which is considered to be where the + * on-screen pointer is "pointing"). + *

    + * You must dispose the cursor when it is no longer required. + *

    + * + * @param device the device on which to allocate the cursor + * @param source the image data for the cursor + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the image is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the + * image
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
    • + *
    + * + * @since 3.0 + */ +public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + /* Check the hotspots */ + if (hotspotX >= source.width || hotspotX < 0 || + hotspotY >= source.height || hotspotY < 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + createCursor(new Image(device, source).handle, hotspotX, hotspotY); + if (device.tracking) device.new_Object(this); +} + +/** + * Disposes of the operating system resources associated with + * the cursor. Applications must dispose of all cursors which + * they allocate. + */ +public void dispose () { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public boolean equals (Object object) { + if (object == this) return true; + if (!(object instanceof Cursor)) return false; + Cursor cursor = (Cursor) object; + return device == cursor.device && handle == cursor.handle; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects which return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +/** + * Returns true if the cursor has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the cursor. + * When a cursor has been disposed, it is an error to + * invoke any other method using the cursor. + * + * @return true when the cursor is disposed and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString () { + if (isDisposed()) return "Cursor {*DISPOSED*}"; + return "Cursor {" + handle + "}"; +} + +/** + * Invokes platform specific functionality to allocate a new cursor. + *

    + * IMPORTANT: This method is not part of the public + * API for Cursor. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param device the device on which to allocate the color + * @param handle the handle for the cursor + * @return a new cursor object containing the specified device and handle + */ +public static Cursor swing_new(Device device, java.awt.Cursor handle) { + if (device == null) device = Device.getDevice(); + Cursor cursor = new Cursor(); + cursor.handle = handle; + cursor.device = device; + return cursor; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java new file mode 100644 index 00000000000..04ed1c7d22c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java @@ -0,0 +1,829 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.DisplayMode; +import java.awt.GraphicsEnvironment; +import java.awt.Toolkit; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.swing.CGC; +import org.eclipse.swt.internal.swing.LookAndFeelUtils; + +/** + * This class is the abstract superclass of all device objects, + * such as the Display device and the Printer device. Devices + * can have a graphics context (GC) created for them, and they + * can be drawn on by sending messages to the associated GC. + */ +public abstract class Device implements Drawable { + + /* Debugging */ + public static boolean DEBUG; + boolean debug = DEBUG; + boolean tracking = DEBUG; + Error [] errors; + Object [] objects; + +// /** +// * Palette +// * (Warning: This field is platform dependent) +// *

    +// * IMPORTANT: This field is not part of the SWT +// * public API. It is marked public only so that it can be shared +// * within the packages provided by SWT. It is not available on all +// * platforms and should never be accessed from application code. +// *

    +// */ +// public int hPalette = 0; +// int [] colorRefCount; + +// /* Font Enumeration */ +// int nFonts = 256; +// LOGFONT [] logFonts; + +// /* Scripts */ +// int [] scripts; + +// /* Advanced Graphics */ +// int [] gdipToken; + + boolean disposed; + + final static Object CREATE_LOCK = new Object(); + + /* + * TEMPORARY CODE. When a graphics object is + * created and the device parameter is null, + * the current Display is used. This presents + * a problem because SWT graphics does not + * reference classes in SWT widgets. The correct + * fix is to remove this feature. Unfortunately, + * too many application programs rely on this + * feature. + * + * This code will be removed in the future. + */ + protected static Device CurrentDevice; + protected static Runnable DeviceFinder; + static { + try { + Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$ + } catch (Throwable e) {} + } + +/* +* TEMPORARY CODE. +*/ +static synchronized Device getDevice () { + if (DeviceFinder != null) DeviceFinder.run(); + Device device = CurrentDevice; + CurrentDevice = null; + return device; +} + +/** + * Constructs a new instance of this class. + *

    + * You must dispose the device when it is no longer required. + *

    + * + * @see #create + * @see #init + * + * @since 3.1 + */ +public Device() { + this(null); +} + +/** + * Constructs a new instance of this class. + *

    + * You must dispose the device when it is no longer required. + *

    + * + * @param data the DeviceData which describes the receiver + * + * @see #create + * @see #init + * @see DeviceData + */ +public Device(DeviceData data) { + synchronized (CREATE_LOCK) { + if (data != null) { + debug = data.debug; + tracking = data.tracking; + } + create (data); + init (); + if (tracking) { + errors = new Error [128]; + objects = new Object [128]; + } + } +} + +/** + * Throws an SWTException if the receiver can not + * be accessed by the caller. This may include both checks on + * the state of the receiver and more generally on the entire + * execution context. This method should be called by + * device implementors to enforce the standard SWT invariants. + *

    + * Currently, it is an error to invoke any method (other than + * isDisposed() and dispose()) on a + * device that has had its dispose() method called. + *

    + * In future releases of SWT, there may be more or fewer error + * checks and exceptions may be thrown for different reasons. + *

    + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    + */ +protected void checkDevice () { + if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED); +} + +//void checkGDIP() { +// if (gdipToken != null) return; +// int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS); +// try { +// int [] token = new int [1]; +// GdiplusStartupInput input = new GdiplusStartupInput (); +// input.GdiplusVersion = 1; +// if (Gdip.GdiplusStartup (token, input, 0) == 0) { +// gdipToken = token; +// } +// } catch (Throwable t) { +// SWT.error (SWT.ERROR_NO_GRAPHICS_LIBRARY, t); +// } finally { +// OS.SetErrorMode (oldErrorMode); +// } +//} + +/** + * Creates the device in the operating system. If the device + * does not have a handle, this method may do nothing depending + * on the device. + *

    + * This method is called before init. + *

    + * Subclasses are supposed to reimplement this method and not + * call the super implementation. + *

    + * + * @param data the DeviceData which describes the receiver + * + * @see #init + */ +protected void create (DeviceData data) { +} + +//int computePixels(int height) { +// int hDC = internal_new_GC (null); +// int pixels = -Compatibility.round(height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY), 72); +// internal_dispose_GC (hDC, null); +// return pixels; +//} +// +//int computePoints(LOGFONT logFont) { +// int hDC = internal_new_GC (null); +// int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY); +// int pixels = 0; +// if (logFont.lfHeight > 0) { +// /* +// * Feature in Windows. If the lfHeight of the LOGFONT structure +// * is positive, the lfHeight measures the height of the entire +// * cell, including internal leading, in logical units. Since the +// * height of a font in points does not include the internal leading, +// * we must subtract the internal leading, which requires a TEXTMETRIC, +// * which in turn requires font creation. +// */ +// int hFont = OS.CreateFontIndirect(logFont); +// int oldFont = OS.SelectObject(hDC, hFont); +// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA(); +// OS.GetTextMetrics(hDC, lptm); +// OS.SelectObject(hDC, oldFont); +// OS.DeleteObject(hFont); +// pixels = logFont.lfHeight - lptm.tmInternalLeading; +// } else { +// pixels = -logFont.lfHeight; +// } +// internal_dispose_GC (hDC, null); +// +// return Compatibility.round(pixels * 72, logPixelsY); +//} + +/** + * Destroys the device in the operating system and releases + * the device's handle. If the device does not have a handle, + * this method may do nothing depending on the device. + *

    + * This method is called after release. + *

    + * Subclasses are supposed to reimplement this method and not + * call the super implementation. + *

    + * + * @see #dispose + * @see #release + */ +protected void destroy () { +} + +/** + * Disposes of the operating system resources associated with + * the receiver. After this method has been invoked, the receiver + * will answer true when sent the message + * isDisposed(). + * + * @see #release + * @see #destroy + * @see #checkDevice + */ +public void dispose () { + if (isDisposed()) return; + checkDevice (); + release (); + destroy (); + disposed = true; + if (tracking) { + objects = null; + errors = null; + } +} + +void dispose_Object (Object object) { + for (int i=0; i + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + */ +public Rectangle getBounds () { + checkDevice (); + //TODO: implement method + throw new IllegalStateException("Not implemented!"); +// int hDC = internal_new_GC (null); +// int width = OS.GetDeviceCaps (hDC, OS.HORZRES); +// int height = OS.GetDeviceCaps (hDC, OS.VERTRES); +// internal_dispose_GC (hDC, null); +// return new Rectangle (0, 0, width, height); +} + +/** + * Returns a DeviceData based on the receiver. + * Modifications made to this DeviceData will not + * affect the receiver. + * + * @return a DeviceData containing the device's data and attributes + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see DeviceData + */ +public DeviceData getDeviceData () { + checkDevice(); + DeviceData data = new DeviceData (); + data.debug = debug; + data.tracking = tracking; + int count = 0, length = 0; + if (tracking) length = objects.length; + for (int i=0; i + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + * + * @see #getBounds + */ +public Rectangle getClientArea () { + return getBounds (); +} + +/** + * Returns the bit depth of the screen, which is the number of + * bits it takes to represent the number of unique colors that + * the screen is currently capable of displaying. This number + * will typically be one of 1, 8, 15, 16, 24 or 32. + * + * @return the depth of the screen + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getDepth () { + checkDevice (); +// int hDC = internal_new_GC (null); +// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL); +// int planes = OS.GetDeviceCaps (hDC, OS.PLANES); +// internal_dispose_GC (hDC, null); +// return bits * planes; + // TODO: is this correct? + DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode(); + if(displayMode == null) { + return 32; + } + int bitDepth = displayMode.getBitDepth(); + return bitDepth == DisplayMode.BIT_DEPTH_MULTI? 32: bitDepth; +} + +/** + * Returns a point whose x coordinate is the horizontal + * dots per inch of the display, and whose y coordinate + * is the vertical dots per inch of the display. + * + * @return the horizontal and vertical DPI + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Point getDPI () { + checkDevice (); + return getDPI_(); +// int hDC = internal_new_GC (null); +// int dpiX = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX); +// int dpiY = OS.GetDeviceCaps (hDC, OS.LOGPIXELSY); +// internal_dispose_GC (hDC, null); +// return new Point (dpiX, dpiY); +} + +protected Point getDPI_() { + int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); + return new Point(resolution, resolution); +} + +/** + * Returns FontData objects which describe + * the fonts that match the given arguments. If the + * faceName is null, all fonts will be returned. + * + * @param faceName the name of the font to look for, or null + * @param scalable if true only scalable fonts are returned, otherwise only non-scalable fonts are returned. + * @return the matching font data + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public FontData [] getFontList (String faceName, boolean scalable) { + checkDevice (); + if(!scalable) { + return new FontData[0]; + } + // TODO: propose all styles? + java.awt.Font[] fonts; + if(faceName != null) { + java.awt.Font font = new java.awt.Font(faceName, java.awt.Font.PLAIN, 1); + if(!"Dialog".equals(faceName) && "Dialog".equals(font.getFamily())) { + fonts = new java.awt.Font[0]; + } else { + fonts = new java.awt.Font[] {font}; + } + } else { + fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); + } + FontData[] results = new FontData[fonts.length]; + for(int i=0; iSWT. Any value other + * than one of the SWT color constants which is passed + * in will result in the color black. This color should + * not be freed because it was allocated by the system, + * not the application. + * + * @param id the color constant + * @return the matching color + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see SWT + */ +public Color getSystemColor (int id) { + checkDevice (); + java.awt.Color pixel = java.awt.Color.BLACK; + switch (id) { + case SWT.COLOR_WHITE: pixel = java.awt.Color.WHITE; break; + case SWT.COLOR_BLACK: pixel = java.awt.Color.BLACK; break; + case SWT.COLOR_RED: pixel = java.awt.Color.RED; break; + case SWT.COLOR_DARK_RED: pixel = java.awt.Color.RED.darker(); break; + case SWT.COLOR_GREEN: pixel = java.awt.Color.GREEN; break; + case SWT.COLOR_DARK_GREEN: pixel = java.awt.Color.GREEN.darker(); break; + case SWT.COLOR_YELLOW: pixel = java.awt.Color.YELLOW; break; + case SWT.COLOR_DARK_YELLOW: pixel = java.awt.Color.YELLOW.darker(); break; + case SWT.COLOR_BLUE: pixel = java.awt.Color.BLUE; break; + case SWT.COLOR_DARK_BLUE: pixel = java.awt.Color.BLUE.darker(); break; + case SWT.COLOR_MAGENTA: pixel = java.awt.Color.MAGENTA; break; + case SWT.COLOR_DARK_MAGENTA: pixel = java.awt.Color.MAGENTA.darker(); break; + case SWT.COLOR_CYAN: pixel = java.awt.Color.CYAN; break; + case SWT.COLOR_DARK_CYAN: pixel = java.awt.Color.CYAN.darker(); break; + case SWT.COLOR_GRAY: pixel = java.awt.Color.GRAY; break; + case SWT.COLOR_DARK_GRAY: pixel = java.awt.Color.GRAY.darker(); break; + } + return Color.swing_new (this, pixel); +} + +/** + * Returns a reasonable font for applications to use. + * On some platforms, this will match the "default font" + * or "system font" if such can be found. This font + * should not be freed because it was allocated by the + * system, not the application. + *

    + * Typically, applications which want the default look + * should simply not set the font on the widgets they + * create. Widgets are always created with the correct + * default font for the class of user-interface component + * they represent. + *

    + * + * @return a font + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Font getSystemFont () { + checkDevice (); + return Font.swing_new (this, LookAndFeelUtils.getSystemFont()); +} + +/** + * Returns true if the underlying window system prints out + * warning messages on the console, and setWarnings + * had previously been called with true. + * + * @return trueif warnings are being handled, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean getWarnings () { + checkDevice (); + return false; +} + +/** + * Initializes any internal resources needed by the + * device. + *

    + * This method is called after create. + *

    + * If subclasses reimplement this method, they must + * call the super implementation. + *

    + * + * @see #create + */ +protected void init () { +// if (debug) { +// if (!OS.IsWinCE) OS.GdiSetBatchLimit(1); +// } +// +// /* Initialize scripts list */ +// if (!OS.IsWinCE) { +// int [] ppSp = new int [1]; +// int [] piNumScripts = new int [1]; +// OS.ScriptGetProperties (ppSp, piNumScripts); +// scripts = new int [piNumScripts [0]]; +// OS.MoveMemory (scripts, ppSp [0], scripts.length * 4); +// } +// +// /* +// * If we're not on a device which supports palettes, +// * don't create one. +// */ +// int hDC = internal_new_GC (null); +// int rc = OS.GetDeviceCaps (hDC, OS.RASTERCAPS); +// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL); +// int planes = OS.GetDeviceCaps (hDC, OS.PLANES); +// +// bits *= planes; +// if ((rc & OS.RC_PALETTE) == 0 || bits != 8) { +// internal_dispose_GC (hDC, null); +// return; +// } +// +// int numReserved = OS.GetDeviceCaps (hDC, OS.NUMRESERVED); +// int numEntries = OS.GetDeviceCaps (hDC, OS.SIZEPALETTE); +// +// if (OS.IsWinCE) { +// /* +// * Feature on WinCE. For some reason, certain 8 bit WinCE +// * devices return 0 for the number of reserved entries in +// * the system palette. Their system palette correctly contains +// * the usual 20 system colors. The workaround is to assume +// * there are 20 reserved system colors instead of 0. +// */ +// if (numReserved == 0 && numEntries >= 20) numReserved = 20; +// } +// +// /* Create the palette and reference counter */ +// colorRefCount = new int [numEntries]; +// +// /* 4 bytes header + 4 bytes per entry * numEntries entries */ +// byte [] logPalette = new byte [4 + 4 * numEntries]; +// +// /* 2 bytes = special header */ +// logPalette [0] = 0x00; +// logPalette [1] = 0x03; +// +// /* 2 bytes = number of colors, LSB first */ +// logPalette [2] = 0; +// logPalette [3] = 1; +// +// /* +// * Create a palette which contains the system entries +// * as they are located in the system palette. The +// * MSDN article 'Memory Device Contexts' describes +// * where system entries are located. On an 8 bit +// * display with 20 reserved colors, the system colors +// * will be the first 10 entries and the last 10 ones. +// */ +// byte[] lppe = new byte [4 * numEntries]; +// OS.GetSystemPaletteEntries (hDC, 0, numEntries, lppe); +// /* Copy all entries from the system palette */ +// System.arraycopy (lppe, 0, logPalette, 4, 4 * numEntries); +// /* Lock the indices corresponding to the system entries */ +// for (int i = 0; i < numReserved / 2; i++) { +// colorRefCount [i] = 1; +// colorRefCount [numEntries - 1 - i] = 1; +// } +// internal_dispose_GC (hDC, null); +// hPalette = OS.CreatePalette (logPalette); +} + +/** + * Invokes platform specific functionality to allocate a new GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Device. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param data the platform specific GC data + * @return the platform specific GC handle + */ +public abstract CGC internal_new_GC (GCData data); + +/** + * Invokes platform specific functionality to dispose a GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Device. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param handle the platform specific GC handle + * @param data the platform specific GC data + */ +public abstract void internal_dispose_GC (CGC handle, GCData data); + +/** + * Returns true if the device has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the device. + * When a device has been disposed, it is an error to + * invoke any other method using the device. + * + * @return true when the device is disposed and false otherwise + */ +public boolean isDisposed () { + return disposed; +} + +void new_Object (Object object) { + for (int i=0; i + * When a device is destroyed, resources that were acquired + * on behalf of the programmer need to be returned to the + * operating system. For example, if the device allocated a + * font to be used as the system font, this font would be + * freed in release. Also,to assist the garbage + * collector and minimize the amount of memory that is not + * reclaimed when the programmer keeps a reference to a + * disposed device, all fields except the handle are zero'd. + * The handle is needed by destroy. + *

    + * This method is called before destroy. + *

    + * If subclasses reimplement this method, they must + * call the super implementation. + *

    + * + * @see #dispose + * @see #destroy + */ +protected void release () { +// if (gdipToken != null) { +// Gdip.GdiplusShutdown (gdipToken); +// } +// gdipToken = null; +// scripts = null; +// if (hPalette != 0) OS.DeleteObject (hPalette); +// hPalette = 0; +// colorRefCount = null; +// logFonts = null; +// nFonts = 0; +} + +/** + * If the underlying window system supports printing warning messages + * to the console, setting warnings to true prevents these + * messages from being printed. If the argument is false + * message printing is not blocked. + * + * @param warnings trueif warnings should be handled, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setWarnings (boolean warnings) { + checkDevice (); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java new file mode 100644 index 00000000000..593b25584db --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +public class DeviceData { + /* + * Debug fields - may not be honoured + * on some SWT platforms. + */ + public boolean debug; + public boolean tracking; + public Error [] errors; + public Object [] objects; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java new file mode 100644 index 00000000000..7b201c260ed --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java @@ -0,0 +1,279 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.font.TextAttribute; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; + +/** + * Instances of this class manage operating system resources that + * define how text looks when it is displayed. Fonts may be constructed + * by providing a device and either name, size and style information + * or a FontData object which encapsulates this data. + *

    + * Application code must explicitly invoke the Font.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @see FontData + */ + +public final class Font extends Resource { + + /** + * the handle to the OS font resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public java.awt.Font handle; + + FontData fontData; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Font() { +} + +/** + * Constructs a new font given a device and font data + * which describes the desired font's appearance. + *

    + * You must dispose the font when it is no longer required. + *

    + * + * @param device the device to create the font on + * @param fd the FontData that describes the desired font (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the fd argument is null
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a font could not be created from the given font data
    • + *
    + */ +public Font(Device device, FontData fd) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, fd); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new font given a device and an array + * of font data which describes the desired font's + * appearance. + *

    + * You must dispose the font when it is no longer required. + *

    + * + * @param device the device to create the font on + * @param fds the array of FontData that describes the desired font (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the fds argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the length of fds is zero
    • + *
    • ERROR_NULL_ARGUMENT - if any fd in the array is null
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a font could not be created from the given font data
    • + *
    + * + * @since 2.1 + */ +public Font(Device device, FontData[] fds) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (fds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (fds.length == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + for (int i=0; i + * You must dispose the font when it is no longer required. + *

    + * + * @param device the device to create the font on + * @param name the name of the font (must not be null) + * @param height the font height in points + * @param style a bit or combination of NORMAL, BOLD, ITALIC + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the name argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the height is negative
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES - if a font could not be created from the given arguments
    • + *
    + */ +public Font(Device device, String name, int height, int style) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, new FontData (name, height, style)); + if (device.tracking) device.new_Object(this); +} + +/** + * Disposes of the operating system resources associated with + * the font. Applications must dispose of all fonts which + * they allocate. + */ +public void dispose() { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public boolean equals(Object object) { + if (object == this) return true; + if (!(object instanceof Font)) return false; + Font font = (Font) object; + return device == font.device && handle == font.handle; +} + +/** + * Returns an array of FontDatas representing the receiver. + * On Windows, only one FontData will be returned per font. On X however, + * a Font object may be composed of multiple X + * fonts. To support this case, we return an array of font data objects. + * + * @return an array of font data objects describing the receiver + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public FontData[] getFontData() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return new FontData[] {new FontData(fontData)}; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +void init (Device device, FontData fd) { + if (fd == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + fontData = new FontData(fd); + int style = fd.getStyle(); + int height = Math.round(fd.getHeight() * device.getDPI().x / 72.0f); + if(fontData.data != null) { + Map attributeMap = new HashMap(fontData.data); + attributeMap.put(TextAttribute.FAMILY, fd.getName()); + attributeMap.put(TextAttribute.POSTURE, (style & SWT.ITALIC) != 0? TextAttribute.POSTURE_OBLIQUE: TextAttribute.POSTURE_REGULAR); + attributeMap.put(TextAttribute.WEIGHT, (style & SWT.BOLD) != 0? TextAttribute.WEIGHT_BOLD: TextAttribute.WEIGHT_REGULAR); + handle = new java.awt.Font(attributeMap); + } else { + handle = new java.awt.Font(fd.getName(), 0 + | (((style & SWT.ITALIC) != 0 ? java.awt.Font.ITALIC : 0)) + | (((style & SWT.BOLD) != 0 ? java.awt.Font.BOLD : 0)), height); + } +// handle = new java.awt.Font(fd.getName(), 0 | (((style & SWT.ITALIC) != 0? java.awt.Font.ITALIC: 0)) | (((style & SWT.BOLD) != 0? java.awt.Font.BOLD: 0)), fd.getHeight()); +} + +/** + * Returns true if the font has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the font. + * When a font has been disposed, it is an error to + * invoke any other method using the font. + * + * @return true when the font is disposed and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString () { + if (isDisposed()) return "Font {*DISPOSED*}"; + return "Font {" + handle + "}"; +} + +/** + * Invokes platform specific functionality to allocate a new font. + *

    + * IMPORTANT: This method is not part of the public + * API for Font. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param device the device on which to allocate the font + * @param handle the handle for the font + * @return a new font object containing the specified device and handle + */ +public static Font swing_new(Device device, java.awt.Font handle) { + if (device == null) device = Device.getDevice(); + Font font = new Font(); + font.handle = handle; + font.device = device; + int style = handle.getStyle(); + int height = Math.round(handle.getSize() * 72.0f / device.getDPI_().x); + font.fontData = new FontData(handle.getName(), height, 0 | (((style & java.awt.Font.ITALIC) != 0? SWT.ITALIC: 0)) | (((style & java.awt.Font.BOLD) != 0? SWT.BOLD: 0))); + return font; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java new file mode 100644 index 00000000000..6bbc1f8146b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java @@ -0,0 +1,445 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.util.Map; + +import org.eclipse.swt.SWT; + +/** + * Instances of this class describe operating system fonts. + *

    + * For platform-independent behaviour, use the get and set methods + * corresponding to the following properties: + *

    + *
    height
    the height of the font in points
    + *
    name
    the face name of the font, which may include the foundry
    + *
    style
    A bitwise combination of NORMAL, ITALIC and BOLD
    + *
    + * If extra, platform-dependent functionality is required: + *
      + *
    • On Windows, the data member of the FontData + * corresponds to a Windows LOGFONT structure whose fields + * may be retrieved and modified.
    • + *
    • On X, the fields of the FontData correspond + * to the entries in the font's XLFD name and may be retrieved and modified. + *
    + * Application code does not need to explicitly release the + * resources managed by each instance when those instances are no longer + * required, and thus no dispose() method is provided. + * + * @see Font + */ + +public final class FontData { + + /** + * A Swing font Map of TextAttributes + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public Map data; + + /** + * The height of the font data in points + * (Warning: This field is platform dependent) + */ + int height; + + /** + * The style of the font data + * (Warning: This field is platform dependent) + */ + int style; + + /** + * The name of the font data + * (Warning: This field is platform dependent) + */ + String name; + + /** + * The locale of the font data + * (Warning: This field is platform dependent) + */ + java.util.Locale locale; + +/** + * Constructs a new un-initialized font data. + */ +public FontData() { + height = 12; +} + +/** + * Constructs a new font data given the Swing Font + * that it should represent. + * + * @param font the Font for the result + */ +FontData(FontData fontData) { + this.height = fontData.height; + this.style = fontData.style; + this.name = fontData.name; + this.locale = fontData.locale; + this.data = fontData.data; +} + +/** + * Constructs a new FontData given a string representation + * in the form generated by the FontData.toString + * method. + *

    + * Note that the representation varies between platforms, + * and a FontData can only be created from a string that was + * generated on the same platform. + *

    + * + * @param string the string representation of a FontData (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the argument does not represent a valid description
    • + *
    + * + * @see #toString + */ +public FontData(String string) { + if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + int start = 0; + int end = string.indexOf('|'); + if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + String version1 = string.substring(start, end); + try { + if (Integer.parseInt(version1) != 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } catch (NumberFormatException e) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + start = end + 1; + end = string.indexOf('|', start); + if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + String name = string.substring(start, end); + + start = end + 1; + end = string.indexOf('|', start); + if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + int height = 0; + try { + height = Integer.parseInt(string.substring(start, end)); + } catch (NumberFormatException e) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + start = end + 1; + end = string.indexOf('|', start); + if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + int style = 0; + try { + style = Integer.parseInt(string.substring(start, end)); + } catch (NumberFormatException e) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + + start = end + 1; + end = string.indexOf('|', start); + setName(name); + setHeight(height); + setStyle(style); + if (end == -1) return; + setLocale(string.substring(start, end)); +} + +/** + * Constructs a new font data given a font name, + * the height of the desired font in points, + * and a font style. + * + * @param name the name of the font (must not be null) + * @param height the font height in points + * @param style a bit or combination of NORMAL, BOLD, ITALIC + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - when the font name is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the height is negative
    • + *
    + */ +public FontData(String name, int height, int style) { + if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + setName(name); + setHeight(height); + setStyle(style); +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public boolean equals (Object object) { + if (object == this) return true; + if (!(object instanceof FontData)) return false; + FontData fd = (FontData)object; + return height == fd.height && + style == fd.style && + (name == null && fd.name == null || name != null && name.equals(fd.name)); +} + +/** + * Returns the height of the receiver in points. + * + * @return the height of this FontData + * + * @see #setHeight + */ +public int getHeight() { + return height; +} + +/** + * Returns the locale of the receiver. + *

    + * The locale determines which platform character set this + * font is going to use. Widgets and graphics operations that + * use this font will convert UNICODE strings to the platform + * character set of the specified locale. + *

    + *

    + * On platforms where there are multiple character sets for a + * given language/country locale, the variant portion of the + * locale will determine the character set. + *

    + * + * @return the String representing a Locale object + * @since 3.0 + */ +public String getLocale () { + StringBuffer buffer = new StringBuffer (); + char sep = '_'; + if (locale != null && !"".equals(locale.getLanguage())) { + buffer.append (locale.getLanguage()); + buffer.append (sep); + } + if (locale != null && !"".equals(locale.getCountry())) { + buffer.append (locale.getCountry()); + buffer.append (sep); + } + if (locale != null && !"".equals(locale.getVariant())) { + buffer.append (locale.getVariant()); + } + + String result = buffer.toString (); + int length = result.length (); + if (length > 0) { + if (result.charAt (length - 1) == sep) { + result = result.substring (0, length - 1); + } + } + return result; +} + +/** + * Returns the name of the receiver. + * On platforms that support font foundries, the return value will + * be the foundry followed by a dash ("-") followed by the face name. + * + * @return the name of this FontData + * + * @see #setName + */ +public String getName() { + return name; +} + +/** + * Returns the style of the receiver which is a bitwise OR of + * one or more of the SWT constants NORMAL, BOLD + * and ITALIC. + * + * @return the style of this FontData + * + * @see #setStyle + */ +public int getStyle() { + return style; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public int hashCode () { + return height ^ style ^ (locale == null? 0: locale.hashCode()) ^ getName().hashCode(); +} + +/** + * Sets the height of the receiver. The parameter is + * specified in terms of points, where a point is one + * seventy-second of an inch. + * + * @param height the height of the FontData + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the height is negative
    • + *
    + * + * @see #getHeight + */ +public void setHeight(int height) { + if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + this.height = height; +} + +/** + * Sets the locale of the receiver. + *

    + * The locale determines which platform character set this + * font is going to use. Widgets and graphics operations that + * use this font will convert UNICODE strings to the platform + * character set of the specified locale. + *

    + *

    + * On platforms where there are multiple character sets for a + * given language/country locale, the variant portion of the + * locale will determine the character set. + *

    + * + * @param locale the String representing a Locale object + * @see java.util.Locale#toString + */ +public void setLocale(String locale) { + if (locale != null) { + char sep = '_'; + int length = locale.length(); + int firstSep, secondSep; + + firstSep = locale.indexOf(sep); + if (firstSep == -1) { + firstSep = secondSep = length; + } else { + secondSep = locale.indexOf(sep, firstSep + 1); + if (secondSep == -1) secondSep = length; + } + String lang = ""; + String country = ""; + String variant = ""; + if (firstSep > 0) lang = locale.substring(0, firstSep); + if (secondSep > firstSep + 1) country = locale.substring(firstSep + 1, secondSep); + if (length > secondSep + 1) variant = locale.substring(secondSep + 1); + this.locale = new java.util.Locale(lang, country, variant); + } +} + +/** + * Sets the name of the receiver. + *

    + * Some platforms support font foundries. On these platforms, the name + * of the font specified in setName() may have one of the following forms: + *

      + *
    1. a face name (for example, "courier")
    2. + *
    3. a foundry followed by a dash ("-") followed by a face name (for example, "adobe-courier")
    4. + *
    + * In either case, the name returned from getName() will include the + * foundry. + *

    + *

    + * On platforms that do not support font foundries, only the face name + * (for example, "courier") is used in setName() and + * getName(). + *

    + * + * @param name the name of the font data (must not be null) + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - when the font name is null
    • + *
    + * + * @see #getName + */ +public void setName(String name) { + if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.name = name; +} + +/** + * Sets the style of the receiver to the argument which must + * be a bitwise OR of one or more of the SWT + * constants NORMAL, BOLD and ITALIC. All other style bits are + * ignored. + * + * @param style the new style for this FontData + * + * @see #getStyle + */ +public void setStyle(int style) { + this.style = style; +} + +/** + * Returns a string representation of the receiver which is suitable + * for constructing an equivalent instance using the + * FontData(String) constructor. + * + * @return a string representation of the FontData + * + * @see FontData + */ +public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("1|"); //$NON-NLS-1$ + buffer.append(getName()); + buffer.append("|"); //$NON-NLS-1$ + buffer.append(getHeight()); + buffer.append("|"); //$NON-NLS-1$ + buffer.append(getStyle()); + buffer.append("|"); //$NON-NLS-1$ + String locale = getLocale(); + if(locale != null) { + buffer.append(locale); + buffer.append("|"); //$NON-NLS-1$ + } + return buffer.toString(); +} + +///** +// * Invokes platform specific functionality to allocate a new font data. +// *

    +// * IMPORTANT: This method is not part of the public +// * API for FontData. It is marked public only so that +// * it can be shared within the packages provided by SWT. It is not +// * available on all platforms, and should never be called from +// * application code. +// *

    +// * +// * @param font the Font for the font data +// * @return a new font data object containing the specified LOGFONT and height +// */ +//public static FontData swing_new(FontData fontData) { +// return new FontData(fontData); +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java new file mode 100644 index 00000000000..11a9278634f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +/** + * Instances of this class provide measurement information + * about fonts including ascent, descent, height, leading + * space between rows, and average character width. + * FontMetrics are obtained from GCs + * using the getFontMetrics() method. + * + * @see GC#getFontMetrics + */ + +public final class FontMetrics { + + /** + * On Windows, handle is a Win32 TEXTMETRIC struct + * On Photon, handle is a Photon FontQueryInfo struct + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public java.awt.FontMetrics handle; + + int ascent; + int descent; + int height; + int leading; + int averageCharWidth; + +/** + * Prevents instances from being created outside the package. + */ +FontMetrics() { +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +@Override +public boolean equals (Object object) { + if (object == this) return true; + if (!(object instanceof FontMetrics)) return false; + return ((FontMetrics)object).handle.equals(handle); +// TEXTMETRIC metric = ((FontMetrics)object).handle; +// return handle.tmHeight == metric.tmHeight && +// handle.tmAscent == metric.tmAscent && +// handle.tmDescent == metric.tmDescent && +// handle.tmInternalLeading == metric.tmInternalLeading && +// handle.tmExternalLeading == metric.tmExternalLeading && +// handle.tmAveCharWidth == metric.tmAveCharWidth && +// handle.tmMaxCharWidth == metric.tmMaxCharWidth && +// handle.tmWeight == metric.tmWeight && +// handle.tmOverhang == metric.tmOverhang && +// handle.tmDigitizedAspectX == metric.tmDigitizedAspectX && +// handle.tmDigitizedAspectY == metric.tmDigitizedAspectY && +//// handle.tmFirstChar == metric.tmFirstChar && +//// handle.tmLastChar == metric.tmLastChar && +//// handle.tmDefaultChar == metric.tmDefaultChar && +//// handle.tmBreakChar == metric.tmBreakChar && +// handle.tmItalic == metric.tmItalic && +// handle.tmUnderlined == metric.tmUnderlined && +// handle.tmStruckOut == metric.tmStruckOut && +// handle.tmPitchAndFamily == metric.tmPitchAndFamily && +// handle.tmCharSet == metric.tmCharSet; +} + +/** + * Returns the ascent of the font described by the receiver. A + * font's ascent is the distance from the baseline to the + * top of actual characters, not including any of the leading area, + * measured in pixels. + * + * @return the ascent of the font + */ +public int getAscent() { + return handle == null? ascent: handle.getAscent(); +} + +/** + * Returns the average character width, measured in pixels, + * of the font described by the receiver. + * + * @return the average character width of the font + */ +public int getAverageCharWidth() { + // Use a letter that looks average + return handle == null? averageCharWidth: handle.charWidth('c'); +} + +/** + * Returns the descent of the font described by the receiver. A + * font's descent is the distance from the baseline to the + * bottom of actual characters, not including any of the leading area, + * measured in pixels. + * + * @return the descent of the font + */ +public int getDescent() { + return handle == null? descent: handle.getDescent(); +} + +/** + * Returns the height of the font described by the receiver, + * measured in pixels. A font's height is the sum of + * its ascent, descent and leading area. + * + * @return the height of the font + * + * @see #getAscent + * @see #getDescent + * @see #getLeading + */ +public int getHeight() { + return handle == null? height: handle.getHeight(); +} + +/** + * Returns the leading area of the font described by the + * receiver. A font's leading area is the space + * above its ascent which may include accents or other marks. + * + * @return the leading space of the font + */ +public int getLeading() { + return handle == null? leading: handle.getLeading(); +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +@Override +public int hashCode() { + return (handle == null? 0: handle.hashCode()) ^ getAscent() ^ getDescent() ^ getHeight() ^ getLeading() ^ getAverageCharWidth(); +} + +/** + * Invokes platform specific functionality to allocate a new font metrics. + *

    + * IMPORTANT: This method is not part of the public + * API for FontMetrics. It is marked public only so that + * it can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param handle the TEXTMETRIC containing information about a font + * @return a new font metrics object containing the specified TEXTMETRIC + */ +public static FontMetrics swing_new(java.awt.FontMetrics handle) { + FontMetrics fontMetrics = new FontMetrics(); + fontMetrics.handle = handle; + return fontMetrics; +} + +static FontMetrics internal_new(int ascent, int descent, int averageCharWidth, int leading, int height) { + FontMetrics fontMetrics = new FontMetrics(); + fontMetrics.ascent = ascent; + fontMetrics.descent = descent; + fontMetrics.height = height; + fontMetrics.leading = leading; + fontMetrics.averageCharWidth = averageCharWidth; + return fontMetrics; +} + +public int getAverageCharacterWidth() { + throw new UnsupportedOperationException("Not implemented yet"); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java new file mode 100644 index 00000000000..4071b4be731 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java @@ -0,0 +1,3880 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.AWTException; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Paint; +import java.awt.RenderingHints; +import java.awt.Robot; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.swing.CGC; +import org.eclipse.swt.internal.swing.LookAndFeelUtils; +import org.eclipse.swt.internal.swing.Utils; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; + +/** + * Class GC is where all of the drawing capabilities that are + * supported by SWT are located. Instances are used to draw on either an + * Image, a Control, or directly on a Display. + *
    + *
    Styles:
    + *
    LEFT_TO_RIGHT, RIGHT_TO_LEFT
    + *
    + * + *

    + * The SWT drawing coordinate system is the two-dimensional space with the origin + * (0,0) at the top left corner of the drawing area and with (x,y) values increasing + * to the right and downward respectively. + *

    + * + *

    + * Application code must explicitly invoke the GC.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. This is particularly + * important on Windows95 and Windows98 where the operating system has a limited + * number of device contexts available. + *

    + * + *

    + * Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified. + *

    + * + * @see org.eclipse.swt.events.PaintEvent + */ + +public final class GC extends Resource { + + /** + * the handle to the OS device context + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public CGC handle; + + Drawable drawable; + GCData data; + + // Saved Affine Transform + private AffineTransform saveAT, gcAT; + + // Fill Rule + private int fillRule = SWT.FILL_EVEN_ODD; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +GC() { +} + +/** + * Constructs a new instance of this class which has been + * configured to draw on the specified drawable. Sets the + * foreground and background color in the GC to match those + * in the drawable. + *

    + * You must dispose the graphics context when it is no longer required. + *

    + * @param drawable the drawable to draw on + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the drawable is null
    • + *
    • ERROR_NULL_ARGUMENT - if there is no current device
    • + *
    • ERROR_INVALID_ARGUMENT + * - if the drawable is an image that is not a bitmap or an icon + * - if the drawable is an image or printer that is already selected + * into another graphics context
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for GC creation
    • + *
    + */ +public GC(Drawable drawable) { + this(drawable, SWT.NONE); +} + +/** + * Constructs a new instance of this class which has been + * configured to draw on the specified drawable. Sets the + * foreground and background color in the GC to match those + * in the drawable. + *

    + * You must dispose the graphics context when it is no longer required. + *

    + * + * @param drawable the drawable to draw on + * @param style the style of GC to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the drawable is null
    • + *
    • ERROR_NULL_ARGUMENT - if there is no current device
    • + *
    • ERROR_INVALID_ARGUMENT + * - if the drawable is an image that is not a bitmap or an icon + * - if the drawable is an image or printer that is already selected + * into another graphics context
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for GC creation
    • + *
    + * + * @since 2.1.2 + */ +public GC(Drawable drawable, int style) { + if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + GCData data = new GCData (); + data.style = checkStyle(style); + Device device = data.device; + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = data.device = device; + CGC handle = drawable.internal_new_GC(data); + if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES); + data.background = java.awt.Color.WHITE; + init (drawable, data, handle); + if (device.tracking) device.new_Object(this); +} + +static int checkStyle(int style) { + if ((style & SWT.LEFT_TO_RIGHT) != 0) style &= ~SWT.RIGHT_TO_LEFT; + return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); +} + +/** + * Copies a rectangular area of the receiver at the specified + * position into the image, which must be of type SWT.BITMAP. + * + * @param image the image to copy into + * @param x the x coordinate in the receiver of the area to be copied + * @param y the y coordinate in the receiver of the area to be copied + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the image is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void copyArea(Image image, int x, int y) { + if (drawable instanceof Control) { + Control control = (Control) drawable; + Graphics graphics = image.handle.getGraphics(); + graphics.translate(-x, -y); + control.handle.paint(graphics); + graphics.translate(x, y); + return; + } + if (drawable instanceof Display) { + // TODO: better way? + Rectangle r = image.getBounds(); + try { + image.handle = new Robot().createScreenCapture(new java.awt.Rectangle(r.x, r.y, r.width, r.height)); + } catch (AWTException e) { + e.printStackTrace(); + } + return; + } + // TODO: what about other cases? + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + + // TODO: check that it works + java.awt.Composite oldComposite = handle.getComposite(); + java.awt.Composite newComposite = new java.awt.Composite() { + public java.awt.CompositeContext createContext(java.awt.image.ColorModel srcColorModel, java.awt.image.ColorModel dstColorModel, java.awt.RenderingHints hints) { + return new java.awt.CompositeContext() { + public void compose(java.awt.image.Raster src, java.awt.image.Raster dstIn, java.awt.image.WritableRaster dstOut) { + // TODO: do the composition + } + public void dispose() { + } + }; + } + }; + handle.setComposite(newComposite); + // TODO: find how to flush + handle.setComposite(oldComposite); +// +// +// /* Get the HDC for the device */ +// Device device = data.device; +// int hDC = device.internal_new_GC(null); +// +// /* Copy the bitmap area */ +// Rectangle rect = image.getBounds(); +// int memHdc = OS.CreateCompatibleDC(hDC); +// int hOldBitmap = OS.SelectObject(memHdc, image.handle); +// OS.BitBlt(memHdc, 0, 0, rect.width, rect.height, handle, x, y, OS.SRCCOPY); +// OS.SelectObject(memHdc, hOldBitmap); +// OS.DeleteDC(memHdc); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +} + +/** + * Copies a rectangular area of the receiver at the source + * position onto the receiver at the destination position. + * + * @param srcX the x coordinate in the receiver of the area to be copied + * @param srcY the y coordinate in the receiver of the area to be copied + * @param width the width of the area to copy + * @param height the height of the area to copy + * @param destX the x coordinate in the receiver of the area to copy to + * @param destY the y coordinate in the receiver of the area to copy to + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) { + copyArea(srcX, srcY, width, height, destX, destY, true); +} + +/** + * Copies a rectangular area of the receiver at the source + * position onto the receiver at the destination position. + * + * @param srcX the x coordinate in the receiver of the area to be copied + * @param srcY the y coordinate in the receiver of the area to be copied + * @param width the width of the area to copy + * @param height the height of the area to copy + * @param destX the x coordinate in the receiver of the area to copy to + * @param destY the y coordinate in the receiver of the area to copy to + * @param paint if true paint events will be generated for old and obscured areas + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) { + // TODO: check what to do with the paint argument + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.copyArea(srcX, srcY, width, height, destX - srcX, destY - srcY); +// ensureAreaClean(destX, destY, width, height); +} + +//int createDIB(int width, int height) { +// short depth = 32; +// +// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = width; +// bmiHeader.biHeight = -height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = depth; +// if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS; +// else bmiHeader.biCompression = OS.BI_RGB; +// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// /* Set the rgb colors into the bitmap info */ +// if (OS.IsWinCE) { +// int redMask = 0xFF00; +// int greenMask = 0xFF0000; +// int blueMask = 0xFF000000; +// /* big endian */ +// int offset = BITMAPINFOHEADER.sizeof; +// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24); +// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16); +// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8); +// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0); +// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24); +// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16); +// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8); +// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0); +// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24); +// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16); +// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8); +// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0); +// } +// +// int[] pBits = new int[1]; +// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0); +// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// return hDib; +//} +// +//int createGdipBrush() { +// int colorRef = OS.GetBkColor (handle); +// int rgb = ((colorRef >> 16) & 0xFF) | (colorRef & 0xFF00) | ((colorRef & 0xFF) << 16); +// int color = Gdip.Color_new(data.alpha << 24 | rgb); +// if (color == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// int brush = Gdip.SolidBrush_new(color); +// if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// Gdip.Color_delete(color); +// return brush; +//} +// +//int createGdipPen() { +// int style, colorRef, width, size, hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN); +// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) { +// LOGPEN logPen = new LOGPEN(); +// OS.GetObject(hPen, LOGPEN.sizeof, logPen); +// colorRef = logPen.lopnColor; +// width = logPen.x; +// style = logPen.lopnStyle; +// } else { +// EXTLOGPEN logPen = new EXTLOGPEN(); +// if (size <= EXTLOGPEN.sizeof) { +// OS.GetObject(hPen, size, logPen); +// } else { +// int hHeap = OS.GetProcessHeap(); +// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size); +// OS.GetObject(hPen, size, ptr); +// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof); +// OS.HeapFree(hHeap, 0, ptr); +// } +// colorRef = logPen.elpColor; +// width = logPen.elpWidth; +// style = logPen.elpPenStyle; +// } +// int rgb = ((colorRef >> 16) & 0xFF) | (colorRef & 0xFF00) | ((colorRef & 0xFF) << 16); +// int color = Gdip.Color_new(data.alpha << 24 | rgb); +// int pen = Gdip.Pen_new(color, width); +// Gdip.Color_delete(color); +// int dashStyle = 0; +// switch (style & OS.PS_STYLE_MASK) { +// case OS.PS_SOLID: dashStyle = Gdip.DashStyleSolid; break; +// case OS.PS_DOT: dashStyle = Gdip.DashStyleDot; break; +// case OS.PS_DASH: dashStyle = Gdip.DashStyleDash; break; +// case OS.PS_DASHDOT: dashStyle = Gdip.DashStyleDashDot; break; +// case OS.PS_DASHDOTDOT: dashStyle = Gdip.DashStyleDashDotDot; break; +// case OS.PS_USERSTYLE: { +// if (data.dashes != null) { +// float[] pattern = new float[data.dashes.length]; +// for (int i = 0; i < pattern.length; i++) { +// pattern[i] = (float)data.dashes[i] / width; +// } +// Gdip.Pen_SetDashPattern(pen, pattern, pattern.length); +// dashStyle = Gdip.DashStyleCustom; +// } else { +// dashStyle = Gdip.DashStyleSolid; +// } +// } +// } +// if (dashStyle != Gdip.DashStyleCustom) Gdip.Pen_SetDashStyle(pen, dashStyle); +// int joinStyle = 0; +// switch (style & OS.PS_JOIN_MASK) { +// case OS.PS_JOIN_MITER: joinStyle = Gdip.LineJoinMiter; break; +// case OS.PS_JOIN_BEVEL: joinStyle = Gdip.LineJoinBevel; break; +// case OS.PS_JOIN_ROUND: joinStyle = Gdip.LineJoinRound; break; +// } +// Gdip.Pen_SetLineJoin(pen, joinStyle); +// int dashCap = Gdip.DashCapFlat, capStyle = 0; +// switch (style & OS.PS_ENDCAP_MASK) { +// case OS.PS_ENDCAP_FLAT: capStyle = Gdip.LineCapFlat; break; +// case OS.PS_ENDCAP_ROUND: capStyle = Gdip.LineCapRound; dashCap = Gdip.DashCapRound; break; +// case OS.PS_ENDCAP_SQUARE: capStyle = Gdip.LineCapSquare; break; +// } +// Gdip.Pen_SetLineCap(pen, capStyle, capStyle, dashCap); +// return pen; +//} + +/** + * Disposes of the operating system resources associated with + * the graphics context. Applications must dispose of all GCs + * which they allocate. + */ +public void dispose() { + if (this.handle == null) return; +// if (data.device.isDisposed()) return; + +// if (data.gdipGraphics != 0) Gdip.Graphics_delete(data.gdipGraphics); +// if (data.gdipPen != 0) Gdip.Pen_delete(data.gdipPen); +// if (data.gdipBrush != 0) Gdip.SolidBrush_delete(data.gdipBrush); +// data.gdipBrush = data.gdipPen = data.gdipGraphics = 0; +// +// /* Select stock pen and brush objects and free resources */ +// if (data.hPen != 0) { +// int nullPen = OS.GetStockObject(OS.NULL_PEN); +// OS.SelectObject(handle, nullPen); +// OS.DeleteObject(data.hPen); +// data.hPen = 0; +// } +// if (data.hBrush != 0) { +// int nullBrush = OS.GetStockObject(OS.NULL_BRUSH); +// OS.SelectObject(handle, nullBrush); +// OS.DeleteObject(data.hBrush); +// data.hBrush = 0; +// } + +// /* +// * Put back the original bitmap into the device context. +// * This will ensure that we have not left a bitmap +// * selected in it when we delete the HDC. +// */ +// int hNullBitmap = data.hNullBitmap; +// if (hNullBitmap != 0) { +// OS.SelectObject(handle, hNullBitmap); +// data.hNullBitmap = 0; +// } +// Image image = data.image; +// if (image != null) image.memGC = null; +// +// /* +// * Dispose the HDC. +// */ + handle.dispose(); + Device device = data.device; + if (drawable != null) drawable.internal_dispose_GC(handle, data); + drawable = null; + handle = null; +// data.image = null; +// data.ps = null; + if (device.tracking) device.dispose_Object(this); +// data.device = null; + data = null; +} + +/** + * Draws the outline of a circular or elliptical arc + * within the specified rectangular area. + *

    + * The resulting arc begins at startAngle and extends + * for arcAngle degrees, using the current color. + * Angles are interpreted such that 0 degrees is at the 3 o'clock + * position. A positive value indicates a counter-clockwise rotation + * while a negative value indicates a clockwise rotation. + *

    + * The center of the arc is the center of the rectangle whose origin + * is (x, y) and whose size is specified by the + * width and height arguments. + *

    + * The resulting arc covers an area width + 1 pixels wide + * by height + 1 pixels tall. + *

    + * + * @param x the x coordinate of the upper-left corner of the arc to be drawn + * @param y the y coordinate of the upper-left corner of the arc to be drawn + * @param width the width of the arc to be drawn + * @param height the height of the arc to be drawn + * @param startAngle the beginning angle + * @param arcAngle the angular extent of the arc, relative to the start angle + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + if (width == 0 || height == 0 || arcAngle == 0) return; + handle.drawArc(x, y, width, height, startAngle, arcAngle); +// ensureAreaClean(x, y, width, height); +} + +/** + * Draws a rectangle, based on the specified arguments, which has + * the appearance of the platform's focus rectangle if the + * platform supports such a notion, and otherwise draws a simple + * rectangle in the receiver's foreground color. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param width the width of the rectangle + * @param height the height of the rectangle + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawRectangle(int, int, int, int) + */ +public void drawFocus (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Color oldColor = handle.getColor(); + handle.setColor(LookAndFeelUtils.getFocusColor()); + handle.drawRect(x, y, width, height); + handle.setColor(oldColor); +// ensureAreaClean(x, y, width, height); +} + +/** + * Draws the given image in the receiver at the specified + * coordinates. + * + * @param image the image to draw + * @param x the x coordinate of where to draw + * @param y the y coordinate of where to draw + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the image is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    • ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image
    • + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * @exception SWTError
        + *
      • ERROR_NO_HANDLES - if no handles are available to perform the operation
      • + *
      + */ +public void drawImage(Image image, int x, int y) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true); +} + +/** + * Copies a rectangular area from the source image into a (potentially + * different sized) rectangular area in the receiver. If the source + * and destination areas are of differing sizes, then the source + * area will be stretched or shrunk to fit the destination area + * as it is copied. The copy fails if any part of the source rectangle + * lies outside the bounds of the source image, or if any of the width + * or height arguments are negative. + * + * @param image the source image + * @param srcX the x coordinate in the source image to copy from + * @param srcY the y coordinate in the source image to copy from + * @param srcWidth the width in pixels to copy from the source + * @param srcHeight the height in pixels to copy from the source + * @param destX the x coordinate in the destination to copy to + * @param destY the y coordinate in the destination to copy to + * @param destWidth the width in pixels of the destination rectangle + * @param destHeight the height in pixels of the destination rectangle + * + * @exception IllegalArgumentException
        + *
      • ERROR_NULL_ARGUMENT - if the image is null
      • + *
      • ERROR_INVALID_ARGUMENT - if the image has been disposed
      • + *
      • ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative. + *
      • ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * @exception SWTError
        + *
      • ERROR_NO_HANDLES - if no handles are available to perform the operation
      • + *
      + */ +public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return; + if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false); +} + +void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { + if(srcWidth == -1) { + srcWidth = srcImage.handle.getWidth(); + } + if(srcHeight == -1) { + srcHeight = srcImage.handle.getHeight(); + } + if(destWidth == -1) { + destWidth = srcWidth; + } + if(destHeight == -1) { + destHeight = srcHeight; + } + // Simple == no stretch + if(!simple || srcWidth == destWidth && srcHeight == destHeight) { + handle.drawImage(srcImage.handle, destX, destY, destX + destWidth, destY + destHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, null); + } else { +// Shape oldClip = handle.getClip(); +// handle.setClip(systemClip); +// handle.clipRect(destX, destY, destWidth, destHeight); + handle.drawImage(srcImage.handle, destX, destY, destX + destWidth, destY + destHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, null); +// handle.setClip(oldClip); + } +// ensureAreaClean(destX, destY, destWidth, destHeight); +// switch (srcImage.type) { +// case SWT.BITMAP: +// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); +// break; +// case SWT.ICON: +// drawIcon(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); +// break; +// default: +// SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT); +// } +} +// +//void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +// int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY); +// +// /* Simple case: no stretching, entire icon */ +// if (simple && technology != OS.DT_RASPRINTER) { +// OS.DrawIconEx(handle, destX, destY, srcImage.handle, 0, 0, 0, 0, OS.DI_NORMAL); +// return; +// } +// +// /* Get the icon info */ +// ICONINFO srcIconInfo = new ICONINFO(); +// if (OS.IsWinCE) { +// Image.GetIconInfo(srcImage, srcIconInfo); +// } else { +// OS.GetIconInfo(srcImage.handle, srcIconInfo); +// } +// +// /* Get the icon width and height */ +// int hBitmap = srcIconInfo.hbmColor; +// if (hBitmap == 0) hBitmap = srcIconInfo.hbmMask; +// BITMAP bm = new BITMAP(); +// OS.GetObject(hBitmap, BITMAP.sizeof, bm); +// int iconWidth = bm.bmWidth, iconHeight = bm.bmHeight; +// if (hBitmap == srcIconInfo.hbmMask) iconHeight /= 2; +// +// if (simple) { +// srcWidth = destWidth = iconWidth; +// srcHeight = destHeight = iconHeight; +// } +// +// /* Draw the icon */ +// boolean failed = srcX + srcWidth > iconWidth || srcY + srcHeight > iconHeight; +// if (!failed) { +// simple = srcX == 0 && srcY == 0 && +// srcWidth == destWidth && srcHeight == destHeight && +// srcWidth == iconWidth && srcHeight == iconHeight; +// if (simple && technology != OS.DT_RASPRINTER) { +// /* Simple case: no stretching, entire icon */ +// OS.DrawIconEx(handle, destX, destY, srcImage.handle, 0, 0, 0, 0, OS.DI_NORMAL); +// } else { +// /* Get the HDC for the device */ +// Device device = data.device; +// int hDC = device.internal_new_GC(null); +// +// /* Create the icon info and HDC's */ +// ICONINFO newIconInfo = new ICONINFO(); +// newIconInfo.fIcon = true; +// int srcHdc = OS.CreateCompatibleDC(hDC); +// int dstHdc = OS.CreateCompatibleDC(hDC); +// +// /* Blt the color bitmap */ +// int srcColorY = srcY; +// int srcColor = srcIconInfo.hbmColor; +// if (srcColor == 0) { +// srcColor = srcIconInfo.hbmMask; +// srcColorY += iconHeight; +// } +// int oldSrcBitmap = OS.SelectObject(srcHdc, srcColor); +// newIconInfo.hbmColor = OS.CreateCompatibleBitmap(srcHdc, destWidth, destHeight); +// if (newIconInfo.hbmColor == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// int oldDestBitmap = OS.SelectObject(dstHdc, newIconInfo.hbmColor); +// boolean stretch = !simple && (srcWidth != destWidth || srcHeight != destHeight); +// if (stretch) { +// if (!OS.IsWinCE) OS.SetStretchBltMode(dstHdc, OS.COLORONCOLOR); +// OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, srcWidth, srcHeight, OS.SRCCOPY); +// } else { +// OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, OS.SRCCOPY); +// } +// +// /* Blt the mask bitmap */ +// OS.SelectObject(srcHdc, srcIconInfo.hbmMask); +// newIconInfo.hbmMask = OS.CreateBitmap(destWidth, destHeight, 1, 1, null); +// if (newIconInfo.hbmMask == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// OS.SelectObject(dstHdc, newIconInfo.hbmMask); +// if (stretch) { +// OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCCOPY); +// } else { +// OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCCOPY); +// } +// +// if (technology == OS.DT_RASPRINTER) { +// OS.SelectObject(srcHdc, newIconInfo.hbmColor); +// OS.SelectObject(dstHdc, srcIconInfo.hbmMask); +// drawBitmapTransparentByClipping(srcHdc, dstHdc, 0, 0, destWidth, destHeight, destX, destY, destWidth, destHeight, true, destWidth, destHeight); +// OS.SelectObject(srcHdc, oldSrcBitmap); +// OS.SelectObject(dstHdc, oldDestBitmap); +// } else { +// OS.SelectObject(srcHdc, oldSrcBitmap); +// OS.SelectObject(dstHdc, oldDestBitmap); +// int hIcon = OS.CreateIconIndirect(newIconInfo); +// if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// OS.DrawIconEx(handle, destX, destY, hIcon, destWidth, destHeight, 0, 0, OS.DI_NORMAL); +// OS.DestroyIcon(hIcon); +// } +// +// /* Destroy the new icon src and mask and hdc's*/ +// OS.DeleteObject(newIconInfo.hbmMask); +// OS.DeleteObject(newIconInfo.hbmColor); +// OS.DeleteDC(dstHdc); +// OS.DeleteDC(srcHdc); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +// } +// } +// +// /* Free icon info */ +// OS.DeleteObject(srcIconInfo.hbmMask); +// if (srcIconInfo.hbmColor != 0) { +// OS.DeleteObject(srcIconInfo.hbmColor); +// } +// +// if (failed) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +//} +// +//void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +// BITMAP bm = new BITMAP(); +// OS.GetObject(srcImage.handle, BITMAP.sizeof, bm); +// int imgWidth = bm.bmWidth; +// int imgHeight = bm.bmHeight; +// if (simple) { +// srcWidth = destWidth = imgWidth; +// srcHeight = destHeight = imgHeight; +// } else { +// if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) { +// SWT.error (SWT.ERROR_INVALID_ARGUMENT); +// } +// simple = srcX == 0 && srcY == 0 && +// srcWidth == destWidth && destWidth == imgWidth && +// srcHeight == destHeight && destHeight == imgHeight; +// } +// boolean mustRestore = false; +// GC memGC = srcImage.memGC; +// if (memGC != null && !memGC.isDisposed()) { +// mustRestore = true; +// GCData data = memGC.data; +// if (data.hNullBitmap != 0) { +// OS.SelectObject(memGC.handle, data.hNullBitmap); +// data.hNullBitmap = 0; +// } +// } +// if (srcImage.alpha != -1 || srcImage.alphaData != null) { +// drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); +// } else if (srcImage.transparentPixel != -1) { +// drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); +// } else { +// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); +// } +// if (mustRestore) { +// int hOldBitmap = OS.SelectObject(memGC.handle, srcImage.handle); +// memGC.data.hNullBitmap = hOldBitmap; +// } +//} +// +//void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { +// /* Simple cases */ +// if (srcImage.alpha == 0) return; +// if (srcImage.alpha == 255) { +// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); +// return; +// } +// +// /* Check clipping */ +// Rectangle rect = getClipping(); +// rect = rect.intersection(new Rectangle(destX, destY, destWidth, destHeight)); +// if (rect.isEmpty()) return; +// +// /* +// * Optimization. Recalculate src and dest rectangles so that +// * only the clipping area is drawn. +// */ +// int sx1 = srcX + (((rect.x - destX) * srcWidth) / destWidth); +// int sx2 = srcX + ((((rect.x + rect.width) - destX) * srcWidth) / destWidth); +// int sy1 = srcY + (((rect.y - destY) * srcHeight) / destHeight); +// int sy2 = srcY + ((((rect.y + rect.height) - destY) * srcHeight) / destHeight); +// destX = rect.x; +// destY = rect.y; +// destWidth = rect.width; +// destHeight = rect.height; +// srcX = sx1; +// srcY = sy1; +// srcWidth = Math.max(1, sx2 - sx1); +// srcHeight = Math.max(1, sy2 - sy1); +// +// /* Create resources */ +// int srcHdc = OS.CreateCompatibleDC(handle); +// int oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); +// int memHdc = OS.CreateCompatibleDC(handle); +// int memDib = createDIB(Math.max(srcWidth, destWidth), Math.max(srcHeight, destHeight)); +// int oldMemBitmap = OS.SelectObject(memHdc, memDib); +// +// BITMAP dibBM = new BITMAP(); +// OS.GetObject(memDib, BITMAP.sizeof, dibBM); +// int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight; +// +// /* Get the background pixels */ +// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY); +// byte[] destData = new byte[sizeInBytes]; +// OS.MoveMemory(destData, dibBM.bmBits, sizeInBytes); +// +// /* Get the foreground pixels */ +// OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY); +// byte[] srcData = new byte[sizeInBytes]; +// OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes); +// +// /* Merge the alpha channel in place */ +// int alpha = srcImage.alpha; +// final boolean hasAlphaChannel = (srcImage.alpha == -1); +// if (hasAlphaChannel) { +// final int apinc = imgWidth - srcWidth; +// final int spinc = dibBM.bmWidthBytes - srcWidth * 4; +// int ap = srcY * imgWidth + srcX, sp = 3; +// byte[] alphaData = srcImage.alphaData; +// for (int y = 0; y < srcHeight; ++y) { +// for (int x = 0; x < srcWidth; ++x) { +// srcData[sp] = alphaData[ap++]; +// sp += 4; +// } +// ap += apinc; +// sp += spinc; +// } +// } +// +// /* Scale the foreground pixels with alpha */ +// OS.MoveMemory(dibBM.bmBits, srcData, sizeInBytes); +// /* +// * Bug in WinCE and Win98. StretchBlt does not correctly stretch when +// * the source and destination HDCs are the same. The workaround is to +// * stretch to a temporary HDC and blit back into the original HDC. +// * Note that on WinCE StretchBlt correctly compresses the image when the +// * source and destination HDCs are the same. +// */ +// if ((OS.IsWinCE && (destWidth > srcWidth || destHeight > srcHeight)) || (!OS.IsWinNT && !OS.IsWinCE)) { +// int tempHdc = OS.CreateCompatibleDC(handle); +// int tempDib = createDIB(destWidth, destHeight); +// int oldTempBitmap = OS.SelectObject(tempHdc, tempDib); +// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) { +// if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR); +// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY); +// } else { +// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY); +// } +// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY); +// OS.SelectObject(tempHdc, oldTempBitmap); +// OS.DeleteObject(tempDib); +// OS.DeleteDC(tempHdc); +// } else { +// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) { +// if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR); +// OS.StretchBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY); +// } else { +// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY); +// } +// } +// OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes); +// +// /* Compose the pixels */ +// final int dpinc = dibBM.bmWidthBytes - destWidth * 4; +// int dp = 0; +// for (int y = 0; y < destHeight; ++y) { +// for (int x = 0; x < destWidth; ++x) { +// if (hasAlphaChannel) alpha = srcData[dp + 3] & 0xff; +// destData[dp] += ((srcData[dp] & 0xff) - (destData[dp] & 0xff)) * alpha / 255; +// destData[dp + 1] += ((srcData[dp + 1] & 0xff) - (destData[dp + 1] & 0xff)) * alpha / 255; +// destData[dp + 2] += ((srcData[dp + 2] & 0xff) - (destData[dp + 2] & 0xff)) * alpha / 255; +// dp += 4; +// } +// dp += dpinc; +// } +// +// /* Draw the composed pixels */ +// OS.MoveMemory(dibBM.bmBits, destData, sizeInBytes); +// OS.BitBlt(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY); +// +// /* Free resources */ +// OS.SelectObject(memHdc, oldMemBitmap); +// OS.DeleteDC(memHdc); +// OS.DeleteObject(memDib); +// OS.SelectObject(srcHdc, oldSrcBitmap); +// OS.DeleteDC(srcHdc); +//} +// +//void drawBitmapTransparentByClipping(int srcHdc, int maskHdc, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight) { +// int rgn = OS.CreateRectRgn(0, 0, 0, 0); +// for (int y=0; y> 16; +// transGreen = (color & 0xFF00) >> 8; +// transRed = color & 0xFF; +// } else { +// int maxColors = 1 << bm.bmBitsPixel; +// byte[] oldColors = new byte[maxColors * 4]; +// OS.GetDIBColorTable(srcHdc, 0, maxColors, oldColors); +// int offset = srcImage.transparentPixel * 4; +// byte[] newColors = new byte[oldColors.length]; +// transRed = transGreen = transBlue = 0xff; +// newColors[offset] = (byte)transBlue; +// newColors[offset+1] = (byte)transGreen; +// newColors[offset+2] = (byte)transRed; +// OS.SetDIBColorTable(srcHdc, 0, maxColors, newColors); +// originalColors = oldColors; +// } +// } else { +// /* Palette-based bitmap */ +// int numColors = 1 << bm.bmBitsPixel; +// /* Set the few fields necessary to get the RGB data out */ +// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biPlanes = bm.bmPlanes; +// bmiHeader.biBitCount = bm.bmBitsPixel; +// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(srcHdc, srcImage.handle, 0, 0, 0, bmi, OS.DIB_RGB_COLORS); +// int offset = BITMAPINFOHEADER.sizeof + 4 * srcImage.transparentPixel; +// transRed = bmi[offset + 2] & 0xFF; +// transGreen = bmi[offset + 1] & 0xFF; +// transBlue = bmi[offset] & 0xFF; +// } +// } else { +// /* Direct color image */ +// int pixel = srcImage.transparentPixel; +// switch (bm.bmBitsPixel) { +// case 16: +// transBlue = (pixel & 0x1F) << 3; +// transGreen = (pixel & 0x3E0) >> 2; +// transRed = (pixel & 0x7C00) >> 7; +// break; +// case 24: +// transBlue = (pixel & 0xFF0000) >> 16; +// transGreen = (pixel & 0xFF00) >> 8; +// transRed = pixel & 0xFF; +// break; +// case 32: +// transBlue = (pixel & 0xFF000000) >>> 24; +// transGreen = (pixel & 0xFF0000) >> 16; +// transRed = (pixel & 0xFF00) >> 8; +// break; +// } +// } +// +// if (OS.IsWinCE) { +// /* +// * Note in WinCE. TransparentImage uses the first entry of a palette +// * based image when there are multiple entries that have the same +// * transparent color. +// */ +// int transparentColor = transBlue << 16 | transGreen << 8 | transRed; +// OS.TransparentImage(handle, destX, destY, destWidth, destHeight, +// srcHdc, srcX, srcY, srcWidth, srcHeight, transparentColor); +// } else { +// /* Create the mask for the source image */ +// int maskHdc = OS.CreateCompatibleDC(hDC); +// int maskBitmap = OS.CreateBitmap(imgWidth, imgHeight, 1, 1, null); +// int oldMaskBitmap = OS.SelectObject(maskHdc, maskBitmap); +// OS.SetBkColor(srcHdc, (transBlue << 16) | (transGreen << 8) | transRed); +// OS.BitBlt(maskHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY); +// if (originalColors != null) OS.SetDIBColorTable(srcHdc, 0, 1 << bm.bmBitsPixel, originalColors); +// +// if (OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER) { +// /* Most printers do not support BitBlt(), draw the source bitmap transparently using clipping */ +// drawBitmapTransparentByClipping(srcHdc, maskHdc, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight); +// } else { +// /* Draw the source bitmap transparently using invert/and mask/invert */ +// int tempHdc = OS.CreateCompatibleDC(hDC); +// int tempBitmap = OS.CreateCompatibleBitmap(hDC, destWidth, destHeight); +// int oldTempBitmap = OS.SelectObject(tempHdc, tempBitmap); +// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY); +// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) { +// if (!OS.IsWinCE) OS.SetStretchBltMode(tempHdc, OS.COLORONCOLOR); +// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT); +// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCAND); +// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT); +// } else { +// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT); +// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, OS.SRCAND); +// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT); +// } +// OS.BitBlt(handle, destX, destY, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY); +// OS.SelectObject(tempHdc, oldTempBitmap); +// OS.DeleteDC(tempHdc); +// OS.DeleteObject(tempBitmap); +// } +// OS.SelectObject(maskHdc, oldMaskBitmap); +// OS.DeleteDC(maskHdc); +// OS.DeleteObject(maskBitmap); +// } +// OS.SelectObject(srcHdc, oldSrcBitmap); +// if (hBitmap != srcImage.handle) OS.DeleteObject(hBitmap); +// OS.DeleteDC(srcHdc); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +//} +// +//void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { +// if (data.gdipGraphics != 0) { +// //TODO - cache bitmap +// int img = Gdip.Bitmap_new(srcImage.handle, 0); +// Rect rect = new Rect(); +// rect.X = destX; +// rect.Y = destY; +// rect.Width = destWidth; +// rect.Height = destHeight; +// Gdip.Graphics_DrawImage(data.gdipGraphics, img, rect, srcX, srcY, srcWidth, srcHeight, Gdip.UnitPixel, 0, 0, 0); +// Gdip.Bitmap_delete(img); +// return; +// } +// int srcHdc = OS.CreateCompatibleDC(handle); +// int oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); +// int rop2 = 0; +// if (!OS.IsWinCE) { +// rop2 = OS.GetROP2(handle); +// } else { +// rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN); +// OS.SetROP2 (handle, rop2); +// } +// int dwRop = rop2 == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY; +// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) { +// int mode = 0; +// if (!OS.IsWinCE) mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR); +// OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop); +// if (!OS.IsWinCE) OS.SetStretchBltMode(handle, mode); +// } else { +// OS.BitBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, dwRop); +// } +// OS.SelectObject(srcHdc, oldSrcBitmap); +// OS.DeleteDC(srcHdc); +//} + +/** + * Draws a line, using the foreground color, between the points + * (x1, y1) and (x2, y2). + * + * @param x1 the first point's x coordinate + * @param y1 the first point's y coordinate + * @param x2 the second point's x coordinate + * @param y2 the second point's y coordinate + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public void drawLine (int x1, int y1, int x2, int y2) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.drawLine(x1, y1, x2, y2); +// Point p1 = new Point(Math.min(x1, x2), Math.min(y1, y2)); +// Point p2 = new Point(Math.max(x1, x2), Math.max(y1, y2)); +// ensureAreaClean(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y); +} + +/** + * Draws the outline of an oval, using the foreground color, + * within the specified rectangular area. + *

      + * The result is a circle or ellipse that fits within the + * rectangle specified by the x, y, + * width, and height arguments. + *

      + * The oval covers an area that is width + 1 + * pixels wide and height + 1 pixels tall. + *

      + * + * @param x the x coordinate of the upper left corner of the oval to be drawn + * @param y the y coordinate of the upper left corner of the oval to be drawn + * @param width the width of the oval to be drawn + * @param height the height of the oval to be drawn + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public void drawOval (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.drawOval(x, y, width, height); +// ensureAreaClean(x, y, width, height); +} + +/** + * Draws the path described by the parameter. + * + * @param path the path to draw + * + * @exception IllegalArgumentException
        + *
      • ERROR_NULL_ARGUMENT - if the parameter is null
      • + *
      • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see Path + * + * @since 3.1 + */ +public void drawPath (Path path) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (path.handle == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.draw(path.handle); +// java.awt.Rectangle bounds = path.handle.getBounds(); +// ensureAreaClean(bounds.x, bounds.y, bounds.width, bounds.height); +} + +/** + * Draws a pixel, using the foreground color, at the specified + * point (x, y). + *

      + * Note that the receiver's line attributes do not affect this + * operation. + *

      + * + * @param x the point's x coordinate + * @param y the point's y coordinate + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @since 3.0 + */ +public void drawPoint (int x, int y) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.drawLine(x, y, x, y); +// ensureAreaClean(x, y, 1, 1); +} + +/** + * Draws the closed polygon which is defined by the specified array + * of integer coordinates, using the receiver's foreground color. The array + * contains alternating x and y values which are considered to represent + * points which are the vertices of the polygon. Lines are drawn between + * each consecutive pair, and between the first pair and last pair in the + * array. + * + * @param pointArray an array of alternating x and y values which are the vertices of the polygon + * + * @exception IllegalArgumentException
        + *
      • ERROR_NULL_ARGUMENT if pointArray is null
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public void drawPolygon(int[] pointArray) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// int maxX = Integer.MIN_VALUE; +// int maxY = Integer.MIN_VALUE; +// int minX = Integer.MAX_VALUE; +// int minY = Integer.MAX_VALUE; + int[] xPoints = new int[pointArray.length/2]; + int[] yPoints = new int[xPoints.length]; + for(int i=0; i + *
    • ERROR_NULL_ARGUMENT - if the point array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawPolyline(int[] pointArray) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// int maxX = Integer.MIN_VALUE; +// int maxY = Integer.MIN_VALUE; +// int minX = Integer.MAX_VALUE; +// int minY = Integer.MAX_VALUE; + int[] xPoints = new int[pointArray.length/2]; + int[] yPoints = new int[xPoints.length]; + for(int i=0; ix and x + width. + * The top and bottom edges are at y and y + height. + * + * @param x the x coordinate of the rectangle to be drawn + * @param y the y coordinate of the rectangle to be drawn + * @param width the width of the rectangle to be drawn + * @param height the height of the rectangle to be drawn + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawRectangle (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.drawRect(x, y, width, height); +// ensureAreaClean(x, y, width, height); +} + +/** + * Draws the outline of the specified rectangle, using the receiver's + * foreground color. The left and right edges of the rectangle are at + * rect.x and rect.x + rect.width. The top + * and bottom edges are at rect.y and + * rect.y + rect.height. + * + * @param rect the rectangle to draw + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the rectangle is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawRectangle (Rectangle rect) { + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + drawRectangle (rect.x, rect.y, rect.width, rect.height); +} + +/** + * Draws the outline of the round-cornered rectangle specified by + * the arguments, using the receiver's foreground color. The left and + * right edges of the rectangle are at x and x + width. + * The top and bottom edges are at y and y + height. + * The roundness of the corners is specified by the + * arcWidth and arcHeight arguments, which + * are respectively the width and height of the ellipse used to draw + * the corners. + * + * @param x the x coordinate of the rectangle to be drawn + * @param y the y coordinate of the rectangle to be drawn + * @param width the width of the rectangle to be drawn + * @param height the height of the rectangle to be drawn + * @param arcWidth the width of the arc + * @param arcHeight the height of the arc + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.drawRoundRect(x, y, width, height, arcWidth, arcHeight); +// ensureAreaClean(x, y, width, height); +} + +//void drawRoundRectangleGdip (int gdipGraphics, int brush, int x, int y, int width, int height, int arcWidth, int arcHeight) { +// int nx = x; +// int ny = y; +// int nw = width; +// int nh = height; +// int naw = arcWidth; +// int nah = arcHeight; +// +// if (nw < 0) { +// nw = 0 - nw; +// nx = nx - nw; +// } +// if (nh < 0) { +// nh = 0 - nh; +// ny = ny - nh; +// } +// if (naw < 0) +// naw = 0 - naw; +// if (nah < 0) +// nah = 0 - nah; +// +// int naw2 = naw / 2; +// int nah2 = nah / 2; +// +// if (nw > naw) { +// if (nh > nah) { +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, naw, nah, -90, -90); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny, nx + nw - naw2, ny); +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny, naw, nah, 0, -90); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + nw, ny + nah2, nx + nw, ny + nh - nah2); +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny + nh, nx + nw - naw2, ny + nh); +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny + nh - nah, naw, nah, -180, -90); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx, ny + nah2, nx, ny + nh - nah2); +// } else { +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, naw, nh, 90, -180); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny, nx + nw - naw2, ny); +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny, naw, nh, 270, -180); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny + nh, nx + nw - naw2, ny + nh); +// } +// } else { +// if (nh > nah) { +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, nw, nah, 0, -180); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + nw, ny + nah2, nx + nw, ny + nh - nah2); +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny + nh - nah, nw, nah, -180, -180); +// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx, ny + nah2, nx, ny + nh - nah2); +// } else { +// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, nw, nh, 0, 360); +// } +// } +//} + +/** + * Draws the given string, using the receiver's current font and + * foreground color. No tab expansion or carriage return processing + * will be performed. The background of the rectangular area where + * the string is being drawn will be filled with the receiver's + * background color. + * + * @param string the string to be drawn + * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawString (String string, int x, int y) { + drawString(string, x, y, false); +} + +/** + * Draws the given string, using the receiver's current font and + * foreground color. No tab expansion or carriage return processing + * will be performed. If isTransparent is true, + * then the background of the rectangular area where the string is being + * drawn will not be modified, otherwise it will be filled with the + * receiver's background color. + * + * @param string the string to be drawn + * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn + * @param isTransparent if true the background will be transparent, otherwise it will be opaque + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawString (String string, int x, int y, boolean isTransparent) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + drawText(string, x, y, isTransparent? SWT.DRAW_TRANSPARENT: 0); +// if(!isTransparent) { +// java.awt.Color oldColor = handle.getColor(); +// handle.setColor(data.background); +// Point extent = stringExtent(string); +// fillRectangle(x, y, extent.x, extent.y); +// handle.setColor(oldColor); +// } +// handle.drawString(string, x, y + handle.getFontMetrics().getMaxAscent()); +// // TODO: optimize if the ensureAreaClean works +// Point extent = stringExtent(string); +// ensureAreaClean(x, y, extent.x, extent.y); +} + +/** + * Draws the given string, using the receiver's current font and + * foreground color. Tab expansion and carriage return processing + * are performed. The background of the rectangular area where + * the text is being drawn will be filled with the receiver's + * background color. + * + * @param string the string to be drawn + * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawText (String string, int x, int y) { + drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB); +} + +/** + * Draws the given string, using the receiver's current font and + * foreground color. Tab expansion and carriage return processing + * are performed. If isTransparent is true, + * then the background of the rectangular area where the text is being + * drawn will not be modified, otherwise it will be filled with the + * receiver's background color. + * + * @param string the string to be drawn + * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param isTransparent if true the background will be transparent, otherwise it will be opaque + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawText (String string, int x, int y, boolean isTransparent) { + int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB; + if (isTransparent) flags |= SWT.DRAW_TRANSPARENT; + drawText(string, x, y, flags); +} + +/** + * Draws the given string, using the receiver's current font and + * foreground color. Tab expansion, line delimiter and mnemonic + * processing are performed according to the specified flags. If + * flags includes DRAW_TRANSPARENT, + * then the background of the rectangular area where the text is being + * drawn will not be modified, otherwise it will be filled with the + * receiver's background color. + *

    + * The parameter flags may be a combination of: + *

    + *
    DRAW_DELIMITER
    + *
    draw multiple lines
    + *
    DRAW_TAB
    + *
    expand tabs
    + *
    DRAW_MNEMONIC
    + *
    underline the mnemonic character
    + *
    DRAW_TRANSPARENT
    + *
    transparent background
    + *
    + *

    + * + * @param string the string to be drawn + * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param flags the flags specifing how to process the text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void drawText (String string, int x, int y, int flags) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (string.length() == 0) return; + if((flags & SWT.DRAW_TAB) != 0) { + string = string.replaceAll("\t", " "); + } + int mnemonicIndex = -1; + if((flags & SWT.DRAW_MNEMONIC) != 0) { + // Copied from Label + mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); + mnemonicIndex -= mnemonicIndex - 1 - s.length(); + mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + // TODO: if the mnemonic index is not -1, then draw a line under the char. + } + String[] tokens; + if((flags & SWT.DRAW_DELIMITER) != 0) { + tokens = string.split("\n"); + } else { + tokens = new String[] {string}; + } + boolean isTransparent = (flags & SWT.DRAW_TRANSPARENT) != 0; + java.awt.FontMetrics fm = handle.getFontMetrics(); + int fmHeight = fm.getHeight(); + int maxAscent = fm.getMaxAscent(); + int currentHeight = 0; + for(int i=0; i= length) return -1; + if (string.charAt (index) != '&') return index; + index++; + } while (index < length); + return -1; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public boolean equals (Object object) { + return (object == this) || ((object instanceof GC) && (handle == ((GC)object).handle)); +} + +/** + * Fills the interior of a circular or elliptical arc within + * the specified rectangular area, with the receiver's background + * color. + *

    + * The resulting arc begins at startAngle and extends + * for arcAngle degrees, using the current color. + * Angles are interpreted such that 0 degrees is at the 3 o'clock + * position. A positive value indicates a counter-clockwise rotation + * while a negative value indicates a clockwise rotation. + *

    + * The center of the arc is the center of the rectangle whose origin + * is (x, y) and whose size is specified by the + * width and height arguments. + *

    + * The resulting arc covers an area width + 1 pixels wide + * by height + 1 pixels tall. + *

    + * + * @param x the x coordinate of the upper-left corner of the arc to be filled + * @param y the y coordinate of the upper-left corner of the arc to be filled + * @param width the width of the arc to be filled + * @param height the height of the arc to be filled + * @param startAngle the beginning angle + * @param arcAngle the angular extent of the arc, relative to the start angle + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawArc + */ +public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + if (width == 0 || height == 0 || arcAngle == 0) return; + java.awt.Color oldColor = handle.getColor(); + handle.setColor(data.background); + handle.fillArc(x, y, width, height, startAngle, arcAngle); + handle.setColor(oldColor); +// ensureAreaClean(x, y, width, height); +// if (data.gdipGraphics != 0) { +// initGdip(false, true); +// Gdip.Graphics_FillPie(data.gdipGraphics, data.gdipBrush, x, y, width, height, -startAngle, -arcAngle); +// return; +// } +// +// /* +// * Feature in WinCE. The function Pie is not present in the +// * WinCE SDK. The fix is to emulate it by using Polygon. +// */ +// if (OS.IsWinCE) { +// /* compute arc with a simple linear interpolation */ +// if (arcAngle < 0) { +// startAngle += arcAngle; +// arcAngle = -arcAngle; +// } +// boolean drawSegments = true; +// if (arcAngle >= 360) { +// arcAngle = 360; +// drawSegments = false; +// } +// int[] points = new int[(arcAngle + 1) * 2 + (drawSegments ? 4 : 0)]; +// int cteX = 2 * x + width; +// int cteY = 2 * y + height; +// int index = (drawSegments ? 2 : 0); +// for (int i = 0; i <= arcAngle; i++) { +// points[index++] = (Compatibility.cos(startAngle + i, width) + cteX) >> 1; +// points[index++] = (cteY - Compatibility.sin(startAngle + i, height)) >> 1; +// } +// if (drawSegments) { +// points[0] = points[points.length - 2] = cteX >> 1; +// points[1] = points[points.length - 1] = cteY >> 1; +// } +// int nullPen = OS.GetStockObject(OS.NULL_PEN); +// int oldPen = OS.SelectObject(handle, nullPen); +// OS.Polygon(handle, points, points.length / 2); +// OS.SelectObject(handle, oldPen); +// } else { +// int x1, y1, x2, y2,tmp; +// boolean isNegative; +// if (arcAngle >= 360 || arcAngle <= -360) { +// x1 = x2 = x + width; +// y1 = y2 = y + height / 2; +// } else { +// isNegative = arcAngle < 0; +// +// arcAngle = arcAngle + startAngle; +// if (isNegative) { +// // swap angles +// tmp = startAngle; +// startAngle = arcAngle; +// arcAngle = tmp; +// } +// x1 = Compatibility.cos(startAngle, width) + x + width/2; +// y1 = -1 * Compatibility.sin(startAngle, height) + y + height/2; +// +// x2 = Compatibility.cos(arcAngle, width) + x + width/2; +// y2 = -1 * Compatibility.sin(arcAngle, height) + y + height/2; +// } +// +// int nullPen = OS.GetStockObject(OS.NULL_PEN); +// int oldPen = OS.SelectObject(handle, nullPen); +// OS.Pie(handle, x, y, x + width + 1, y + height + 1, x1, y1, x2, y2); +// OS.SelectObject(handle, oldPen); +// } +} + +/** + * Fills the interior of the specified rectangle with a gradient + * sweeping from left to right or top to bottom progressing + * from the receiver's foreground color to its background color. + * + * @param x the x coordinate of the rectangle to be filled + * @param y the y coordinate of the rectangle to be filled + * @param width the width of the rectangle to be filled, may be negative + * (inverts direction of gradient if horizontal) + * @param height the height of the rectangle to be filled, may be negative + * (inverts direction of gradient if vertical) + * @param vertical if true sweeps from top to bottom, else + * sweeps from left to right + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawRectangle(int, int, int, int) + */ +public void fillGradientRectangle(int x, int y, int width, int height, boolean vertical) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width == 0 || height == 0) return; + java.awt.Color fromColor = handle.getColor(); + java.awt.Color toColor = handle.getBackground(); + Paint oldPaint = handle.getPaint(); + java.awt.Point p1; + java.awt.Point p2; + if(vertical) { + p1 = new java.awt.Point(x, y); + p2 = new java.awt.Point(x, y + height); + } else { + p1 = new java.awt.Point(x, y); + p2 = new java.awt.Point(x + width, y); + } +// java.awt.Color oldColor = handle.getColor(); +// handle.setColor(data.background); + handle.setPaint(new GradientPaint(p1, fromColor, p2, toColor)); + handle.fill(new java.awt.Rectangle(x, y, width, height)); +// handle.setColor(oldColor); + handle.setPaint(oldPaint); +// ensureAreaClean(x, y, width, height); +} + +/** + * Fills the interior of an oval, within the specified + * rectangular area, with the receiver's background + * color. + * + * @param x the x coordinate of the upper left corner of the oval to be filled + * @param y the y coordinate of the upper left corner of the oval to be filled + * @param width the width of the oval to be filled + * @param height the height of the oval to be filled + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawOval + */ +public void fillOval (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Color oldColor = handle.getColor(); + handle.setColor(data.background); + handle.fillOval(x, y, width, height); + handle.setColor(oldColor); +// ensureAreaClean(x, y, width, height); +// if (data.gdipGraphics != 0) { +// initGdip(false, true); +// Gdip.Graphics_FillEllipse(data.gdipGraphics, data.gdipBrush, x, y, width, height); +// return; +// } +// /* Assumes that user sets the background color. */ +// int nullPen = OS.GetStockObject(OS.NULL_PEN); +// int oldPen = OS.SelectObject(handle, nullPen); +// OS.Ellipse(handle, x, y, x + width + 1, y + height + 1); +// OS.SelectObject(handle,oldPen); +} + +/** + * Fills the path described by the parameter. + * + * @param path the path to fill + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Path + * + * @since 3.1 + */ +public void fillPath (Path path) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (path.handle == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + // Set fill(winding) rule + int windingRule = fillRule == SWT.FILL_EVEN_ODD ? GeneralPath.WIND_EVEN_ODD: GeneralPath.WIND_NON_ZERO; + path.handle.setWindingRule(windingRule); + // Use background color for paint. + Paint old = handle.getPaint(); + handle.setPaint(handle.getBackground()); + handle.fill(path.handle); + handle.setPaint(old); +// java.awt.Rectangle bounds = path.handle.getBounds(); +// ensureAreaClean(bounds.x, bounds.y, bounds.width, bounds.height); +} + +/** + * Fills the interior of the closed polygon which is defined by the + * specified array of integer coordinates, using the receiver's + * background color. The array contains alternating x and y values + * which are considered to represent points which are the vertices of + * the polygon. Lines are drawn between each consecutive pair, and + * between the first pair and last pair in the array. + * + * @param pointArray an array of alternating x and y values which are the vertices of the polygon + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT if pointArray is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawPolygon + */ +public void fillPolygon(int[] pointArray) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + int maxX = Integer.MIN_VALUE; + int maxY = Integer.MIN_VALUE; + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + int[] xPoints = new int[pointArray.length/2]; + int[] yPoints = new int[xPoints.length]; + for(int i=0; i + *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • + * + * + * @see #drawRectangle(int, int, int, int) + */ +public void fillRectangle (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Color oldColor = handle.getColor(); + handle.setColor(data.background); + handle.fillRect(x, y, width, height); + handle.setColor(oldColor); +// ensureAreaClean(x, y, width, height); +// if (data.gdipGraphics != 0) { +// initGdip(false, true); +// Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height); +// return; +// } +// int rop2 = 0; +// if (OS.IsWinCE) { +// rop2 = OS.SetROP2(handle, OS.R2_COPYPEN); +// OS.SetROP2(handle, rop2); +// } else { +// rop2 = OS.GetROP2(handle); +// } +// int dwRop = rop2 == OS.R2_XORPEN ? OS.PATINVERT : OS.PATCOPY; +// OS.PatBlt(handle, x, y, width, height, dwRop); +} + +/** + * Fills the interior of the specified rectangle, using the receiver's + * background color. + * + * @param rect the rectangle to be filled + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the rectangle is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawRectangle(int, int, int, int) + */ +public void fillRectangle (Rectangle rect) { + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + java.awt.Color oldColor = handle.getColor(); + handle.setColor(data.background); + fillRectangle (rect.x, rect.y, rect.width, rect.height); + handle.setColor(oldColor); +} + +/** + * Fills the interior of the round-cornered rectangle specified by + * the arguments, using the receiver's background color. + * + * @param x the x coordinate of the rectangle to be filled + * @param y the y coordinate of the rectangle to be filled + * @param width the width of the rectangle to be filled + * @param height the height of the rectangle to be filled + * @param arcWidth the width of the arc + * @param arcHeight the height of the arc + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #drawRoundRectangle + */ +public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Color oldColor = handle.getColor(); + handle.setColor(data.background); + handle.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + handle.setColor(oldColor); +// ensureAreaClean(x, y, width, height); +// if (data.gdipGraphics != 0) { +// initGdip(false, true); +// fillRoundRectangleGdip(data.gdipGraphics, data.gdipBrush, x, y, width, height, arcWidth, arcHeight); +// return; +// } +// int nullPen = OS.GetStockObject(OS.NULL_PEN); +// int oldPen = OS.SelectObject(handle, nullPen); +// OS.RoundRect(handle, x,y,x+width+1,y+height+1,arcWidth, arcHeight); +// OS.SelectObject(handle,oldPen); +} + +//void fillRoundRectangleGdip (int gdipGraphics, int brush, int x, int y, int width, int height, int arcWidth, int arcHeight) { +// int nx = x; +// int ny = y; +// int nw = width; +// int nh = height; +// int naw = arcWidth; +// int nah = arcHeight; +// +// if (nw < 0) { +// nw = 0 - nw; +// nx = nx - nw; +// } +// if (nh < 0) { +// nh = 0 - nh; +// ny = ny -nh; +// } +// if (naw < 0) +// naw = 0 - naw; +// if (nah < 0) +// nah = 0 - nah; +// +// int naw2 = naw / 2; +// int nah2 = nah / 2; +// +// if (nw > naw) { +// if (nh > nah) { +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, naw, nah, -90, -90); +// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny, nw - naw2 * 2, nah2); +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny, naw, nah, 0, -90); +// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx, ny + nah2, nw, nh - nah2 * 2); +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); +// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny + nh - nah2, nw - naw2 * 2, nah2); +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny + nh - nah, naw, nah, -180, -90); +// } else { +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, naw, nh, -90, -180); +// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny, nw - naw2 * 2, nh); +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny, naw, nh, -270, -180); +// } +// } else { +// if (nh > nah) { +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, nw, nah, 0, -180); +// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx, ny + nah2, nw, nh - nah2 * 2); +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny + nh - nah, nw, nah, -180, -180); +// } else { +// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, nw, nh, 0, 360); +// } +// } +//} + +/** + * Returns the advance width of the specified character in + * the font which is currently selected into the receiver. + *

    + * The advance width is defined as the horizontal distance the cursor + * should move after printing the character in the selected font. + *

    + * + * @param ch the character to measure + * @return the distance in the x direction to move past the character before painting the next + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getAdvanceWidth(char ch) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.getFontMetrics().charWidth(ch); +// if (OS.IsWinCE) { +// SIZE size = new SIZE(); +// OS.GetTextExtentPoint32W(handle, new char[]{ch}, 1, size); +// return size.cx; +// } +// int tch = ch; +// if (ch > 0x7F) { +// TCHAR buffer = new TCHAR(getCodePage(), ch, false); +// tch = buffer.tcharAt(0); +// } +// int[] width = new int[1]; +// OS.GetCharWidth(handle, tch, tch, width); +// return width[0]; +} + +/** + * Returns true if receiver is using the operating system's + * advanced graphics subsystem. Otherwise, false is returned + * to indicate that normal graphics are in use. + *

    + * Advanced graphics may not be installed for the operating system. In this + * case, false is always returned. Some operating system have + * only one graphics subsystem. If this subsystem supports advanced graphics, + * then true is always returned. If any graphics operation such + * as alpha, antialias, patterns, interpolation, paths, clipping or transformation + * has caused the receiver to switch from regular to advanced graphics mode, + * true is returned. If the receiver has been explicitly switched + * to advanced mode and this mode is supported, true is returned. + *

    + * + * @return the advanced value + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setAdvanced + * @since 3.1 + */ +public boolean getAdvanced() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data.advanced; +} + +/** + * Returns the receiver's alpha value. + * + * @return the alpha value + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int getAlpha() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data.alpha; +} + +/** + * Returns the receiver's anti-aliasing setting value, which will be + * one of SWT.DEFAULT, SWT.OFF or + * SWT.ON. Note that this controls anti-aliasing for all + * non-text drawing operations. + * + * @return the anti-aliasing setting + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getTextAntialias + * + * @since 3.1 + */ +public int getAntialias() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + Object value = handle.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + if(value == RenderingHints.VALUE_ANTIALIAS_OFF) return SWT.OFF; + if(value == RenderingHints.VALUE_ANTIALIAS_ON) return SWT.ON; + return SWT.DEFAULT; +} + +/** + * Returns the background color. + * + * @return the receiver's background color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Color getBackground() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return Color.swing_new(data.device, handle.getBackground()); +// int color = OS.GetBkColor(handle); +// if (color == OS.CLR_INVALID) { +// color = OS.GetSysColor(OS.COLOR_WINDOW); +// } +// return Color.win32_new(data.device, color); +} + +/** + * Returns the background pattern. The default value is + * null. + * + * @return the receiver's background pattern + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Pattern + * + * @since 3.1 + */ +public Pattern getBackgroundPattern() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data.backgroundPattern; +} + +/** + * Returns the width of the specified character in the font + * selected into the receiver. + *

    + * The width is defined as the space taken up by the actual + * character, not including the leading and tailing whitespace + * or overhang. + *

    + * + * @param ch the character to measure + * @return the width of the character + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getCharWidth(char ch) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + // TODO: find the difference between advance width and char width + return handle.getFontMetrics().charWidth(ch); +// +// /* GetCharABCWidths only succeeds on truetype fonts */ +// if (!OS.IsWinCE) { +// int tch = ch; +// if (ch > 0x7F) { +// TCHAR buffer = new TCHAR(getCodePage(), ch, false); +// tch = buffer.tcharAt (0); +// } +// int[] width = new int[3]; +// if (OS.GetCharABCWidths(handle, tch, tch, width)) { +// return width[1]; +// } +// } +// +// /* It wasn't a truetype font */ +// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA(); +// OS.GetTextMetrics(handle, lptm); +// SIZE size = new SIZE(); +// OS.GetTextExtentPoint32W(handle, new char[]{ch}, 1, size); +// return size.cx - lptm.tmOverhang; +} + +/** + * Returns the bounding rectangle of the receiver's clipping + * region. If no clipping region is set, the return value + * will be a rectangle which covers the entire bounds of the + * object the receiver is drawing on. + * + * @return the bounding rectangle of the clipping region + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Rectangle getClipping() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + Shape userClip = handle.getUserClip(); + java.awt.Rectangle bounds; + if(userClip != null) { + bounds = userClip.getBounds(); + } else { + bounds = new java.awt.Rectangle(handle.getDeviceSize()); + } + return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); +} + +/** + * Sets the region managed by the argument to the current + * clipping region of the receiver. + * + * @param region the region to fill with the clipping region + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the region is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the region is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void getClipping (Region region) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT); + Shape userClip = handle.getUserClip(); + if(userClip == null) { + userClip = new java.awt.Rectangle(handle.getDeviceSize()); + } + region.add(new Region(data.device, userClip)); +// int result = OS.GetClipRgn (handle, region.handle); +// if (result != 1) { +// RECT rect = new RECT(); +// OS.GetClipBox(handle, rect); +// OS.SetRectRgn(region.handle, rect.left, rect.top, rect.right, rect.bottom); +// } +// if (!OS.IsWinCE) { +// int flags = 0; +// if (OS.WIN32_VERSION >= OS.VERSION(4, 10)) { +// flags = OS.GetLayout(handle); +// } +// int hwnd = data.hwnd; +// if (hwnd != 0 && data.ps != null && (flags & OS.LAYOUT_RTL) == 0) { +// int sysRgn = OS.CreateRectRgn (0, 0, 0, 0); +// if (OS.GetRandomRgn (handle, sysRgn, OS.SYSRGN) == 1) { +// if (OS.IsWinNT) { +// POINT pt = new POINT(); +// OS.MapWindowPoints(0, hwnd, pt, 1); +// OS.OffsetRgn(sysRgn, pt.x, pt.y); +// } +// OS.CombineRgn (region.handle, sysRgn, region.handle, OS.RGN_AND); +// } +// OS.DeleteObject(sysRgn); +// } +// } +} + +//int getCodePage () { +// if (OS.IsUnicode) return OS.CP_ACP; +// int[] lpCs = new int[8]; +// int cs = OS.GetTextCharset(handle); +// OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET); +// return lpCs[1]; +//} + +/** + * Returns the receiver's fill rule, which will be one of + * SWT.FILL_EVEN_ODD or SWT.FILL_WINDING. + * + * @return the receiver's fill rule + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int getFillRule() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return fillRule; +} + +/** + * Returns the font currently being used by the receiver + * to draw and measure text. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Font getFont () { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return Font.swing_new(data.device, handle.getFont()); +} + +/** + * Returns a FontMetrics which contains information + * about the font currently being used by the receiver + * to draw and measure text. + * + * @return font metrics for the receiver's font + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public FontMetrics getFontMetrics() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return FontMetrics.swing_new(handle.getFontMetrics()); +} + +/** + * Returns the receiver's foreground color. + * + * @return the color used for drawing foreground things + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Color getForeground() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return Color.swing_new(data.device, handle.getColor()); +} + +/** + * Returns the foreground pattern. The default value is + * null. + * + * @return the receiver's foreground pattern + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Pattern + * + * @since 3.1 + */ +public Pattern getForegroundPattern() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data.foregroundPattern; +} + +/** + * Returns the GCData. + *

    + * IMPORTANT: This method is not part of the public + * API for GC. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @return the receiver's GCData + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see GCData + * + * @since 3.2 + */ +public GCData getGCData() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data; +} + +/** + * Returns the receiver's interpolation setting, which will be one of + * SWT.DEFAULT, SWT.NONE, + * SWT.LOW or SWT.HIGH. + * + * @return the receiver's interpolation setting + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int getInterpolation() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + Utils.notImplemented(); return SWT.DEFAULT; +// if (data.gdipGraphics == 0) return SWT.DEFAULT; +// int mode = Gdip.Graphics_GetInterpolationMode(data.gdipGraphics); +// switch (mode) { +// case Gdip.InterpolationModeDefault: return SWT.DEFAULT; +// case Gdip.InterpolationModeNearestNeighbor: return SWT.NONE; +// case Gdip.InterpolationModeBilinear: +// case Gdip.InterpolationModeLowQuality: return SWT.LOW; +// case Gdip.InterpolationModeBicubic: +// case Gdip.InterpolationModeHighQualityBilinear: +// case Gdip.InterpolationModeHighQualityBicubic: +// case Gdip.InterpolationModeHighQuality: return SWT.HIGH; +// } +// return SWT.DEFAULT; +} + +/** + * Returns the receiver's line cap style, which will be one + * of the constants SWT.CAP_FLAT, SWT.CAP_ROUND, + * or SWT.CAP_SQUARE. + * + * @return the cap style used for drawing lines + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int getLineCap() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + switch(getCurrentBasicStroke().getEndCap()) { + case BasicStroke.CAP_ROUND: + return SWT.CAP_ROUND; + case BasicStroke.CAP_SQUARE: + return SWT.CAP_SQUARE; + } + return SWT.CAP_FLAT; +} + +/** + * Returns the receiver's line dash style. The default value is + * null. + * + * @return the line dash style used for drawing lines + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int[] getLineDash() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + float[] dashArray = getCurrentBasicStroke().getDashArray(); + if(dashArray == null) return null; + int[] dashes = new int[dashArray.length]; + for(int i=0; iSWT.JOIN_MITER, SWT.JOIN_ROUND, + * or SWT.JOIN_BEVEL. + * + * @return the join style used for drawing lines + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public int getLineJoin() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + switch(getCurrentBasicStroke().getLineJoin()) { + case BasicStroke.JOIN_BEVEL: + return SWT.JOIN_BEVEL; + case BasicStroke.JOIN_ROUND: + return SWT.JOIN_ROUND; + } + return SWT.JOIN_MITER; +} + +/** + * Returns the receiver's line style, which will be one + * of the constants SWT.LINE_SOLID, SWT.LINE_DASH, + * SWT.LINE_DOT, SWT.LINE_DASHDOT or + * SWT.LINE_DASHDOTDOT. + * + * @return the style used for drawing lines + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getLineStyle() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + float[] dashArray = getCurrentBasicStroke().getDashArray(); + if(dashArray == null) { + return SWT.LINE_SOLID; + } else if(dashArray == lineDashArray) { + return SWT.LINE_DASH; + } else if(dashArray == lineDotArray) { + return SWT.LINE_DOT; + } else if(dashArray == lineDashDotArray) { + return SWT.LINE_DASHDOT; + } else if(dashArray == lineDashDotDotArray) { + return SWT.LINE_DASHDOTDOT; + } else if(dashArray != null && dashArray == data.dashes) { + return SWT.LINE_CUSTOM; + } + return SWT.LINE_SOLID; +// +// int style, size; +// int hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN); +// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) { +// LOGPEN logPen = new LOGPEN(); +// OS.GetObject(hPen, LOGPEN.sizeof, logPen); +// style = logPen.lopnStyle; +// } else { +// EXTLOGPEN logPen = new EXTLOGPEN(); +// if (size <= EXTLOGPEN.sizeof) { +// OS.GetObject(hPen, size, logPen); +// } else { +// int hHeap = OS.GetProcessHeap(); +// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size); +// OS.GetObject(hPen, size, ptr); +// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof); +// OS.HeapFree(hHeap, 0, ptr); +// } +// style = logPen.elpPenStyle & OS.PS_STYLE_MASK; +// } +// switch (style) { +// case OS.PS_SOLID: return SWT.LINE_SOLID; +// case OS.PS_DASH: return SWT.LINE_DASH; +// case OS.PS_DOT: return SWT.LINE_DOT; +// case OS.PS_DASHDOT: return SWT.LINE_DASHDOT; +// case OS.PS_DASHDOTDOT: return SWT.LINE_DASHDOTDOT; +// case OS.PS_USERSTYLE: return SWT.LINE_CUSTOM; +// default: return SWT.LINE_SOLID; +// } +} + +/** + * Returns the width that will be used when drawing lines + * for all of the figure drawing operations (that is, + * drawLine, drawRectangle, + * drawPolyline, and so forth. + * + * @return the receiver's line width + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getLineWidth() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return (int)getCurrentBasicStroke().getLineWidth(); +} + +/** + * Returns the receiver's style information. + *

    + * Note that the value which is returned by this method may + * not match the value which was provided to the constructor + * when the receiver was created. This can occur when the underlying + * operating system does not support a particular combination of + * requested styles. + *

    + * + * @return the style bits + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1.2 + */ +public int getStyle () { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return data.style; +} + +/** + * Returns the receiver's text drawing anti-aliasing setting value, + * which will be one of SWT.DEFAULT, SWT.OFF or + * SWT.ON. Note that this controls anti-aliasing + * only for text drawing operations. + * + * @return the anti-aliasing setting + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getAntialias + * + * @since 3.1 + */ +public int getTextAntialias() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + Object value = handle.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); + if(value == RenderingHints.VALUE_TEXT_ANTIALIAS_OFF) return SWT.OFF; + if(value == RenderingHints.VALUE_TEXT_ANTIALIAS_ON) return SWT.ON; + return SWT.DEFAULT; +} + +/** + * Sets the parameter to the transform that is currently being + * used by the receiver. + * + * @param transform the destination to copy the transform into + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Transform + * + * @since 3.1 + */ +public void getTransform(Transform transform) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if(gcAT == null) { + transform.handle = new AffineTransform(); + } else { + transform.handle = new AffineTransform(gcAT); + } +} + +boolean isXORMode = false; + +/** + * Returns true if this GC is drawing in the mode + * where the resulting color in the destination is the + * exclusive or of the color values in the source + * and the destination, and false if it is + * drawing in the mode where the destination color is being + * replaced with the source color value. + * + * @return true true if the receiver is in XOR mode, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean getXORMode() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + // TODO: Not a solution because if swing is used directly in future implementation, this does not detect. + return isXORMode; +// int rop2 = 0; +// if (OS.IsWinCE) { +// rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN); +// OS.SetROP2 (handle, rop2); +// } else { +// rop2 = OS.GetROP2(handle); +// } +// return rop2 == OS.R2_XORPEN; +} + +//void initGdip(boolean draw, boolean fill) { +// data.device.checkGDIP(); +// int gdipGraphics = data.gdipGraphics; +// if (gdipGraphics == 0) gdipGraphics = data.gdipGraphics = Gdip.Graphics_new(handle); +// if (gdipGraphics == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// if (draw && data.gdipPen == 0) data.gdipPen = createGdipPen(); +// if (fill && data.gdipBrush == 0) data.gdipBrush = createGdipBrush(); +//} + +void init(Drawable drawable, GCData data, CGC handle) { + if(data.foreground != null) { + handle.setColor(data.foreground); + } + if(data.background != null) { + handle.setBackground(data.background); + } + if(data.hFont != null) { + handle.setFont(data.hFont); + } +// int foreground = data.foreground; +// if (foreground != -1 && OS.GetTextColor(hDC) != foreground) { +// OS.SetTextColor(hDC, foreground); +// int newPen = OS.CreatePen(OS.PS_SOLID, 0, foreground); +// OS.SelectObject(hDC, newPen); +// if (data.hPen != 0) OS.DeleteObject(data.hPen); +// data.hPen = newPen; +// } +// int background = data.background; +// if (background != -1 && OS.GetBkColor(hDC) != background) { +// OS.SetBkColor(hDC, background); +// int newBrush = OS.CreateSolidBrush(background); +// OS.SelectObject(hDC, newBrush); +// if (data.hBrush != 0) OS.DeleteObject (data.hBrush); +// data.hBrush = newBrush; +// } +// int hFont = data.hFont; +// if (hFont != 0) OS.SelectObject (hDC, hFont); +// int hPalette = data.device.hPalette; +// if (hPalette != 0) { +// OS.SelectPalette(hDC, hPalette, true); +// OS.RealizePalette(hDC); +// } +// Image image = data.image; +// if (image != null) { +// data.hNullBitmap = OS.SelectObject(hDC, image.handle); +// image.memGC = this; +// } +// int layout = data.layout; +// if (layout != -1) { +// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { +// int flags = OS.GetLayout(hDC); +// if ((flags & OS.LAYOUT_RTL) != (layout & OS.LAYOUT_RTL)) { +// flags &= ~OS.LAYOUT_RTL; +// OS.SetLayout(hDC, flags | layout); +// } +// if ((data.style & SWT.RIGHT_TO_LEFT) != 0) data.style |= SWT.MIRRORED; +// } +// } + this.drawable = drawable; + this.data = data; + this.handle = handle; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #equals + */ +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +/** + * Returns true if the receiver has a clipping + * region set into it, and false otherwise. + * If this method returns false, the receiver will draw on all + * available space in the destination. If it returns true, + * it will draw only in the area that is covered by the region + * that can be accessed with getClipping(region). + * + * @return true if the GC has a clipping region, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean isClipped() { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.getUserClip() != null; +} + +/** + * Returns true if the GC has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the GC. + * When a GC has been disposed, it is an error to + * invoke any other method using the GC. + * + * @return true when the GC is disposed and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +//boolean isIdentity(float[] xform) { +// return xform[0] == 1 && xform[1] == 0 && xform[2] == 0 && +// xform[3] == 1 && xform[4] == 0 && xform[5] == 0; +//} + +/** + * Sets the receiver to always use the operating system's advanced graphics + * subsystem for all graphics operations if the argument is true. + * If the argument is false, the advanced graphics subsystem is + * no longer used, advanced graphics state is cleared and the normal graphics + * subsystem is used from now on. + *

    + * Normally, the advanced graphics subsystem is invoked automatically when + * any one of the alpha, antialias, patterns, interpolation, paths, clipping + * or transformation operations in the receiver is requested. When the receiver + * is switched into advanced mode, the advanced graphics subsystem performs both + * advanced and normal graphics operations. Because the two subsystems are + * different, their output may differ. Switching to advanced graphics before + * any graphics operations are performed ensures that the output is consistent. + *

    + *

    + * Advanced graphics may not be installed for the operating system. In this + * case, this operation does nothing. Some operating system have only one + * graphics subsystem, so switching from normal to advanced graphics does + * nothing. However, switching from advanced to normal graphics will always + * clear the advanced graphics state, even for operating systems that have + * only one graphics subsystem. + *

    + * + * @param advanced the new advanced graphics state + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setAlpha + * @see #setAntialias + * @see #setBackgroundPattern + * @see #setClipping(Path) + * @see #setForegroundPattern + * @see #setInterpolation + * @see #setTextAntialias + * @see #setTransform + * @see #getAdvanced + * + * @since 3.1 + */ +public void setAdvanced(boolean advanced) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + data.advanced = advanced; +} + +/** + * Sets the receiver's anti-aliasing value to the parameter, + * which must be one of SWT.DEFAULT, SWT.OFF + * or SWT.ON. Note that this controls anti-aliasing for all + * non-text drawing operations. + * + * @param antialias the anti-aliasing setting + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parameter is not one of SWT.DEFAULT, + * SWT.OFF or SWT.ON
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setTextAntialias + * + * @since 3.1 + */ +public void setAntialias(int antialias) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + switch (antialias) { + case SWT.DEFAULT: + handle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT); + break; + case SWT.OFF: + handle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + break; + case SWT.ON: + handle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } +} + +/** + * Sets the receiver's alpha value. + * + * @param alpha the alpha value + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setAlpha(int alpha) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + data.alpha = alpha & 0xFF; + AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, data.alpha / 255.0f); + handle.setComposite(comp); +} + +/** + * Sets the background color. The background color is used + * for fill operations and as the background color when text + * is drawn. + * + * @param color the new background color for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the color is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the color has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setBackground (Color color) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + data.background = color.handle; + handle.setBackground(color.handle); +// if (OS.GetBkColor(handle) == color.handle) return; +// data.background = color.handle; +// OS.SetBkColor (handle, color.handle); +// int newBrush = OS.CreateSolidBrush (color.handle); +// OS.SelectObject (handle, newBrush); +// if (data.hBrush != 0) OS.DeleteObject (data.hBrush); +// data.hBrush = newBrush; +// if (data.gdipBrush != 0) { +// Gdip.SolidBrush_delete(data.gdipBrush); +// data.gdipBrush = 0; +// } +} + +/** + * Sets the background pattern. The default value is null. + * + * @param pattern the new background pattern + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Pattern + * + * @since 3.1 + */ +public void setBackgroundPattern (Pattern pattern) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + Utils.notImplemented(); +// if (data.gdipGraphics == 0 && pattern == null) return; +// initGdip(false, false); +// if (data.gdipBrush != 0) destroyGdipBrush(data.gdipBrush); +// if (pattern != null) { +// data.gdipBrush = Gdip.Brush_Clone(pattern.handle); +// } else { +// data.gdipBrush = 0; +// } + data.backgroundPattern = pattern; +} + +//void setClipping(int clipRgn) { +// int hRgn = clipRgn; +// int gdipGraphics = data.gdipGraphics; +// if (hRgn != 0) { +// boolean result; +// float[] xform = new float[]{1, 0, 0, 1, 0, 0}; +// if (gdipGraphics != 0) { +// int matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0); +// result = Gdip.Graphics_GetTransform(gdipGraphics, matrix) == 0; +// Gdip.Matrix_GetElements(matrix, xform); +// Gdip.Matrix_delete(matrix); +// } else { +// result = OS.GetWorldTransform(handle, xform); +// } +// if (result && !isIdentity(xform)) { +// int count = OS.GetRegionData(hRgn, 0, null); +// int[] lpRgnData = new int[count / 4]; +// OS.GetRegionData(hRgn, count, lpRgnData); +// hRgn = OS.ExtCreateRegion(xform, count, lpRgnData); +// } +// } +// OS.SelectClipRgn (handle, hRgn); +// if (gdipGraphics != 0) { +// if (hRgn != 0) { +// Gdip.Graphics_SetClip(gdipGraphics, hRgn, Gdip.CombineModeReplace); +// } else { +// Gdip.Graphics_ResetClip(gdipGraphics); +// } +// } +// if (hRgn != 0 && hRgn != clipRgn) { +// OS.DeleteObject(hRgn); +// } +//} + +/** + * Sets the area of the receiver which can be changed + * by drawing operations to the rectangular area specified + * by the arguments. + * + * @param x the x coordinate of the clipping rectangle + * @param y the y coordinate of the clipping rectangle + * @param width the width of the clipping rectangle + * @param height the height of the clipping rectangle + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setClipping (int x, int y, int width, int height) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + setClipping(new Rectangle(x, y, width, height)); +} + +/** + * Sets the area of the receiver which can be changed + * by drawing operations to the path specified + * by the argument. + * + * @param path the clipping path. + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the path has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Path + * + * @since 3.1 + */ +public void setClipping (Path path) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.setUserClip(path.handle); +} + +/** + * Sets the area of the receiver which can be changed + * by drawing operations to the rectangular area specified + * by the argument. Specifying null for the + * rectangle reverts the receiver's clipping area to its + * original value. + * + * @param rect the clipping rectangle or null + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setClipping (Rectangle rect) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Rectangle userClip = rect == null? null: new java.awt.Rectangle(rect.x, rect.y, rect.width, rect.height); + handle.setUserClip(userClip); +} + +/** + * Sets the area of the receiver which can be changed + * by drawing operations to the region specified + * by the argument. Specifying null for the + * region reverts the receiver's clipping area to its + * original value. + * + * @param region the clipping region or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the region has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setClipping (Region region) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.setUserClip(region.handle); +} + +/** + * Sets the receiver's fill rule to the parameter, which must be one of + * SWT.FILL_EVEN_ODD or SWT.FILL_WINDING. + * + * @param rule the new fill rule + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the rule is not one of SWT.FILL_EVEN_ODD + * or SWT.FILL_WINDING
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setFillRule(int rule) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + switch (rule) { + case SWT.FILL_WINDING: + case SWT.FILL_EVEN_ODD: + fillRule = rule; + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } +} + +/** + * Sets the font which will be used by the receiver + * to draw and measure text to the argument. If the + * argument is null, then a default font appropriate + * for the platform will be used instead. + * + * @param font the new font for the receiver, or null to indicate a default font + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the font has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setFont (Font font) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (font == null) { + handle.setFont(LookAndFeelUtils.getSystemFont()); + } else { + if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.setFont(font.handle); + } +} + +/** + * Sets the foreground color. The foreground color is used + * for drawing operations including when text is drawn. + * + * @param color the new foreground color for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the color is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the color has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setForeground (Color color) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + data.foreground = color.handle; + handle.setColor(color.handle); +} + +/** + * Sets the foreground pattern. The default value is null. + * + * @param pattern the new foreground pattern + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Pattern + * + * @since 3.1 + */ +public void setForegroundPattern (Pattern pattern) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + Utils.notImplemented(); +// if (data.gdipGraphics == 0 && pattern == null) return; +// initGdip(false, false); +// if (pattern != null) { +// if (data.gdipPen != 0) Gdip.Pen_SetBrush(data.gdipPen, pattern.handle); +// } else { +// if (data.gdipPen != 0) { +// Gdip.Pen_delete(data.gdipPen); +// data.gdipPen = 0; +// } +// } + data.foregroundPattern = pattern; +} + +/** + * Sets the receiver's interpolation setting to the parameter, which + * must be one of SWT.DEFAULT, SWT.NONE, + * SWT.LOW or SWT.HIGH. + * + * @param interpolation the new interpolation setting + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the rule is not one of SWT.DEFAULT, + * SWT.NONE, SWT.LOW or SWT.HIGH + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setInterpolation(int interpolation) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + Utils.notImplemented(); +// if (data.gdipGraphics == 0 && interpolation == SWT.DEFAULT) return; +// int mode = 0; +// switch (interpolation) { +// case SWT.DEFAULT: mode = Gdip.InterpolationModeDefault; break; +// case SWT.NONE: mode = Gdip.InterpolationModeNearestNeighbor; break; +// case SWT.LOW: mode = Gdip.InterpolationModeLowQuality; break; +// case SWT.HIGH: mode = Gdip.InterpolationModeHighQuality; break; +// default: +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// } +// initGdip(false, false); +// Gdip.Graphics_SetInterpolationMode(data.gdipGraphics, mode); +} + +/** + * Sets the receiver's line cap style to the argument, which must be one + * of the constants SWT.CAP_FLAT, SWT.CAP_ROUND, + * or SWT.CAP_SQUARE. + * + * @param cap the cap style to be used for drawing lines + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the style is not valid
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setLineCap(int cap) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BasicStroke stroke = getCurrentBasicStroke(); + int capStyle = 0; + switch (cap) { + case SWT.CAP_ROUND: + capStyle = BasicStroke.CAP_ROUND; + break; + case SWT.CAP_FLAT: + capStyle = BasicStroke.CAP_BUTT; + break; + case SWT.CAP_SQUARE: + capStyle = BasicStroke.CAP_SQUARE; + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + handle.setStroke(new BasicStroke(stroke.getLineWidth(), capStyle, stroke.getLineJoin(), stroke.getMiterLimit(), stroke.getDashArray(), 0)); +} + +/** + * Sets the receiver's line dash style to the argument. The default + * value is null. If the argument is not null, + * the receiver's line style is set to SWT.LINE_CUSTOM, otherwise + * it is set to SWT.LINE_SOLID. + * + * @param dashes the dash style to be used for drawing lines + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if any of the values in the array is less than or equal 0
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setLineDash(int[] dashes) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BasicStroke stroke = getCurrentBasicStroke(); + if(dashes == null) dashes = new int[0]; + data.dashes = new float[dashes.length]; + for(int i=0; iSWT.JOIN_MITER, SWT.JOIN_ROUND, + * or SWT.JOIN_BEVEL. + * + * @param join the join style to be used for drawing lines + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the style is not valid
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void setLineJoin(int join) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BasicStroke stroke = getCurrentBasicStroke(); + int joinStyle = 0; + switch (join) { + case SWT.JOIN_MITER: + joinStyle = BasicStroke.JOIN_MITER; + break; + case SWT.JOIN_ROUND: + joinStyle = BasicStroke.JOIN_ROUND; + break; + case SWT.JOIN_BEVEL: + joinStyle = BasicStroke.JOIN_BEVEL; + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + handle.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), joinStyle, stroke.getMiterLimit(), stroke.getDashArray(), 0)); +} + +/** + * Sets the receiver's line style to the argument, which must be one + * of the constants SWT.LINE_SOLID, SWT.LINE_DASH, + * SWT.LINE_DOT, SWT.LINE_DASHDOT or + * SWT.LINE_DASHDOTDOT. + * + * @param lineStyle the style to be used for drawing lines + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the style is not valid
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setLineStyle(int lineStyle) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BasicStroke stroke = getCurrentBasicStroke(); + float[] array = null; + switch(lineStyle) { + case SWT.LINE_SOLID: + break; + case SWT.LINE_DASH: + array = lineDashArray; + break; + case SWT.LINE_DOT: + array = lineDotArray; + break; + case SWT.LINE_DASHDOT: + array = lineDashDotArray; + break; + case SWT.LINE_DASHDOTDOT: + array = lineDashDotDotArray; + break; + case SWT.LINE_CUSTOM: + array = data.dashes; + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + handle.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), array, 0)); +} + +/** + * Sets the width that will be used when drawing lines + * for all of the figure drawing operations (that is, + * drawLine, drawRectangle, + * drawPolyline, and so forth. + *

    + * Note that line width of zero is used as a hint to + * indicate that the fastest possible line drawing + * algorithms should be used. This means that the + * output may be different from line width one. + *

    + * + * @param lineWidth the width of a line + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setLineWidth(int lineWidth) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BasicStroke stroke = getCurrentBasicStroke(); + handle.setStroke(new BasicStroke(lineWidth, stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), stroke.getDashArray(), stroke.getDashPhase())); +} + +//void setPen(int newColor, int newWidth, int lineStyle, int capStyle, int joinStyle, int[] dashes) { +// boolean extPen = false, changed = false; +// int style, color, width, size, hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN); +// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) { +// LOGPEN logPen = new LOGPEN(); +// OS.GetObject(hPen, LOGPEN.sizeof, logPen); +// color = logPen.lopnColor; +// width = logPen.x; +// style = logPen.lopnStyle; +// /* +// * Feature in Windows. The default end caps is PS_ENDCAP_ROUND +// * and the default line join is PS_JOIN_ROUND which are different +// * from other platforms. The fix is to change these values when +// * line width is widened. +// */ +// if (width <= 1 && (newWidth > 1 || lineStyle == OS.PS_USERSTYLE)) { +// if (capStyle == -1) capStyle = OS.PS_ENDCAP_FLAT; +// if (joinStyle == -1) joinStyle = OS.PS_JOIN_MITER; +// } +// } else { +// EXTLOGPEN logPen = new EXTLOGPEN(); +// if (size <= EXTLOGPEN.sizeof) { +// OS.GetObject(hPen, size, logPen); +// } else { +// int hHeap = OS.GetProcessHeap(); +// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size); +// OS.GetObject(hPen, size, ptr); +// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof); +// OS.HeapFree(hHeap, 0, ptr); +// } +// color = logPen.elpColor; +// width = logPen.elpWidth; +// style = logPen.elpPenStyle; +// extPen = true; +// if (newWidth == 0 || newWidth == 1) { +// if (dashes == null && (style & OS.PS_ENDCAP_MASK) == OS.PS_ENDCAP_FLAT && (style & OS.PS_JOIN_MASK) == OS.PS_JOIN_MITER) { +// style &= ~(OS.PS_ENDCAP_MASK | OS.PS_JOIN_MASK | OS.PS_TYPE_MASK); +// extPen = false; +// } +// } +// } +// if (newColor != -1) { +// if (newColor != color) { +// color = newColor; +// changed = true; +// } +// } +// if (newWidth != -1) { +// if (newWidth != width) { +// width = newWidth; +// changed = true; +// } +// } +// if (lineStyle != -1) { +// if ((style & OS.PS_STYLE_MASK) != lineStyle || (style & OS.PS_STYLE_MASK) == OS.PS_USERSTYLE) { +// style = (style & ~OS.PS_STYLE_MASK) | lineStyle; +// changed = true; +// } +// } +// if (capStyle != -1) { +// if ((style & OS.PS_ENDCAP_MASK) != capStyle) { +// style = (style & ~OS.PS_ENDCAP_MASK) | capStyle; +// changed = true; +// } +// } +// if (joinStyle != -1) { +// if ((style & OS.PS_JOIN_MASK) != joinStyle) { +// style = (style & ~OS.PS_JOIN_MASK) | joinStyle; +// changed = true; +// } +// } +// if (!changed) return; +// if ((style & OS.PS_STYLE_MASK) != OS.PS_USERSTYLE) dashes = null; +// /* +// * Feature in Windows. Windows does not honour line styles other then +// * PS_SOLID for pens wider than 1 pixel created with CreatePen(). The fix +// * is to use ExtCreatePen() instead. +// */ +// int newPen; +// if (!OS.IsWinCE && (extPen || width > 1 || (style & OS.PS_STYLE_MASK) == OS.PS_USERSTYLE)) { +// LOGBRUSH logBrush = new LOGBRUSH(); +// logBrush.lbStyle = OS.BS_SOLID; +// logBrush.lbColor = color; +// /* Feature in Windows. PS_GEOMETRIC pens cannot have zero width. */ +// newPen = OS.ExtCreatePen (style | OS.PS_GEOMETRIC, Math.max(1, width), logBrush, dashes != null ? dashes.length : 0, dashes); +// } else { +// newPen = OS.CreatePen(style, width, color); +// } +// OS.SelectObject(handle, newPen); +// if (data.hPen != 0) OS.DeleteObject(data.hPen); +// data.hPen = newPen; +// data.lineWidth = width; +// if (data.gdipPen != 0) { +// Gdip.Pen_delete(data.gdipPen); +// data.gdipPen = 0; +// } +//} + +/** + * If the argument is true, puts the receiver + * in a drawing mode where the resulting color in the destination + * is the exclusive or of the color values in the source + * and the destination, and if the argument is false, + * puts the receiver in a drawing mode where the destination color + * is replaced with the source color value. + *

    + * Note that this mode in fundamentally unsupportable on certain + * platforms, notably Carbon (Mac OS X). Clients that want their + * code to run on all platforms need to avoid this method. + *

    + * + * @param xor if true, then xor mode is used, otherwise source copy mode is used + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @deprecated this functionality is not supported on some platforms + */ +public void setXORMode(boolean xor) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if(xor) { + // need to check if "handle.setXORMode(getBackground().handle)" must be called any time the background color changes. + handle.setXORMode(getBackground().handle); + } else { + handle.setPaintMode(); + } + isXORMode = xor; +} + +/** + * Sets the receiver's text anti-aliasing value to the parameter, + * which must be one of SWT.DEFAULT, SWT.OFF + * or SWT.ON. Note that this controls anti-aliasing only + * for all text drawing operations. + * + * @param antialias the anti-aliasing setting + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parameter is not one of SWT.DEFAULT, + * SWT.OFF or SWT.ON
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setAntialias + * + * @since 3.1 + */ +public void setTextAntialias(int antialias) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + switch (antialias) { + case SWT.DEFAULT: + handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + break; + case SWT.OFF: + handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + break; + case SWT.ON: + handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + break; + default: + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } +} + +/** + * Sets the transform that is currently being used by the receiver. If + * the argument is null, the current transform is set to + * the identity transform. + * + * @param transform the transform to set + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Transform + * + * @since 3.1 + */ +public void setTransform(Transform transform) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (saveAT == null) { + saveAT = handle.getTransform(); + } else { + handle.setTransform(saveAT); + } + AffineTransform at; + if (transform == null) { + at = new AffineTransform(); + gcAT = null; + } else { + at = transform.handle; + gcAT = at; + } + handle.transform(at); +} + +/** + * Returns the extent of the given string. No tab + * expansion or carriage return processing will be performed. + *

    + * The extent of a string is the width and height of + * the rectangular area it would cover if drawn in a particular + * font (in this case, the current font in the receiver). + *

    + * + * @param string the string to measure + * @return a point containing the extent of the string + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Point stringExtent(String string) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return textExtent(string, 0); +// java.awt.FontMetrics fm = handle.getFontMetrics(); +// // TODO: check why the StyledText queries the stringExtent and this is null sometimes (cf RSSOwl) +// if(fm == null) return new Point(0, 0); +// return new Point(fm.stringWidth(string), fm.getMaxAscent() + fm.getMaxDescent()); +} + +/** + * Returns the extent of the given string. Tab expansion and + * carriage return processing are performed. + *

    + * The extent of a string is the width and height of + * the rectangular area it would cover if drawn in a particular + * font (in this case, the current font in the receiver). + *

    + * + * @param string the string to measure + * @return a point containing the extent of the string + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Point textExtent(String string) { + return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB); +} + +/** + * Returns the extent of the given string. Tab expansion, line + * delimiter and mnemonic processing are performed according to + * the specified flags, which can be a combination of: + *
    + *
    DRAW_DELIMITER
    + *
    draw multiple lines
    + *
    DRAW_TAB
    + *
    expand tabs
    + *
    DRAW_MNEMONIC
    + *
    underline the mnemonic character
    + *
    DRAW_TRANSPARENT
    + *
    transparent background
    + *
    + *

    + * The extent of a string is the width and height of + * the rectangular area it would cover if drawn in a particular + * font (in this case, the current font in the receiver). + *

    + * + * @param string the string to measure + * @param flags the flags specifing how to process the text + * @return a point containing the extent of the string + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Point textExtent(String string, int flags) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if((flags & SWT.DRAW_TAB) != 0) { + string = string.replaceAll("\t", " "); + } + int mnemonicIndex = -1; + if((flags & SWT.DRAW_MNEMONIC) != 0) { + // Copied from Label + mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); + mnemonicIndex -= mnemonicIndex - 1 - s.length(); + mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + } + String[] tokens; + if((flags & SWT.DRAW_DELIMITER) != 0) { + tokens = string.split("\n"); + } else { + tokens = new String[] {string}; + } +// boolean isTransparent = (flags & SWT.DRAW_TRANSPARENT) != 0; + java.awt.FontMetrics fm = handle.getFontMetrics(); + int fmHeight = fm.getHeight(); + int currentHeight = fmHeight; + int maxWidth = 0; + int maxHeight = 0; + FontRenderContext fontRenderContext = handle.getFontRenderContext(); + java.awt.Font font = handle.getFont(); + for(int i=0; i + * IMPORTANT: This method is not part of the public + * API for GC. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param drawable the Drawable for the receiver. + * @param data the data for the receiver. + * + * @return a new GC + */ +public static GC swing_new(Drawable drawable, GCData data) { + GC gc = new GC(); + CGC handle = drawable.internal_new_GC(data); + gc.init(drawable, data, handle); + return gc; +} + +/** + * Invokes platform specific functionality to wrap a graphics context. + *

    + * IMPORTANT: This method is not part of the public + * API for GC. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param hDC the Windows HDC. + * @param data the data for the receiver. + * + * @return a new GC + */ +public static GC swing_new(CGC handle, GCData data) { + GC gc = new GC(); + gc.init(null, data, handle); + return gc; +} + +static final float[] lineDashArray = new float[] {18, 6}; +static final float[] lineDotArray = new float[] {3, 3}; +static final float[] lineDashDotArray = new float[] {9, 6, 3, 6}; +static final float[] lineDashDotDotArray = new float[] {9, 3, 3, 3, 3, 3}; + +BasicStroke getCurrentBasicStroke() { + Stroke stroke = handle.getStroke(); + if(stroke instanceof BasicStroke) { + return (BasicStroke)stroke; + } + return new BasicStroke(); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java new file mode 100644 index 00000000000..eeba6b8adfb --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.Component; + +/** + * Instances of this class are descriptions of GCs in terms + * of unallocated platform-specific data fields. + *

    + * IMPORTANT: This class is not part of the public + * API for SWT. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms, and should never be called from application code. + *

    + */ + +public final class GCData { + public Device device; + public int style; + public Image image; + public java.awt.Color foreground = java.awt.Color.BLACK; + public java.awt.Color background = java.awt.Color.BLACK; + public int hPen; + public int lineWidth; + public float[] dashes; + public int hBrush; + public java.awt.Font hFont; + public int hNullBitmap; + public Component hwnd; + public boolean layout = true; + public int alpha = 0xFF; + public boolean advanced; +// public int gdipGraphics; + public int gdipPen; + public int gdipBrush; + public Pattern foregroundPattern; + public Pattern backgroundPattern; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java new file mode 100644 index 00000000000..cc234a7aa8e --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java @@ -0,0 +1,1867 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.*; +import java.awt.image.*; +import java.io.*; + +import javax.swing.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.internal.DPIUtil.*; +import org.eclipse.swt.internal.swing.*; +import org.eclipse.swt.widgets.*; + +/** + * Instances of this class are graphics which have been prepared + * for display on a specific device. That is, they are ready + * to paint using methods such as GC.drawImage() + * and display on widgets with, for example, Button.setImage(). + *

    + * If loaded from a file format that supports it, an + * Image may have transparency, meaning that certain + * pixels are specified as being transparent when drawn. Examples + * of file formats that support transparency are GIF and PNG. + *

    + * There are two primary ways to use Images. + * The first is to load a graphic file from disk and create an + * Image from it. This is done using an Image + * constructor, for example: + *

    + *    Image i = new Image(device, "C:\\graphic.bmp");
    + * 
    + * A graphic file may contain a color table specifying which + * colors the image was intended to possess. In the above example, + * these colors will be mapped to the closest available color in + * SWT. It is possible to get more control over the mapping of + * colors as the image is being created, using code of the form: + *
    + *    ImageData data = new ImageData("C:\\graphic.bmp");
    + *    RGB[] rgbs = data.getRGBs();
    + *    // At this point, rgbs contains specifications of all
    + *    // the colors contained within this image. You may
    + *    // allocate as many of these colors as you wish by
    + *    // using the Color constructor Color(RGB), then
    + *    // create the image:
    + *    Image i = new Image(device, data);
    + * 
    + *

    + * Applications which require even greater control over the image + * loading process should use the support provided in class + * ImageLoader. + *

    + * Application code must explicitly invoke the Image.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @see Color + * @see ImageData + * @see ImageLoader + */ + +public final class Image extends Resource implements Drawable { + + /** + * specifies whether the receiver is a bitmap or an icon + * (one of SWT.BITMAP, SWT.ICON) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public int type; + + /** + * the handle to the OS image resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public BufferedImage handle; + +// /** +// * specifies the transparent pixel +// */ +// int transparentPixel = -1; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Image () { +} + +/** + * Constructs an empty instance of this class with the + * specified width and height. The result may be drawn upon + * by creating a GC and using any of its drawing operations, + * as shown in the following example: + *
    + *    Image i = new Image(device, width, height);
    + *    GC gc = new GC(i);
    + *    gc.drawRectangle(0, 0, 50, 50);
    + *    gc.dispose();
    + * 
    + *

    + * Note: Some platforms may have a limitation on the size + * of image that can be created (size depends on width, height, + * and depth). For example, Windows 95, 98, and ME do not allow + * images larger than 16M. + *

    + * + * @param device the device on which to create the image + * @param width the width of the new image + * @param height the height of the new image + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image(Device device, int width, int height) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, width, height); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new instance of this class based on the + * provided image, with an appearance that varies depending + * on the value of the flag. The possible flag values are: + *
    + *
    IMAGE_COPY
    + *
    the result is an identical copy of srcImage
    + *
    IMAGE_DISABLE
    + *
    the result is a copy of srcImage which has a disabled look
    + *
    IMAGE_GRAY
    + *
    the result is a copy of srcImage which has a gray scale look
    + *
    + * + * @param device the device on which to create the image + * @param srcImage the image to use as the source + * @param flag the style, either IMAGE_COPY, IMAGE_DISABLE or IMAGE_GRAY + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if srcImage is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the flag is not one of IMAGE_COPY, IMAGE_DISABLE or IMAGE_GRAY
    • + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state
    • + *
    • ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image(Device device, Image srcImage, int flag) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + switch (flag) { + case SWT.IMAGE_COPY: { + handle = new BufferedImage(srcImage.handle.getWidth(), srcImage.handle.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = handle.getGraphics(); + g.drawImage(srcImage.handle, 0, 0, null); + g.dispose(); + if (device.tracking) device.new_Object(this); + return; + } + case SWT.IMAGE_DISABLE: + case SWT.IMAGE_GRAY: { + // TODO: test the method below and see if results are different. If so, associate each method to a different case. +// ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); +// ColorConvertOp op = new ColorConvertOp(cs, null); +// bufferedImage = op.filter(bufferedImage, null); + // ImageIcon is used to ensure that the image is loaded + java.awt.Image image = new ImageIcon(GrayFilter.createDisabledImage(srcImage.handle)).getImage(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gs = ge.getDefaultScreenDevice(); + GraphicsConfiguration gc = gs.getDefaultConfiguration(); + handle = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), srcImage.handle.getColorModel().getTransparency()); + Graphics g = handle.createGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); +// init (device, newData); + if (device.tracking) device.new_Object(this); + return; + } + default: + SWT.error(SWT.ERROR_INVALID_IMAGE); + } + // TODO: Set image data? +} + +/** + * Constructs an empty instance of this class with the + * width and height of the specified rectangle. The result + * may be drawn upon by creating a GC and using any of its + * drawing operations, as shown in the following example: + *
    + *    Image i = new Image(device, boundsRectangle);
    + *    GC gc = new GC(i);
    + *    gc.drawRectangle(0, 0, 50, 50);
    + *    gc.dispose();
    + * 
    + *

    + * Note: Some platforms may have a limitation on the size + * of image that can be created (size depends on width, height, + * and depth). For example, Windows 95, 98, and ME do not allow + * images larger than 16M. + *

    + * + * @param device the device on which to create the image + * @param bounds a rectangle specifying the image's width and height (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the bounds rectangle is null
    • + *
    • ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image(Device device, Rectangle bounds) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, bounds.width, bounds.height); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs an instance of this class from the given + * ImageData. + * + * @param device the device on which to create the image + * @param data the image data to create the image from (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the image data is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image(Device device, ImageData data) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, data); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs an instance of this class, whose type is + * SWT.ICON, from the two given ImageData + * objects. The two images must be the same size. Pixel transparency + * in either image will be ignored. + *

    + * The mask image should contain white wherever the icon is to be visible, + * and black wherever the icon is to be transparent. In addition, + * the source image should contain black wherever the icon is to be + * transparent. + *

    + * + * @param device the device on which to create the icon + * @param source the color data for the icon + * @param mask the mask data for the icon + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if either the source or mask is null
    • + *
    • ERROR_INVALID_ARGUMENT - if source and mask are different sizes
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image(Device device, ImageData source, ImageData mask) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (source.width != mask.width || source.height != mask.height) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + mask = ImageData.convertMask(mask); + init(device, this, source, mask); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs an instance of this class by loading its representation + * from the specified input stream. Throws an error if an error + * occurs while loading the image, or if the result is an image + * of an unsupported type. Application code is still responsible + * for closing the input stream. + *

    + * This constructor is provided for convenience when loading a single + * image only. If the stream contains multiple images, only the first + * one will be loaded. To load multiple images, use + * ImageLoader.load(). + *

    + * This constructor may be used to load a resource as follows: + *

    + *
    + *     static Image loadImage (Display display, Class clazz, String string) {
    + *          InputStream stream = clazz.getResourceAsStream (string);
    + *          if (stream == null) return null;
    + *          Image image = null;
    + *          try {
    + *               image = new Image (display, stream);
    + *          } catch (SWTException ex) {
    + *          } finally {
    + *               try {
    + *                    stream.close ();
    + *               } catch (IOException ex) {}
    + *          }
    + *          return image;
    + *     }
    + * 
    + * + * @param device the device on which to create the image + * @param stream the input stream to load the image from + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the stream is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while reading from the stream
    • + *
    • ERROR_INVALID_IMAGE - if the image stream contains invalid data
    • + *
    • ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image (Device device, InputStream stream) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, new ImageData(stream)); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs an instance of this class by loading its representation + * from the file with the specified name. Throws an error if an error + * occurs while loading the image, or if the result is an image + * of an unsupported type. + *

    + * This constructor is provided for convenience when loading + * a single image only. If the specified file contains + * multiple images, only the first one will be used. + * + * @param device the device on which to create the image + * @param filename the name of the file to load the image from + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the file name is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while reading from the file
    • + *
    • ERROR_INVALID_IMAGE - if the image file contains invalid data
    • + *
    • ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for image creation
    • + *
    + */ +public Image (Device device, String filename) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, new ImageData(filename)); + if (device.tracking) device.new_Object(this); +} + +///** +// * Create a DIB from a DDB without using GetDIBits. Note that +// * the DDB should not be selected into a HDC. +// */ +//int createDIBFromDDB(int hDC, int hBitmap, int width, int height) { +// +// /* Determine the DDB depth */ +// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL); +// int planes = OS.GetDeviceCaps (hDC, OS.PLANES); +// int depth = bits * planes; +// +// /* Determine the DIB palette */ +// boolean isDirect = depth > 8; +// RGB[] rgbs = null; +// if (!isDirect) { +// int numColors = 1 << depth; +// byte[] logPalette = new byte[4 * numColors]; +// OS.GetPaletteEntries(device.hPalette, 0, numColors, logPalette); +// rgbs = new RGB[numColors]; +// for (int i = 0; i < numColors; i++) { +// rgbs[i] = new RGB(logPalette[i] & 0xFF, logPalette[i + 1] & 0xFF, logPalette[i + 2] & 0xFF); +// } +// } +// +// boolean useBitfields = OS.IsWinCE && (depth == 16 || depth == 32); +// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = width; +// bmiHeader.biHeight = -height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = (short)depth; +// if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS; +// else bmiHeader.biCompression = OS.BI_RGB; +// byte[] bmi; +// if (isDirect) bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)]; +// else bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// +// /* Set the rgb colors into the bitmap info */ +// int offset = BITMAPINFOHEADER.sizeof; +// if (isDirect) { +// if (useBitfields) { +// int redMask = 0; +// int greenMask = 0; +// int blueMask = 0; +// switch (depth) { +// case 16: +// redMask = 0x7C00; +// greenMask = 0x3E0; +// blueMask = 0x1F; +// /* little endian */ +// bmi[offset] = (byte)((redMask & 0xFF) >> 0); +// bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8); +// bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16); +// bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24); +// bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0); +// bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8); +// bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16); +// bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24); +// bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0); +// bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8); +// bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16); +// bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24); +// break; +// case 32: +// redMask = 0xFF00; +// greenMask = 0xFF0000; +// blueMask = 0xFF000000; +// /* big endian */ +// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24); +// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16); +// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8); +// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0); +// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24); +// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16); +// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8); +// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0); +// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24); +// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16); +// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8); +// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0); +// break; +// default: +// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); +// } +// } +// } else { +// for (int j = 0; j < rgbs.length; j++) { +// bmi[offset] = (byte)rgbs[j].blue; +// bmi[offset + 1] = (byte)rgbs[j].green; +// bmi[offset + 2] = (byte)rgbs[j].red; +// bmi[offset + 3] = 0; +// offset += 4; +// } +// } +// int[] pBits = new int[1]; +// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0); +// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// +// /* Bitblt DDB into DIB */ +// int hdcSource = OS.CreateCompatibleDC(hDC); +// int hdcDest = OS.CreateCompatibleDC(hDC); +// int hOldSrc = OS.SelectObject(hdcSource, hBitmap); +// int hOldDest = OS.SelectObject(hdcDest, hDib); +// OS.BitBlt(hdcDest, 0, 0, width, height, hdcSource, 0, 0, OS.SRCCOPY); +// OS.SelectObject(hdcSource, hOldSrc); +// OS.SelectObject(hdcDest, hOldDest); +// OS.DeleteDC(hdcSource); +// OS.DeleteDC(hdcDest); +// +// return hDib; +//} + +public Image(Display display, AutoScaleImageDataProvider autoScaleImageDataProvider) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +public Image(Device device, ImageDataProvider imageDataProvider) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +/** + * Disposes of the operating system resources associated with + * the image. Applications must dispose of all images which + * they allocate. + */ +@Override +public void dispose () { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +@Override +public boolean equals (Object object) { + if (object == this) return true; + if (!(object instanceof Image)) return false; + Image image = (Image) object; + return device == image.device && handle == image.handle; +} + +/** + * Returns the color to which to map the transparent pixel, or null if + * the receiver has no transparent pixel. + *

    + * There are certain uses of Images that do not support transparency + * (for example, setting an image into a button or label). In these cases, + * it may be desired to simulate transparency by using the background + * color of the widget to paint the transparent pixels of the image. + * Use this method to check which color will be used in these cases + * in place of transparency. This value may be set with setBackground(). + *

    + * + * @return the background color of the image, or null if there is no transparency in the image + * + * @exception SWTException

      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Color getBackground() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + // TODO: see setBackground... + return null; +// if (transparentPixel == -1) return null; +// +// /* Get the HDC for the device */ +// int hDC = device.internal_new_GC(null); +// +// /* Compute the background color */ +// BITMAP bm = new BITMAP(); +// OS.GetObject(handle, BITMAP.sizeof, bm); +// int hdcMem = OS.CreateCompatibleDC(hDC); +// int hOldObject = OS.SelectObject(hdcMem, handle); +// int red = 0, green = 0, blue = 0; +// if (bm.bmBitsPixel <= 8) { +// if (OS.IsWinCE) { +// byte[] pBits = new byte[1]; +// OS.MoveMemory(pBits, bm.bmBits, 1); +// byte oldValue = pBits[0]; +// int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF; +// pBits[0] = (byte)((transparentPixel << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask)); +// OS.MoveMemory(bm.bmBits, pBits, 1); +// int color = OS.GetPixel(hdcMem, 0, 0); +// pBits[0] = oldValue; +// OS.MoveMemory(bm.bmBits, pBits, 1); +// blue = (color & 0xFF0000) >> 16; +// green = (color & 0xFF00) >> 8; +// red = color & 0xFF; +// } else { +// byte[] color = new byte[4]; +// OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color); +// blue = color[0] & 0xFF; +// green = color[1] & 0xFF; +// red = color[2] & 0xFF; +// } +// } else { +// switch (bm.bmBitsPixel) { +// case 16: +// blue = (transparentPixel & 0x1F) << 3; +// green = (transparentPixel & 0x3E0) >> 2; +// red = (transparentPixel & 0x7C00) >> 7; +// break; +// case 24: +// blue = (transparentPixel & 0xFF0000) >> 16; +// green = (transparentPixel & 0xFF00) >> 8; +// red = transparentPixel & 0xFF; +// break; +// case 32: +// blue = (transparentPixel & 0xFF000000) >>> 24; +// green = (transparentPixel & 0xFF0000) >> 16; +// red = (transparentPixel & 0xFF00) >> 8; +// break; +// default: +// return null; +// } +// } +// OS.SelectObject(hdcMem, hOldObject); +// OS.DeleteDC(hdcMem); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +// return Color.win32_new(device, 0x02000000 | (blue << 16) | (green << 8) | red); +} + +/** + * Returns the bounds of the receiver. The rectangle will always + * have x and y values of 0, and the width and height of the + * image. + * + * @return a rectangle specifying the image's bounds + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
    • + *
    + */ +public Rectangle getBounds() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return new Rectangle(0, 0, handle.getWidth(), handle.getHeight()); +} + +/** + * Returns an ImageData based on the receiver + * Modifications made to this ImageData will not + * affect the Image. + * + * @return an ImageData containing the image's data and attributes + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
    • + *
    + * + * @see ImageData + */ +public ImageData getImageData() { + ColorModel colorModel = handle.getColorModel(); + PaletteData paletteData = new PaletteData(0xFF0000, 0xFF00, 0xFF); + int width = handle.getWidth(); + ImageData imageData = new ImageData(width, handle.getHeight(), colorModel.getPixelSize(), paletteData); + int height = handle.getHeight(); + byte[] maskData = new byte[(width + 7) / 8 * height]; + for(int x=width-1; x >= 0; x--) { + for(int y=height-1; y >= 0; y--) { + int rgb = handle.getRGB(x, y); + int pixel = paletteData.getPixel(new RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF)); + imageData.setPixel(x, y, pixel); + int alpha = (rgb >> 24) & 0xFF; + imageData.setAlpha(x, y, alpha); + if(alpha != 0) { + int index = x + y * ((width + 7) / 8) * 8; + maskData[index / 8] |= (byte)(1 << (7 - (index % 8))); + } + } + } + imageData.maskPad = 1; + imageData.maskData = maskData; +// ByteArrayOutputStream baos = new ByteArrayOutputStream(); +// ImageWriter writer = (ImageWriter)ImageIO.getImageWritersBySuffix("jpg").next(); +// try { +// writer.setOutput(ImageIO.createImageOutputStream(baos)); +// writer.write(handle); +// return new ImageData(new ByteArrayInputStream(baos.toByteArray())); +// } catch(Exception e) { +// e.printStackTrace(); +// } + return imageData; +// if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); +// BITMAP bm; +// int depth, width, height; +// switch (type) { +// case SWT.ICON: { +// if (OS.IsWinCE) return data; +// ICONINFO info = new ICONINFO(); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetIconInfo(handle, info); +// /* Get the basic BITMAP information */ +// int hBitmap = info.hbmColor; +// if (hBitmap == 0) hBitmap = info.hbmMask; +// bm = new BITMAP(); +// OS.GetObject(hBitmap, BITMAP.sizeof, bm); +// depth = bm.bmPlanes * bm.bmBitsPixel; +// width = bm.bmWidth; +// if (hBitmap == info.hbmMask) bm.bmHeight /= 2; +// height = bm.bmHeight; +// int numColors = 0; +// if (depth <= 8) numColors = 1 << depth; +// /* Create the BITMAPINFO */ +// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = width; +// bmiHeader.biHeight = -height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = (short)depth; +// bmiHeader.biCompression = OS.BI_RGB; +// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// +// /* Get the HDC for the device */ +// int hDC = device.internal_new_GC(null); +// +// /* Create the DC and select the bitmap */ +// int hBitmapDC = OS.CreateCompatibleDC(hDC); +// int hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap); +// /* Select the palette if necessary */ +// int oldPalette = 0; +// if (depth <= 8) { +// int hPalette = device.hPalette; +// if (hPalette != 0) { +// oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false); +// OS.RealizePalette(hBitmapDC); +// } +// } +// /* Find the size of the image and allocate data */ +// int imageSize; +// /* Call with null lpBits to get the image size */ +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, hBitmap, 0, height, 0, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); +// imageSize = bmiHeader.biSizeImage; +// byte[] data = new byte[imageSize]; +// /* Get the bitmap data */ +// int hHeap = OS.GetProcessHeap(); +// int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, hBitmap, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(data, lpvBits, imageSize); +// /* Calculate the palette */ +// PaletteData palette = null; +// if (depth <= 8) { +// RGB[] rgbs = new RGB[numColors]; +// int srcIndex = 40; +// for (int i = 0; i < numColors; i++) { +// rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); +// srcIndex += 4; +// } +// palette = new PaletteData(rgbs); +// } else if (depth == 16) { +// palette = new PaletteData(0x7C00, 0x3E0, 0x1F); +// } else if (depth == 24) { +// palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); +// } else if (depth == 32) { +// palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); +// } else { +// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); +// } +// +// /* Do the mask */ +// byte [] maskData = null; +// if (info.hbmColor == 0) { +// /* Do the bottom half of the mask */ +// maskData = new byte[imageSize]; +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, hBitmap, height, height, lpvBits, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(maskData, lpvBits, imageSize); +// } else { +// /* Do the entire mask */ +// /* Create the BITMAPINFO */ +// bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = width; +// bmiHeader.biHeight = -height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = 1; +// bmiHeader.biCompression = OS.BI_RGB; +// bmi = new byte[BITMAPINFOHEADER.sizeof + 8]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// +// /* First color black, second color white */ +// int offset = BITMAPINFOHEADER.sizeof; +// bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF; +// bmi[offset + 7] = 0; +// OS.SelectObject(hBitmapDC, info.hbmMask); +// /* Call with null lpBits to get the image size */ +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, 0, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); +// imageSize = bmiHeader.biSizeImage; +// maskData = new byte[imageSize]; +// int lpvMaskBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, lpvMaskBits, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(maskData, lpvMaskBits, imageSize); +// OS.HeapFree(hHeap, 0, lpvMaskBits); +// /* Loop to invert the mask */ +// for (int i = 0; i < maskData.length; i++) { +// maskData[i] ^= -1; +// } +// /* Make sure mask scanlinePad is 2 */ +// int maskPad; +// int bpl = imageSize / height; +// for (maskPad = 1; maskPad < 128; maskPad++) { +// int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; +// if (calcBpl == bpl) break; +// } +// maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2); +// } +// /* Clean up */ +// OS.HeapFree(hHeap, 0, lpvBits); +// OS.SelectObject(hBitmapDC, hOldBitmap); +// if (oldPalette != 0) { +// OS.SelectPalette(hBitmapDC, oldPalette, false); +// OS.RealizePalette(hBitmapDC); +// } +// OS.DeleteDC(hBitmapDC); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +// +// if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor); +// if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask); +// /* Construct and return the ImageData */ +// ImageData imageData = new ImageData(width, height, depth, palette, 4, data); +// imageData.maskData = maskData; +// imageData.maskPad = 2; +// return imageData; +// } +// case SWT.BITMAP: { +// /* Get the basic BITMAP information */ +// bm = new BITMAP(); +// OS.GetObject(handle, BITMAP.sizeof, bm); +// depth = bm.bmPlanes * bm.bmBitsPixel; +// width = bm.bmWidth; +// height = bm.bmHeight; +// /* Find out whether this is a DIB or a DDB. */ +// boolean isDib = (bm.bmBits != 0); +// /* Get the HDC for the device */ +// int hDC = device.internal_new_GC(null); +// +// /* +// * Feature in WinCE. GetDIBits is not available in WinCE. The +// * workaround is to create a temporary DIB from the DDB and use +// * the bmBits field of DIBSECTION to retrieve the image data. +// */ +// int handle = this.handle; +// if (OS.IsWinCE) { +// if (!isDib) { +// boolean mustRestore = false; +// if (memGC != null && !memGC.isDisposed()) { +// mustRestore = true; +// GCData data = memGC.data; +// if (data.hNullBitmap != 0) { +// OS.SelectObject(memGC.handle, data.hNullBitmap); +// data.hNullBitmap = 0; +// } +// } +// handle = createDIBFromDDB(hDC, this.handle, width, height); +// if (mustRestore) { +// int hOldBitmap = OS.SelectObject(memGC.handle, this.handle); +// memGC.data.hNullBitmap = hOldBitmap; +// } +// isDib = true; +// } +// } +// DIBSECTION dib = null; +// if (isDib) { +// dib = new DIBSECTION(); +// OS.GetObject(handle, DIBSECTION.sizeof, dib); +// } +// /* Calculate number of colors */ +// int numColors = 0; +// if (depth <= 8) { +// if (isDib) { +// numColors = dib.biClrUsed; +// } else { +// numColors = 1 << depth; +// } +// } +// /* Create the BITMAPINFO */ +// byte[] bmi = null; +// BITMAPINFOHEADER bmiHeader = null; +// if (!isDib) { +// bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = width; +// bmiHeader.biHeight = -height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = (short)depth; +// bmiHeader.biCompression = OS.BI_RGB; +// bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// } +// +// /* Create the DC and select the bitmap */ +// int hBitmapDC = OS.CreateCompatibleDC(hDC); +// int hOldBitmap = OS.SelectObject(hBitmapDC, handle); +// /* Select the palette if necessary */ +// int oldPalette = 0; +// if (!isDib && depth <= 8) { +// int hPalette = device.hPalette; +// if (hPalette != 0) { +// oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false); +// OS.RealizePalette(hBitmapDC); +// } +// } +// /* Find the size of the image and allocate data */ +// int imageSize; +// if (isDib) { +// imageSize = dib.biSizeImage; +// } else { +// /* Call with null lpBits to get the image size */ +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, handle, 0, height, 0, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); +// imageSize = bmiHeader.biSizeImage; +// } +// byte[] data = new byte[imageSize]; +// /* Get the bitmap data */ +// if (isDib) { +// if (OS.IsWinCE && this.handle != handle) { +// /* get image data from the temporary DIB */ +// OS.MoveMemory(data, dib.bmBits, imageSize); +// } else { +// OS.MoveMemory(data, bm.bmBits, imageSize); +// } +// } else { +// int hHeap = OS.GetProcessHeap(); +// int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.GetDIBits(hBitmapDC, handle, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS); +// OS.MoveMemory(data, lpvBits, imageSize); +// OS.HeapFree(hHeap, 0, lpvBits); +// } +// /* Calculate the palette */ +// PaletteData palette = null; +// if (depth <= 8) { +// RGB[] rgbs = new RGB[numColors]; +// if (isDib) { +// if (OS.IsWinCE) { +// /* +// * Feature on WinCE. GetDIBColorTable is not supported. +// * The workaround is to set a pixel to the desired +// * palette index and use getPixel to get the corresponding +// * RGB value. +// */ +// int red = 0, green = 0, blue = 0; +// byte[] pBits = new byte[1]; +// OS.MoveMemory(pBits, bm.bmBits, 1); +// byte oldValue = pBits[0]; +// int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF; +// for (int i = 0; i < numColors; i++) { +// pBits[0] = (byte)((i << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask)); +// OS.MoveMemory(bm.bmBits, pBits, 1); +// int color = OS.GetPixel(hBitmapDC, 0, 0); +// blue = (color & 0xFF0000) >> 16; +// green = (color & 0xFF00) >> 8; +// red = color & 0xFF; +// rgbs[i] = new RGB(red, green, blue); +// } +// pBits[0] = oldValue; +// OS.MoveMemory(bm.bmBits, pBits, 1); +// } else { +// byte[] colors = new byte[numColors * 4]; +// OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors); +// int colorIndex = 0; +// for (int i = 0; i < rgbs.length; i++) { +// rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF); +// colorIndex += 4; +// } +// } +// } else { +// int srcIndex = BITMAPINFOHEADER.sizeof; +// for (int i = 0; i < numColors; i++) { +// rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); +// srcIndex += 4; +// } +// } +// palette = new PaletteData(rgbs); +// } else if (depth == 16) { +// palette = new PaletteData(0x7C00, 0x3E0, 0x1F); +// } else if (depth == 24) { +// palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); +// } else if (depth == 32) { +// palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); +// } else { +// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); +// } +// /* Clean up */ +// OS.SelectObject(hBitmapDC, hOldBitmap); +// if (oldPalette != 0) { +// OS.SelectPalette(hBitmapDC, oldPalette, false); +// OS.RealizePalette(hBitmapDC); +// } +// if (OS.IsWinCE) { +// if (handle != this.handle) { +// /* free temporary DIB */ +// OS.DeleteObject (handle); +// } +// } +// OS.DeleteDC(hBitmapDC); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +// +// /* Construct and return the ImageData */ +// ImageData imageData = new ImageData(width, height, depth, palette, 4, data); +// imageData.transparentPixel = this.transparentPixel; +// imageData.alpha = alpha; +// if (alpha == -1 && alphaData != null) { +// imageData.alphaData = new byte[alphaData.length]; +// System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length); +// } +// return imageData; +// } +// default: +// SWT.error(SWT.ERROR_INVALID_IMAGE); +// return null; +// } +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +@Override +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +void init(Device device, int width, int height) { + if (width <= 0 || height <= 0) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + this.device = device; + type = SWT.BITMAP; + handle = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + if(!(device instanceof Display)) { + Graphics g = handle.getGraphics(); + g.setColor(java.awt.Color.WHITE); + ((Graphics2D)g).setBackground(java.awt.Color.WHITE); + g.fillRect(0, 0, width, height); + } +} + +static void init(Device device, Image image, ImageData data) { +// BufferedImage bufferedImage; +// if (data.palette.isDirect) { +// bufferedImage = createBufferedImageDirectPalette(data, data.palette); +// } else { +// bufferedImage = createBufferedImageIndexPalette (data, data.palette); +// } +// image.handle = bufferedImage; +// image.device = null; +//// SImageData.serialize(image, data); +// if(true) return; + image.device = device; + if(image.handle == null) { + BufferedImage bufferedImage = new BufferedImage(data.width, data.height, BufferedImage.TYPE_INT_ARGB); + image.handle = bufferedImage; + if(!(device instanceof Display)) { + Graphics g = bufferedImage.getGraphics(); + g.setColor(java.awt.Color.WHITE); + ((Graphics2D)g).setBackground(java.awt.Color.WHITE); + g.fillRect(0, 0, data.width, data.height); + } + } + ImageData transparencyMask = data.getTransparencyMask(); + for(int x=image.handle.getWidth()-1; x >= 0; x--) { + for(int y=image.handle.getHeight()-1; y >= 0; y--) { + RGB rgb = data.palette.getRGB(data.getPixel(x, y)); + int pixel = rgb.red << 16 | rgb.green << 8 | rgb.blue; + rgb = transparencyMask.palette.getRGB(transparencyMask.getPixel(x, y)); + int mask = rgb.red << 16 | rgb.green << 8 | rgb.blue; + if(mask != 0) { + int alpha = data.getAlpha(x, y); + if(alpha > 0) { + pixel = pixel & 0x00FFFFFF | alpha << 24; + image.handle.setRGB(x, y, pixel); + } + } + } + } +// SImageData.serialize(image, data); +// /* +// * BUG in Windows 98: +// * A monochrome DIBSection will display as solid black +// * on Windows 98 machines, even though it contains the +// * correct data. The fix is to convert 1-bit ImageData +// * into 4-bit ImageData before creating the image. +// */ +// /* Windows does not support 2-bit images. Convert to 4-bit image. */ +// if ((i.depth == 1 && i.getTransparencyType() != SWT.TRANSPARENCY_MASK) || i.depth == 2) { +// ImageData img = new ImageData(i.width, i.height, 4, i.palette); +// ImageData.blit(ImageData.BLIT_SRC, +// i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, null, null, null, +// ImageData.ALPHA_OPAQUE, null, 0, 0, 0, +// img.data, img.depth, img.bytesPerLine, i.getByteOrder(), 0, 0, img.width, img.height, null, null, null, +// false, false); +// img.transparentPixel = i.transparentPixel; +// img.maskPad = i.maskPad; +// img.maskData = i.maskData; +// img.alpha = i.alpha; +// img.alphaData = i.alphaData; +// i = img; +// } +// /* +// * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F), +// * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask +// * (0x00FF0000, 0x0000FF00, 0x000000FF) as documented in +// * MSDN BITMAPINFOHEADER. Make sure the image is +// * Windows-supported. +// */ +// /* +// * Note on WinCE. CreateDIBSection requires the biCompression +// * field of the BITMAPINFOHEADER to be set to BI_BITFIELDS for +// * 16 and 32 bit direct images (see MSDN for CreateDIBSection). +// * In this case, the color mask can be set to any value. For +// * consistency, it is set to the same mask used by non WinCE +// * platforms in BI_RGB mode. +// */ +// if (i.palette.isDirect) { +// final PaletteData palette = i.palette; +// final int redMask = palette.redMask; +// final int greenMask = palette.greenMask; +// final int blueMask = palette.blueMask; +// int newDepth = i.depth; +// int newOrder = ImageData.MSB_FIRST; +// PaletteData newPalette = null; +// +// switch (i.depth) { +// case 8: +// newDepth = 16; +// newOrder = ImageData.LSB_FIRST; +// newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); +// break; +// case 16: +// newOrder = ImageData.LSB_FIRST; +// if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) { +// newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); +// } +// break; +// case 24: +// if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) { +// newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000); +// } +// break; +// case 32: +// if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) { +// newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); +// } +// break; +// default: +// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); +// } +// if (newPalette != null) { +// ImageData img = new ImageData(i.width, i.height, newDepth, newPalette); +// ImageData.blit(ImageData.BLIT_SRC, +// i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, redMask, greenMask, blueMask, +// ImageData.ALPHA_OPAQUE, null, 0, 0, 0, +// img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask, +// false, false); +// if (i.transparentPixel != -1) { +// img.transparentPixel = newPalette.getPixel(palette.getRGB(i.transparentPixel)); +// } +// img.maskPad = i.maskPad; +// img.maskData = i.maskData; +// img.alpha = i.alpha; +// img.alphaData = i.alphaData; +// i = img; +// } +// } +// /* Construct bitmap info header by hand */ +// RGB[] rgbs = i.palette.getRGBs(); +// boolean useBitfields = OS.IsWinCE && (i.depth == 16 || i.depth == 32); +// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); +// bmiHeader.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader.biWidth = i.width; +// bmiHeader.biHeight = -i.height; +// bmiHeader.biPlanes = 1; +// bmiHeader.biBitCount = (short)i.depth; +// if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS; +// else bmiHeader.biCompression = OS.BI_RGB; +// bmiHeader.biClrUsed = rgbs == null ? 0 : rgbs.length; +// byte[] bmi; +// if (i.palette.isDirect) +// bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)]; +// else +// bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4]; +// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); +// /* Set the rgb colors into the bitmap info */ +// int offset = BITMAPINFOHEADER.sizeof; +// if (i.palette.isDirect) { +// if (useBitfields) { +// PaletteData palette = i.palette; +// int redMask = palette.redMask; +// int greenMask = palette.greenMask; +// int blueMask = palette.blueMask; +// /* +// * The color masks must be written based on the +// * endianness of the ImageData. +// */ +// if (i.getByteOrder() == ImageData.LSB_FIRST) { +// bmi[offset] = (byte)((redMask & 0xFF) >> 0); +// bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8); +// bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16); +// bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24); +// bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0); +// bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8); +// bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16); +// bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24); +// bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0); +// bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8); +// bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16); +// bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24); +// } else { +// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24); +// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16); +// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8); +// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0); +// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24); +// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16); +// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8); +// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0); +// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24); +// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16); +// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8); +// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0); +// } +// } +// } else { +// for (int j = 0; j < rgbs.length; j++) { +// bmi[offset] = (byte)rgbs[j].blue; +// bmi[offset + 1] = (byte)rgbs[j].green; +// bmi[offset + 2] = (byte)rgbs[j].red; +// bmi[offset + 3] = 0; +// offset += 4; +// } +// } +// int[] pBits = new int[1]; +// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0); +// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// /* In case of a scanline pad other than 4, do the work to convert it */ +// byte[] data = i.data; +// if (i.scanlinePad != 4 && (i.bytesPerLine % 4 != 0)) { +// data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4); +// } +// OS.MoveMemory(pBits[0], data, data.length); +// +// int[] result = null; +// if (i.getTransparencyType() == SWT.TRANSPARENCY_MASK) { +// /* Get the HDC for the device */ +// int hDC = device.internal_new_GC(null); +// +// /* Create the color bitmap */ +// int hdcSrc = OS.CreateCompatibleDC(hDC); +// OS.SelectObject(hdcSrc, hDib); +// int hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height); +// if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// int hdcDest = OS.CreateCompatibleDC(hDC); +// OS.SelectObject(hdcDest, hBitmap); +// OS.BitBlt(hdcDest, 0, 0, i.width, i.height, hdcSrc, 0, 0, OS.SRCCOPY); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +// +// /* Create the mask. Windows requires icon masks to have a scanline pad of 2. */ +// byte[] maskData = ImageData.convertPad(i.maskData, i.width, i.height, 1, i.maskPad, 2); +// int hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData); +// if (hMask == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// OS.SelectObject(hdcSrc, hMask); +// OS.PatBlt(hdcSrc, 0, 0, i.width, i.height, OS.DSTINVERT); +// OS.DeleteDC(hdcSrc); +// OS.DeleteDC(hdcDest); +// OS.DeleteObject(hDib); +// +// if (image == null) { +// result = new int[]{hBitmap, hMask}; +// } else { +// /* Create the icon */ +// ICONINFO info = new ICONINFO(); +// info.fIcon = true; +// info.hbmColor = hBitmap; +// info.hbmMask = hMask; +// int hIcon = OS.CreateIconIndirect(info); +// if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// OS.DeleteObject(hBitmap); +// OS.DeleteObject(hMask); +// image.handle = hIcon; +// image.type = SWT.ICON; +// if (OS.IsWinCE) image.data = i; +// } +// } else { +// if (image == null) { +// result = new int[]{hDib}; +// } else { +// image.handle = hDib; +// image.type = SWT.BITMAP; +// image.transparentPixel = i.transparentPixel; +// if (image.transparentPixel == -1) { +// image.alpha = i.alpha; +// if (i.alpha == -1 && i.alphaData != null) { +// int length = i.alphaData.length; +// image.alphaData = new byte[length]; +// System.arraycopy(i.alphaData, 0, image.alphaData, 0, length); +// } +// } +// } +// } +// return result; +} + +static void init(Device device, Image image, ImageData source, ImageData mask) { + /* Create a temporary image and locate the black pixel */ + ImageData imageData; + int blackIndex = 0; + if (source.palette.isDirect) { + imageData = new ImageData(source.width, source.height, source.depth, source.palette); + } else { + RGB black = new RGB(0, 0, 0); + RGB[] rgbs = source.getRGBs(); + if (source.transparentPixel != -1) { + /* + * The source had transparency, so we can use the transparent pixel + * for black. + */ + RGB[] newRGBs = new RGB[rgbs.length]; + System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length); + if (source.transparentPixel >= newRGBs.length) { + /* Grow the palette with black */ + rgbs = new RGB[source.transparentPixel + 1]; + System.arraycopy(newRGBs, 0, rgbs, 0, newRGBs.length); + for (int i = newRGBs.length; i <= source.transparentPixel; i++) { + rgbs[i] = new RGB(0, 0, 0); + } + } else { + newRGBs[source.transparentPixel] = black; + rgbs = newRGBs; + } + blackIndex = source.transparentPixel; + imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs)); + } else { + while (blackIndex < rgbs.length) { + if (rgbs[blackIndex].equals(black)) break; + blackIndex++; + } + if (blackIndex == rgbs.length) { + /* + * We didn't find black in the palette, and there is no transparent + * pixel we can use. + */ + if ((1 << source.depth) > rgbs.length) { + /* We can grow the palette and add black */ + RGB[] newRGBs = new RGB[rgbs.length + 1]; + System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length); + newRGBs[rgbs.length] = black; + rgbs = newRGBs; + } else { + /* No room to grow the palette */ + blackIndex = -1; + } + } + imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs)); + } + } + if (blackIndex == -1) { + /* There was no black in the palette, so just copy the data over */ + System.arraycopy(source.data, 0, imageData.data, 0, imageData.data.length); + } else { + /* Modify the source image to contain black wherever the mask is 0 */ + int[] imagePixels = new int[imageData.width]; + int[] maskPixels = new int[mask.width]; + for (int y = 0; y < imageData.height; y++) { + source.getPixels(0, y, imageData.width, imagePixels, 0); + mask.getPixels(0, y, mask.width, maskPixels, 0); + for (int i = 0; i < imagePixels.length; i++) { + if (maskPixels[i] == 0) imagePixels[i] = blackIndex; + } + imageData.setPixels(0, y, source.width, imagePixels, 0); + } + } + imageData.maskPad = mask.scanlinePad; + imageData.maskData = mask.data; + init(device, image, imageData); +} + +void init(Device device, ImageData i) { + if (i == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + init(device, this, i); +} + +/** + * Invokes platform specific functionality to allocate a new GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Image. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param data the platform specific GC data + * @return the platform specific GC handle + */ +@Override +public CGC internal_new_GC (GCData data) { + if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if(data != null) { + int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; + if ((data.style & mask) != 0) { + data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? false : true; + } else { + data.style |= SWT.LEFT_TO_RIGHT; + } + data.device = device; + data.image = this; + data.hFont = LookAndFeelUtils.getSystemFont(); + } + final Graphics2D g = (Graphics2D)handle.getGraphics(); + if(g == null) { + return null; + } + return new CGC.CGCGraphics2D() { + @Override + public Graphics2D getGraphics() { + return g; + } + @Override + public Dimension getDeviceSize() { + return new Dimension(handle.getWidth(), handle.getHeight()); + } + }; +} + +/** + * Invokes platform specific functionality to dispose a GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Image. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param hDC the platform specific GC handle + * @param data the platform specific GC data + */ +public void internal_dispose_GC (CGC handle, GCData data) { + handle.dispose(); +} + +/** + * Returns true if the image has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the image. + * When an image has been disposed, it is an error to + * invoke any other method using the image. + * + * @return true when the image is disposed and false otherwise + */ +@Override +public boolean isDisposed() { + return handle == null; +} + +/** + * Sets the color to which to map the transparent pixel. + *

    + * There are certain uses of Images that do not support + * transparency (for example, setting an image into a button or label). + * In these cases, it may be desired to simulate transparency by using + * the background color of the widget to paint the transparent pixels + * of the image. This method specifies the color that will be used in + * these cases. For example: + *

    + *    Button b = new Button();
    + *    image.setBackground(b.getBackground());
    + *    b.setImage(image);
    + * 
    + *

    + * The image may be modified by this operation (in effect, the + * transparent regions may be filled with the supplied color). Hence + * this operation is not reversible and it is not legal to call + * this function twice or with a null argument. + *

    + * This method has no effect if the receiver does not have a transparent + * pixel value. + *

    + * + * @param color the color to use when a transparent pixel is specified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the color is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the color has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setBackground(Color color) { + // TODO: change all pixels with alpha channel == 1.0 to the defined value? + // if(colorModel instanceof IndexColorModel) {return colorModel.getTransparentPixel();} + return; +// /* +// * Note. Not implemented on WinCE. +// */ +// if (OS.IsWinCE) return; +// if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); +// if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); +// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// if (transparentPixel == -1) return; +// +// /* Get the HDC for the device */ +// int hDC = device.internal_new_GC(null); +// +// /* Change the background color in the image */ +// BITMAP bm = new BITMAP(); +// OS.GetObject(handle, BITMAP.sizeof, bm); +// int hdcMem = OS.CreateCompatibleDC(hDC); +// OS.SelectObject(hdcMem, handle); +// int maxColors = 1 << bm.bmBitsPixel; +// byte[] colors = new byte[maxColors * 4]; +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// int numColors = OS.GetDIBColorTable(hdcMem, 0, maxColors, colors); +// int offset = transparentPixel * 4; +// colors[offset] = (byte)color.getBlue(); +// colors[offset + 1] = (byte)color.getGreen(); +// colors[offset + 2] = (byte)color.getRed(); +// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); +// OS.SetDIBColorTable(hdcMem, 0, numColors, colors); +// OS.DeleteDC(hdcMem); +// +// /* Release the HDC for the device */ +// device.internal_dispose_GC(hDC, null); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +@Override +public String toString () { + if (isDisposed()) return "Image {*DISPOSED*}"; + return "Image {" + handle + "}"; +} + +/** + * Invokes platform specific functionality to allocate a new image. + *

    + * IMPORTANT: This method is not part of the public + * API for Image. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param device the device on which to allocate the color + * @param type the type of the image (SWT.BITMAP or SWT.ICON) + * @param handle the OS handle for the image + * @return a new image object containing the specified device, type and handle + */ +public static Image swing_new(Device device, int type, java.awt.Image handle) { + if (device == null) device = Device.getDevice(); + Image image = new Image(); + image.type = type; + image.handle = duplicateImage(handle); + image.device = device; + return image; +} + +static BufferedImage duplicateImage(java.awt.Image handle) { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gs = ge.getDefaultScreenDevice(); + GraphicsConfiguration gc = gs.getDefaultConfiguration(); + int transparency; + if(handle instanceof BufferedImage) { + transparency = ((BufferedImage)handle).getColorModel().getTransparency(); + } else { + PixelGrabber pg = new PixelGrabber(handle, 0, 0, 1, 1, false); + try { + pg.grabPixels(); + } catch (InterruptedException e) {} + transparency = pg.getColorModel().getTransparency(); + } + BufferedImage bHandle = gc.createCompatibleImage(handle.getWidth(null), handle.getHeight(null), transparency); + Graphics g = bHandle.createGraphics(); + g.drawImage(handle, 0, 0, null); + g.dispose(); + return bHandle; +} + +public ImageData getImageData(int deviceZoom) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +//private static BufferedImage createBufferedImageIndexPalette(ImageData data, PaletteData p) { +// RGB[] rgbs = p.getRGBs(); +// byte[] red = new byte[rgbs.length]; +// byte[] green = new byte[rgbs.length]; +// byte[] blue = new byte[rgbs.length]; +// for(int i = 0; i < rgbs.length; i++) { +// RGB rgb = rgbs[i]; +// red[i] = (byte) rgb.red; +// green[i] = (byte) rgb.green; +// blue[i] = (byte) rgb.blue; +// } +// ColorModel cM; +// if(data.transparentPixel != -1) { +// cM = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel); +// } else { +// cM = new IndexColorModel(data.depth, rgbs.length, red, green, blue); +// } +// BufferedImage bi = new BufferedImage(cM, cM.createCompatibleWritableRaster(data.width, data.height), false, null); +// WritableRaster r = bi.getRaster(); +// int[] pA = new int[1]; +// for (int y = 0; y < data.height; y++) { +// for (int x = 0; x < data.width; x++) { +// int pixel = data.getPixel(x, y); +// pA[0] = pixel; +// r.setPixel(x, y, pA); +// } +// } +// // System.out.println("data.transparentPixel: " +// // + data.transparentPixel); +// // System.out.println(colorModel); +// // System.out.println(bufferedImage); +// // System.out.println(); +// return bi; +//} +// +//private static BufferedImage createBufferedImageDirectPalette(ImageData data, PaletteData p) { +// // Added ColorModel.TRANSLUCENT to create a ColorModel with +// // transparency and resulting in a ARGB BufferedImage +// // TODO: Check if true: Still Transparency-Gradients may be +// // impossible with standard JavaIO & BufferedImages since +// // ColorModel.TRANSLUCENT is either opaque or transparent. +// ColorModel cM = new DirectColorModel(data.depth, p.redMask, p.greenMask, p.blueMask, 0); +// BufferedImage bi = new BufferedImage(cM, cM.createCompatibleWritableRaster(data.width, data.height), false, null); +// WritableRaster r = bi.getRaster(); +// int[] pA = new int[4]; +// for (int y = 0; y < data.height; y++) { +// for (int x = 0; x < data.width; x++) { +// int pixel = data.getPixel(x, y); +// RGB rgb = p.getRGB(pixel); +// pA[0] = rgb.red; +// pA[1] = rgb.green; +// pA[2] = rgb.blue; +// pA[3] = data.getAlpha(x, y); +// // Line is a bugfix which is actually for Problems with +// // detecting Transparency in BufferedImages. Also using the +// // normal ImageIO.read(...) method results in this bug and +// // can be tested using comment.png from Azureus +// if (data.transparentPixel != -1 && pixel == data.transparentPixel) { +// pA[3] = 0; +// } +// // System.out.println(pixelArray[3]); +// r.setPixels(x, y, 1, 1, pA); +// } +// } +// // System.out.println("data.transparentPixel: " +// // + data.transparentPixel); +// // System.out.println(colorModel); +// // System.out.println(bufferedImage); +// // System.out.println(); +// return bi; +//} + +//public static class SImageData implements java.io.Serializable { +// public static class SPaletteData implements java.io.Serializable { +// public boolean isDirect; +// public RGB[] colors; +// public int redMask; +// public int greenMask; +// public int blueMask; +// public int redShift; +// public int greenShift; +// public int blueShift; +// SPaletteData(PaletteData data) { +// this.colors = data.colors; +// this.isDirect = data.isDirect; +// this.redMask = data.redMask; +// this.greenMask = data.greenMask; +// this.blueMask = data.blueMask; +// this.redShift = data.redShift; +// this.greenShift = data.greenShift; +// this.blueShift = data.blueShift; +// } +// public PaletteData createPaletteData() { +// PaletteData paletteData = new PaletteData(new RGB[0]); +// paletteData.colors = colors; +// paletteData.isDirect = isDirect; +// paletteData.redMask = redMask; +// paletteData.greenMask = greenMask; +// paletteData.blueMask = blueMask; +// paletteData.redShift = redShift; +// paletteData.greenShift = greenShift; +// paletteData.blueShift = blueShift; +// return paletteData; +// } +// public String toString() { +// StringBuilder sb = new StringBuilder("PaletteData:"); +// try { +// java.lang.reflect.Field[] fields = getClass().getDeclaredFields(); +// for(int i=0; i + * Currently supported image formats are: + *

      + *
    • BMP (Windows or OS/2 Bitmap)
    • + *
    • ICO (Windows Icon)
    • + *
    • JPEG
    • + *
    • GIF
    • + *
    • PNG
    • + *
    • TIFF
    • + *
    + * ImageLoaders can be used to: + *
      + *
    • load/save single images in all formats
    • + *
    • load/save multiple images (GIF/ICO/TIFF)
    • + *
    • load/save animated GIF images
    • + *
    • load interlaced GIF/PNG images
    • + *
    • load progressive JPEG images
    • + *
    + * + *

    + * NOTE: ImageLoader is implemented in Java on some platforms, which has + * certain performance implications. Performance and memory sensitive applications may + * benefit from using one of the constructors provided by Image, as these + * are implemented natively.

    + * + * @see SWT Example: ImageAnalyzer + * @see Sample code and further information + */ +public class ImageLoader { + + /** + * the array of ImageData objects in this ImageLoader. + * This array is read in when the load method is called, + * and it is written out when the save method is called + */ + public ImageData[] data; + + /** + * the width of the logical screen on which the images + * reside, in pixels (this corresponds to the GIF89a + * Logical Screen Width value) + */ + public int logicalScreenWidth; + + /** + * the height of the logical screen on which the images + * reside, in pixels (this corresponds to the GIF89a + * Logical Screen Height value) + */ + public int logicalScreenHeight; + + /** + * the background pixel for the logical screen (this + * corresponds to the GIF89a Background Color Index value). + * The default is -1 which means 'unspecified background' + */ + public int backgroundPixel; + + /** + * the number of times to repeat the display of a sequence + * of animated images (this corresponds to the commonly-used + * GIF application extension for "NETSCAPE 2.0 01"). + * The default is 1. A value of 0 means 'display repeatedly' + */ + public int repeatCount; + + /** + * This is the compression used when saving jpeg and png files. + *

    + * When saving jpeg files, the value is from 1 to 100, + * where 1 is very high compression but low quality, and 100 is + * no compression and high quality; default is 75. + *

    + * When saving png files, the value is from 0 to 3, but they do not impact the quality + * because PNG is lossless compression. 0 is uncompressed, 1 is low compression and fast, + * 2 is default compression, and 3 is high compression but slow. + *

    + * + * @since 3.8 + */ + public int compression; + + /* + * the set of ImageLoader event listeners, created on demand + */ + List imageLoaderListeners; + +/** + * Construct a new empty ImageLoader. + */ +public ImageLoader() { + reset(); +} + +/** + * Resets the fields of the ImageLoader, except for the + * imageLoaderListeners field. + */ +void reset() { + data = null; + logicalScreenWidth = 0; + logicalScreenHeight = 0; + backgroundPixel = -1; + repeatCount = 1; + compression = -1; +} + +/** + * Loads an array of ImageData objects from the + * specified input stream. Throws an error if either an error + * occurs while loading the images, or if the images are not + * of a supported type. Returns the loaded image data array. + * + * @param stream the input stream to load the images from + * @return an array of ImageData objects loaded from the specified input stream + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the stream is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while reading from the stream
    • + *
    • ERROR_INVALID_IMAGE - if the image stream contains invalid data
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format
    • + *
    + */ +public ImageData[] load(InputStream stream) { + if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + reset(); + data = FileFormat.load(stream, this); + return data; +} + +/** + * Loads an array of ImageData objects from the + * file with the specified name. Throws an error if either + * an error occurs while loading the images, or if the images are + * not of a supported type. Returns the loaded image data array. + * + * @param filename the name of the file to load the images from + * @return an array of ImageData objects loaded from the specified file + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the file name is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while reading from the file
    • + *
    • ERROR_INVALID_IMAGE - if the image file contains invalid data
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format
    • + *
    + */ +public ImageData[] load(String filename) { + if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + try (InputStream stream = new FileInputStream(filename)) { + return load(stream); + } catch (IOException e) { + SWT.error(SWT.ERROR_IO, e); + } + return null; +} + +/** + * Saves the image data in this ImageLoader to the specified stream. + * The format parameter can have one of the following values: + *
    + *
    IMAGE_BMP
    + *
    Windows BMP file format, no compression
    + *
    IMAGE_BMP_RLE
    + *
    Windows BMP file format, RLE compression if appropriate
    + *
    IMAGE_GIF
    + *
    GIF file format
    + *
    IMAGE_ICO
    + *
    Windows ICO file format
    + *
    IMAGE_JPEG
    + *
    JPEG file format
    + *
    IMAGE_PNG
    + *
    PNG file format
    + *
    + * + * @param stream the output stream to write the images to + * @param format the format to write the images in + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the stream is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while writing to the stream
    • + *
    • ERROR_INVALID_IMAGE - if the image data contains invalid data
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format
    • + *
    + */ +public void save(OutputStream stream, int format) { + if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + FileFormat.save(stream, format, this); +} + +/** + * Saves the image data in this ImageLoader to a file with the specified name. + * The format parameter can have one of the following values: + *
    + *
    IMAGE_BMP
    + *
    Windows BMP file format, no compression
    + *
    IMAGE_BMP_RLE
    + *
    Windows BMP file format, RLE compression if appropriate
    + *
    IMAGE_GIF
    + *
    GIF file format
    + *
    IMAGE_ICO
    + *
    Windows ICO file format
    + *
    IMAGE_JPEG
    + *
    JPEG file format
    + *
    IMAGE_PNG
    + *
    PNG file format
    + *
    + * + * @param filename the name of the file to write the images to + * @param format the format to write the images in + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the file name is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_IO - if an IO error occurs while writing to the file
    • + *
    • ERROR_INVALID_IMAGE - if the image data contains invalid data
    • + *
    • ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format
    • + *
    + */ +public void save(String filename, int format) { + if (filename == null) + SWT.error(SWT.ERROR_NULL_ARGUMENT); + try (OutputStream stream = new FileOutputStream(filename)) { + save(stream, format); + } catch (IOException e) { + SWT.error(SWT.ERROR_IO, e); + } +} + +/** + * Adds the listener to the collection of listeners who will be + * notified when image data is either partially or completely loaded. + *

    + * An ImageLoaderListener should be added before invoking + * one of the receiver's load methods. The listener's + * imageDataLoaded method is called when image + * data has been partially loaded, as is supported by interlaced + * GIF/PNG or progressive JPEG images. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @see ImageLoaderListener + * @see ImageLoaderEvent + */ +public void addImageLoaderListener(ImageLoaderListener listener) { + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (imageLoaderListeners == null) { + imageLoaderListeners = new ArrayList<>(); + } + imageLoaderListeners.add(listener); +} + +/** + * Removes the listener from the collection of listeners who will be + * notified when image data is either partially or completely loaded. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @see #addImageLoaderListener(ImageLoaderListener) + */ +public void removeImageLoaderListener(ImageLoaderListener listener) { + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (imageLoaderListeners == null) return; + imageLoaderListeners.remove(listener); +} + +/** + * Returns true if the receiver has image loader + * listeners, and false otherwise. + * + * @return true if there are ImageLoaderListeners, and false otherwise + * + * @see #addImageLoaderListener(ImageLoaderListener) + * @see #removeImageLoaderListener(ImageLoaderListener) + */ +public boolean hasListeners() { + return imageLoaderListeners != null && imageLoaderListeners.size() > 0; +} + +/** + * Notifies all image loader listeners that an image loader event + * has occurred. Pass the specified event object to each listener. + * + * @param event the ImageLoaderEvent to send to each ImageLoaderListener + */ +public void notifyListeners(ImageLoaderEvent event) { + if (!hasListeners()) return; + int size = imageLoaderListeners.size(); + for (int i = 0; i < size; i++) { + ImageLoaderListener listener = imageLoaderListeners.get(i); + listener.imageDataLoaded(event); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java new file mode 100644 index 00000000000..422302f351d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java @@ -0,0 +1,489 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.geom.Arc2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; + +/** + * Instances of this class represent paths through the two-dimensional + * coordinate system. Paths do not have to be continuous, and can be + * described using lines, rectangles, arcs, cubic or quadratic bezier curves, + * glyphs, or other paths. + *

    + * Application code must explicitly invoke the Path.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @since 3.1 + */ +public class Path extends Resource { + + /** + * the OS resource for the Path + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public GeneralPath handle; + +/** + * Constructs a new empty Path. + * + * @param device the device on which to allocate the path + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the path could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Path (Device device) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + handle = new GeneralPath(); + if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES); + if (device.tracking) device.new_Object(this); +} + +/** + * Adds to the receiver a circular or elliptical arc that lies within + * the specified rectangular area. + *

    + * The resulting arc begins at startAngle and extends + * for arcAngle degrees. + * Angles are interpreted such that 0 degrees is at the 3 o'clock + * position. A positive value indicates a counter-clockwise rotation + * while a negative value indicates a clockwise rotation. + *

    + * The center of the arc is the center of the rectangle whose origin + * is (x, y) and whose size is specified by the + * width and height arguments. + *

    + * The resulting arc covers an area width + 1 pixels wide + * by height + 1 pixels tall. + *

    + * + * @param x the x coordinate of the upper-left corner of the arc + * @param y the y coordinate of the upper-left corner of the arc + * @param width the width of the arc + * @param height the height of the arc + * @param startAngle the beginning angle + * @param arcAngle the angular extent of the arc, relative to the start angle + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void addArc(float x, float y, float width, float height, float startAngle, float arcAngle) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + if (width == 0 || height == 0 || arcAngle == 0) return; + handle.append(new Arc2D.Float(x, y, width, height, startAngle, + arcAngle, Arc2D.OPEN), true); +} + +/** + * Adds to the receiver the path described by the parameter. + * + * @param path the path to add to the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void addPath(Path path) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + //TODO - expose connect? + handle.append(path.handle, true); +} + +/** + * Adds to the receiver the rectangle specified by x, y, width and height. + * + * @param x the x coordinate of the rectangle to add + * @param y the y coordinate of the rectangle to add + * @param width the width of the rectangle to add + * @param height the height of the rectangle to add + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void addRectangle(float x, float y, float width, float height) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.append(new Rectangle2D.Float(x, y, width, height), true); +} + +/** + * Adds to the receiver the pattern of glyphs generated by drawing + * the given string using the given font starting at the point (x, y). + * + * @param string the text to use + * @param x the x coordinate of the starting point + * @param y the y coordinate of the starting point + * @param font the font to use + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the font is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the font has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void addString(String string, float x, float y, org.eclipse.swt.graphics.Font font) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + FontRenderContext frc = new FontRenderContext(null, true, true); + GlyphVector glyph = font.handle.createGlyphVector(frc, string); + LineMetrics lm = font.handle.getLineMetrics(string, frc); + handle.append(glyph.getOutline(x, y + lm.getAscent()), true); +} + +/** + * Closes the current sub path by adding to the receiver a line + * from the current point of the path back to the starting point + * of the sub path. + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void close() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.closePath(); +} + +/** + * Returns true if the specified point is contained by + * the receiver and false otherwise. + *

    + * If outline is true, the point (x, y) checked for containment in + * the receiver's outline. If outline is false, the point is + * checked to see if it is contained within the bounds of the (closed) area + * covered by the receiver. + * + * @param x the x coordinate of the point to test for containment + * @param y the y coordinate of the point to test for containment + * @param gc the GC to use when testing for containment + * @param outline controls whether to check the outline or contained area of the path + * @return true if the path contains the point and false otherwise + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the gc is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the gc has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean contains(float x, float y, GC gc, boolean outline) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + //TODO - should use GC transformation + // TODO support outline + return handle.contains(x, y); +} + +/** + * Adds to the receiver a cubic bezier curve based on the parameters. + * + * @param cx1 the x coordinate of the first control point of the spline + * @param cy1 the y coordinate of the first control of the spline + * @param cx2 the x coordinate of the second control of the spline + * @param cy2 the y coordinate of the second control of the spline + * @param x the x coordinate of the end point of the spline + * @param y the y coordinate of the end point of the spline + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.curveTo(cx1, cy1, cx2, cy2, x, y); +} + +/** + * Disposes of the operating system resources associated with + * the Path. Applications must dispose of all Paths that + * they allocate. + */ +public void dispose() { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Replaces the first four elements in the parameter with values that + * describe the smallest rectangle that will completely contain the + * receiver (i.e. the bounding box). + * + * @param bounds the array to hold the result + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the bounding box
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void getBounds(float[] bounds) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + Rectangle2D boundingBox = handle.getBounds2D(); + bounds[0] = (float)boundingBox.getX(); + bounds[1] = (float)boundingBox.getY(); + bounds[2] = (float)boundingBox.getWidth(); + bounds[3] = (float)boundingBox.getHeight(); +} + +/** + * Replaces the first two elements in the parameter with values that + * describe the current point of the path. + * + * @param point the array to hold the result + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the end point
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void getCurrentPoint(float[] point) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (point == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (point.length < 2) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + Point2D p = handle.getCurrentPoint(); + point[0] = (float) p.getX(); + point[1] = (float) p.getY(); +} + +/** + * Returns a device independent representation of the receiver. + * + * @return the PathData for the receiver + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see PathData + */ +public PathData getPathData() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + List typeList = new ArrayList(); + List pointList = new ArrayList(); + float[] values = new float[6]; + for(PathIterator pathIterator = handle.getPathIterator(null); !pathIterator.isDone(); pathIterator.next()) { + switch(pathIterator.currentSegment(values)) { + case PathIterator.SEG_MOVETO: + typeList.add(new Byte((byte)SWT.PATH_MOVE_TO)); + break; + case PathIterator.SEG_LINETO: + typeList.add(new Byte((byte)SWT.PATH_LINE_TO)); + pointList.add(new Float(values[0])); + pointList.add(new Float(values[1])); + break; + case PathIterator.SEG_QUADTO: + typeList.add(new Byte((byte)SWT.PATH_QUAD_TO)); + pointList.add(new Float(values[0])); + pointList.add(new Float(values[1])); + pointList.add(new Float(values[2])); + pointList.add(new Float(values[3])); + break; + case PathIterator.SEG_CUBICTO: + typeList.add(new Byte((byte)SWT.PATH_CUBIC_TO)); + pointList.add(new Float(values[0])); + pointList.add(new Float(values[1])); + pointList.add(new Float(values[2])); + pointList.add(new Float(values[3])); + pointList.add(new Float(values[4])); + pointList.add(new Float(values[5])); + break; + case PathIterator.SEG_CLOSE: + typeList.add(new Byte((byte)SWT.PATH_CLOSE)); + break; + } + } + byte[] types = new byte[typeList.size()]; + for(int i=typeList.size()-1; i>=0; i--) { + types[i] = ((Byte)typeList.get(i)).byteValue(); + } + float[] points = new float[pointList.size()]; + for(int i=pointList.size()-1; i>=0; i--) { + points[i] = ((Float)typeList.get(i)).floatValue(); + } + PathData result = new PathData(); + result.types = types; + result.points = points; + return result; +// int count = Gdip.GraphicsPath_GetPointCount(handle); +// byte[] gdipTypes = new byte[count]; +// float[] points = new float[count * 2]; +// Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes, count); +// Gdip.GraphicsPath_GetPathPoints(handle, points, count); +// byte[] types = new byte[count * 2]; +// int index = 0, typesIndex = 0; +// while (index < count) { +// byte type = gdipTypes[index]; +// boolean close = false; +// switch (type & Gdip.PathPointTypePathTypeMask) { +// case Gdip.PathPointTypeStart: +// types[typesIndex++] = SWT.PATH_MOVE_TO; +// close = (type & Gdip.PathPointTypeCloseSubpath) != 0; +// index += 1; +// break; +// case Gdip.PathPointTypeLine: +// types[typesIndex++] = SWT.PATH_LINE_TO; +// close = (type & Gdip.PathPointTypeCloseSubpath) != 0; +// index += 1; +// break; +// case Gdip.PathPointTypeBezier: +// types[typesIndex++] = SWT.PATH_CUBIC_TO; +// close = (gdipTypes[index + 2] & Gdip.PathPointTypeCloseSubpath) != 0; +// index += 3; +// break; +// default: +// index++; +// } +// if (close) { +// types[typesIndex++] = SWT.PATH_CLOSE; +// } +// } +// if (typesIndex != types.length) { +// byte[] newTypes = new byte[typesIndex]; +// System.arraycopy(types, 0, newTypes, 0, typesIndex); +// types = newTypes; +// } +// PathData result = new PathData(); +// result.types = types; +// result.points = points; +// return result; +} + +/** + * Adds to the receiver a line from the current point to + * the point specified by (x, y). + * + * @param x the x coordinate of the end of the line to add + * @param y the y coordinate of the end of the line to add + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void lineTo(float x, float y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.lineTo(x, y); +} + +/** + * Returns true if the Path has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the Path. + * When a Path has been disposed, it is an error to + * invoke any other method using the Path. + * + * @return true when the Path is disposed, and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +/** + * Sets the current point of the receiver to the point + * specified by (x, y). Note that this starts a new + * sub path. + * + * @param x the x coordinate of the new end point + * @param y the y coordinate of the new end point + * + * @exception SWTException

      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void moveTo(float x, float y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.moveTo(x, y); +} + +/** + * Adds to the receiver a quadratic curve based on the parameters. + * + * @param cx the x coordinate of the control point of the spline + * @param cy the y coordinate of the control point of the spline + * @param x the x coordinate of the end point of the spline + * @param y the y coordinate of the end point of the spline + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void quadTo(float cx, float cy, float x, float y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.quadTo(cx, cy, x, y); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString() { + if (isDisposed()) return "Path {*DISPOSED*}"; + return "Path {" + handle + "}"; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java new file mode 100644 index 00000000000..bab4084355d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import org.eclipse.swt.*; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class represent patterns to use while drawing. Patterns + * can be specified either as bitmaps or gradients. + *

    + * Application code must explicitly invoke the Pattern.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @since 3.1 + */ +public class Pattern extends Resource { + + /** + * the OS resource for the Pattern + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public int handle; + +/** + * Constructs a new Pattern given an image. Drawing with the resulting + * pattern will cause the image to be tiled over the resulting area. + * + * @param device the device on which to allocate the pattern + * @param image the image that the pattern will draw + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device, or the image is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Pattern(Device device, Image image) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + this.device = device; + Utils.notImplemented(); +// device.checkGDIP(); +// int[] gdipImage = image.createGdipImage(); +// int img = gdipImage[0]; +// int width = Gdip.Image_GetWidth(img); +// int height = Gdip.Image_GetHeight(img); +// handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height); +// Gdip.Bitmap_delete(img); +// if (gdipImage[1] != 0) { +// int hHeap = OS.GetProcessHeap (); +// OS.HeapFree(hHeap, 0, gdipImage[1]); +// } +// if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new Pattern that represents a linear, two color + * gradient. Drawing with the pattern will cause the resulting area to be + * tiled with the gradient specified by the arguments. + * + * @param device the device on which to allocate the pattern + * @param x1 the x coordinate of the starting corner of the gradient + * @param y1 the y coordinate of the starting corner of the gradient + * @param x2 the x coordinate of the ending corner of the gradient + * @param y2 the y coordinate of the ending corner of the gradient + * @param color1 the starting color of the gradient + * @param color2 the ending color of the gradient + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device, + * or if either color1 or color2 is null
    • + *
    • ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, Color color2) { + this(device, x1, y1, x2, y2, color1, 0xFF, color2, 0xFF); +} + +/** + * Constructs a new Pattern that represents a linear, two color + * gradient. Drawing with the pattern will cause the resulting area to be + * tiled with the gradient specified by the arguments. + * + * @param device the device on which to allocate the pattern + * @param x1 the x coordinate of the starting corner of the gradient + * @param y1 the y coordinate of the starting corner of the gradient + * @param x2 the x coordinate of the ending corner of the gradient + * @param y2 the y coordinate of the ending corner of the gradient + * @param color1 the starting color of the gradient + * @param alpha1 the starting alpha value of the gradient + * @param color2 the ending color of the gradient + * @param alpha2 the ending alpha value of the gradient + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device, + * or if either color1 or color2 is null
    • + *
    • ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li> + *
    + * + * @see #dispose() + * + * @since 3.2 + */ +public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + this.device = device; + Utils.notImplemented(); +// device.checkGDIP(); +// int colorRef1 = color1.handle; +// int rgb = ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16); +// int foreColor = Gdip.Color_new((alpha1 & 0xFF) << 24 | rgb); +// int colorRef2 = color2.handle; +// rgb = ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16); +// int backColor = Gdip.Color_new((alpha2 & 0xFF) << 24 | rgb); +// PointF p1 = new PointF(); +// p1.X = x1; +// p1.Y = y1; +// PointF p2 = new PointF(); +// p2.X = x2; +// p2.Y = y2; +// handle = Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor); +// if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// if (alpha1 != 0xFF || alpha2 != 0xFF) { +// int a = (int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f); +// int r = (int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f); +// int g = (int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f); +// int b = (int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f); +// int midColor = Gdip.Color_new(a << 24 | r << 16 | g << 8 | b); +// Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int[]{foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3); +// Gdip.Color_delete(midColor); +// } +// Gdip.Color_delete(foreColor); +// Gdip.Color_delete(backColor); +// if (device.tracking) device.new_Object(this); +} + +/** + * Disposes of the operating system resources associated with + * the Pattern. Applications must dispose of all Patterns that + * they allocate. + */ +public void dispose() { + if (handle == 0) return; + if (device.isDisposed()) return; +// int type = Gdip.Brush_GetType(handle); +// switch (type) { +// case Gdip.BrushTypeSolidColor: +// Gdip.SolidBrush_delete(handle); +// break; +// case Gdip.BrushTypeHatchFill: +// Gdip.HatchBrush_delete(handle); +// break; +// case Gdip.BrushTypeLinearGradient: +// Gdip.LinearGradientBrush_delete(handle); +// break; +// case Gdip.BrushTypeTextureFill: +// Gdip.TextureBrush_delete(handle); +// break; +// } + handle = 0; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Returns true if the Pattern has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the Pattern. + * When a Pattern has been disposed, it is an error to + * invoke any other method using the Pattern. + * + * @return true when the Pattern is disposed, and false otherwise + */ +public boolean isDisposed() { + return handle == 0; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString() { + if (isDisposed()) return "Pattern {*DISPOSED*}"; + return "Pattern {" + handle + "}"; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java new file mode 100644 index 00000000000..63c544152c4 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java @@ -0,0 +1,600 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; + +import org.eclipse.swt.*; + +/** + * Instances of this class represent areas of an x-y coordinate + * system that are aggregates of the areas covered by a number + * of polygons. + *

    + * Application code must explicitly invoke the Region.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + */ + +public final class Region extends Resource { + + /** + * the OS resource for the region + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public Area handle; + +/** + * Constructs a new empty region. + * + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for region creation
    • + *
    + */ +public Region () { + this(null); +} + +/** + * Constructs a new empty region. + *

    + * You must dispose the region when it is no longer required. + *

    + * + * @param device the device on which to allocate the region + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for region creation
    • + *
    + * + * @see #dispose + * + * @since 3.0 + */ +public Region (Device device) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + handle = new Area(); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new region given a handle to the operating + * system resources that it should represent. + * + * @param handle the handle for the result + */ +Region(Device device, Shape handle) { + this.device = device; + this.handle = new Area(handle); +} + +/** + * Adds the given polygon to the collection of polygons + * the receiver maintains to describe its area. + * + * @param pointArray points that describe the polygon to merge with the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 +* + */ +public void add (int[] pointArray) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + int[] xPoints = new int[pointArray.length/2]; + int[] yPoints = new int[xPoints.length]; + for (int i = 0; i < xPoints.length; i++) { + xPoints[i] = pointArray[i * 2]; + yPoints[i] = pointArray[i * 2 + 1]; + } + handle.add(new Area(new java.awt.Polygon(xPoints, yPoints, xPoints.length))); +} + +/** + * Adds the given rectangle to the collection of polygons + * the receiver maintains to describe its area. + * + * @param rect the rectangle to merge with the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void add (Rectangle rect) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + add (rect.x, rect.y, rect.width, rect.height); +} + +/** + * Adds the given rectangle to the collection of polygons + * the receiver maintains to describe its area. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param width the width coordinate of the rectangle + * @param height the height coordinate of the rectangle + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void add (int x, int y, int width, int height) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.add(new Area(new java.awt.Rectangle(x, y, width, height))); +} + +/** + * Adds all of the polygons which make up the area covered + * by the argument to the collection of polygons the receiver + * maintains to describe its area. + * + * @param region the region to merge + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void add (Region region) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.add(region.handle); +} + +/** + * Returns true if the point specified by the + * arguments is inside the area specified by the receiver, + * and false otherwise. + * + * @param x the x coordinate of the point to test for containment + * @param y the y coordinate of the point to test for containment + * @return true if the region contains the point and false otherwise + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean contains (int x, int y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.contains(new java.awt.Point(x, y)); +} + +/** + * Returns true if the given point is inside the + * area specified by the receiver, and false + * otherwise. + * + * @param pt the point to test for containment + * @return true if the region contains the point and false otherwise + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean contains (Point pt) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return contains(pt.x, pt.y); +} + +/** + * Disposes of the operating system resources associated with + * the region. Applications must dispose of all regions which + * they allocate. + */ +public void dispose () { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public boolean equals (Object object) { + if (this == object) return true; + if (!(object instanceof Region)) return false; + Region rgn = (Region)object; + return handle == rgn.handle; +} + +/** + * Returns a rectangle which represents the rectangular + * union of the collection of polygons the receiver + * maintains to describe its area. + * + * @return a bounding rectangle for the region + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Rectangle#union + */ +public Rectangle getBounds() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + java.awt.Rectangle bounds = handle.getBounds(); + return new Rectangle((int)bounds.getX(), (int)bounds.getY(), (int)bounds.getWidth(), (int)bounds.getHeight()); +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public int hashCode () { + return handle == null? 0: handle.hashCode(); +} + +/** + * Intersects the given rectangle to the collection of polygons + * the receiver maintains to describe its area. + * + * @param rect the rectangle to intersect with the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public void intersect (Rectangle rect) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + intersect (rect.x, rect.y, rect.width, rect.height); +} + +/** + * Intersects the given rectangle to the collection of polygons + * the receiver maintains to describe its area. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param width the width coordinate of the rectangle + * @param height the height coordinate of the rectangle + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void intersect (int x, int y, int width, int height) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.intersect(new Area(new java.awt.Rectangle(x, y, width, height))); +} + +/** + * Intersects all of the polygons which make up the area covered + * by the argument to the collection of polygons the receiver + * maintains to describe its area. + * + * @param region the region to intersect + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public void intersect (Region region) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.intersect(region.handle); +} + +/** + * Returns true if the rectangle described by the + * arguments intersects with any of the polygons the receiver + * maintains to describe its area, and false otherwise. + * + * @param x the x coordinate of the origin of the rectangle + * @param y the y coordinate of the origin of the rectangle + * @param width the width of the rectangle + * @param height the height of the rectangle + * @return true if the rectangle intersects with the receiver, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Rectangle#intersects(Rectangle) + */ +public boolean intersects (int x, int y, int width, int height) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.intersects(x, y, width, height); +} + +/** + * Returns true if the given rectangle intersects + * with any of the polygons the receiver maintains to describe + * its area and false otherwise. + * + * @param rect the rectangle to test for intersection + * @return true if the rectangle intersects with the receiver, and false otherwise + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Rectangle#intersects(Rectangle) + */ +public boolean intersects (Rectangle rect) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return intersects(rect.x, rect.y, rect.width, rect.height); +} + +/** + * Returns true if the region has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the region. + * When a region has been disposed, it is an error to + * invoke any other method using the region. + * + * @return true when the region is disposed, and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +/** + * Returns true if the receiver does not cover any + * area in the (x, y) coordinate plane, and false if + * the receiver does cover some area in the plane. + * + * @return true if the receiver is empty, and false otherwise + * + * @exception SWTException

      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public boolean isEmpty () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.isEmpty(); +} + +/** + * Subtracts the given polygon from the collection of polygons + * the receiver maintains to describe its area. + * + * @param pointArray points that describe the polygon to merge with the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public void subtract (int[] pointArray) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + int[] xPoints = new int[pointArray.length/2]; + int[] yPoints = new int[xPoints.length]; + for (int i = 0; i < xPoints.length; i++) { + xPoints[i] = pointArray[i * 2]; + yPoints[i] = pointArray[i * 2 + 1]; + } + handle.subtract(new Area(new java.awt.Polygon(xPoints, yPoints, xPoints.length))); +} + +/** + * Subtracts the given rectangle from the collection of polygons + * the receiver maintains to describe its area. + * + * @param rect the rectangle to subtract from the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public void subtract (Rectangle rect) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + subtract (rect.x, rect.y, rect.width, rect.height); +} + +/** + * Subtracts the given rectangle from the collection of polygons + * the receiver maintains to describe its area. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param width the width coordinate of the rectangle + * @param height the height coordinate of the rectangle + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void subtract (int x, int y, int width, int height) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.subtract(new Area(new java.awt.Rectangle(x, y, width, height))); +} + +/** + * Subtracts all of the polygons which make up the area covered + * by the argument from the collection of polygons the receiver + * maintains to describe its area. + * + * @param region the region to subtract + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public void subtract (Region region) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.subtract(region.handle); +} + +/** + * Translate all of the polygons the receiver maintains to describe + * its area by the specified point. + * + * @param x the x coordinate of the point to translate + * @param y the y coordinate of the point to translate + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void translate (int x, int y) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.transform(AffineTransform.getTranslateInstance(x, y)); +} + +/** + * Translate all of the polygons the receiver maintains to describe + * its area by the specified point. + * + * @param pt the point to translate + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the argument is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.1 + */ +public void translate (Point pt) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + translate (pt.x, pt.y); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString () { + if (isDisposed()) return "Region {*DISPOSED*}"; + return "Region {" + handle + "}"; +} + +///** +// * Invokes platform specific functionality to allocate a new region. +// *

    +// * IMPORTANT: This method is not part of the public +// * API for Region. It is marked public only so that it +// * can be shared within the packages provided by SWT. It is not +// * available on all platforms, and should never be called from +// * application code. +// *

    +// * +// * @param device the device on which to allocate the region +// * @param handle the handle for the region +// * @return a new region object containing the specified device and handle +// */ +//public static Region win32_new(Device device, int handle) { +// return new Region(device, handle); +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java new file mode 100644 index 00000000000..2dea926eb81 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java @@ -0,0 +1,1726 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import org.eclipse.swt.*; + +/** + * TextLayout is a graphic object that represents + * styled text. + *

    + * Instances of this class provide support for drawing, cursor + * navigation, hit testing, text wrapping, alignment, tab expansion + * line breaking, etc. These are aspects required for rendering internationalized text. + *

    + * Application code must explicitly invoke the TextLayout#dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @since 3.0 + */ +public final class TextLayout extends Resource { + Device device; + Font font; + String text; + int lineSpacing; + int ascent, descent; + int alignment; + int wrapWidth; + int orientation; + int indent; + boolean justify; + int[] tabs; + int[] segments; + StyleItem[] styles; + + StyleItem[][] runs; + int[] lineOffset, lineY, lineWidth; + + static class StyleItem { + TextStyle style; + int start, length, width, ascent, descent; + boolean lineBreak, softBreak, tab; + @Override + public String toString () { + return "StyleItem {" + start + ", " + style + "}"; + } + } + +/** + * Constructs a new instance of this class on the given device. + *

    + * You must dispose the text layout when it is no longer required. + *

    + * + * @param device the device on which to allocate the text layout + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    + * + * @see #dispose() + */ +public TextLayout (Device device) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + wrapWidth = ascent = descent = -1; + lineSpacing = 0; + orientation = SWT.LEFT_TO_RIGHT; + styles = new StyleItem[2]; + styles[0] = new StyleItem(); + styles[1] = new StyleItem(); + text = ""; //$NON-NLS-1$ + if (device.tracking) device.new_Object(this); +} + +void checkLayout () { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); +} + +void computeRuns (GC gc) { + if (runs != null) return; + boolean newGC = gc == null; + if (newGC) gc = new GC (device); + StyleItem[] allRuns = itemize(); + for (int i=0; i lineWidth) { + run.width = tabs[j] - lineWidth; + break; + } + } + if (j == tabsLength) { + int tabX = tabs[tabsLength-1]; + int lastTabWidth = tabsLength > 1 ? tabs[tabsLength-1] - tabs[tabsLength-2] : tabs[0]; + if (lastTabWidth > 0) { + while (tabX <= lineWidth) tabX += lastTabWidth; + run.width = tabX - lineWidth; + } + } + break; + } + case '\n': + run.lineBreak = true; + run.width = 0; + break; + case '\r': + run.lineBreak = true; + run.width = 0; + StyleItem next = allRuns[i + 1]; + if (next.length != 0 && text.charAt(next.start) == '\n') { + run.length += 1; + i++; + } + break; + } + } + if (wrapWidth != -1 && lineWidth + run.width > wrapWidth && !run.tab) { + int start = 0; + gc.setFont(getItemFont(run)); + char[] chars = new char[run.length]; + text.getChars(run.start, run.start + run.length, chars, 0); + if (!(run.style != null && run.style.metrics != null)) { + int width = 0, maxWidth = wrapWidth - lineWidth; + int charWidth = gc.stringExtent(String.valueOf(chars[start])).x; + while (width + charWidth < maxWidth) { + width += charWidth; + start++; + charWidth = gc.stringExtent(String.valueOf(chars[start])).x; + } + } + int firstStart = start; + int firstIndice = i; + while (i >= lineStart) { + chars = new char[run.length]; + text.getChars(run.start, run.start + run.length, chars, 0); + while(start >= 0) { + if (Character.isSpaceChar(chars[start]) || Character.isWhitespace(chars[start])) break; + start--; + } + if (start >= 0 || i == lineStart) break; + run = allRuns[--i]; + start = run.length - 1; + } + if (start == 0 && i != lineStart) { + run = allRuns[--i]; + } else if (start <= 0 && i == lineStart) { + i = firstIndice; + run = allRuns[i]; + start = Math.max(1, firstStart); + } + chars = new char[run.length]; + text.getChars(run.start, run.start + run.length, chars, 0); + while (start < run.length) { + if (!Character.isWhitespace(chars[start])) break; + start++; + } + if (0 < start && start < run.length) { + StyleItem newRun = new StyleItem(); + newRun.start = run.start + start; + newRun.length = run.length - start; + newRun.style = run.style; + run.length = start; + gc.setFont(getItemFont(run)); + place (gc, run); + place (gc, newRun); + StyleItem[] newAllRuns = new StyleItem[allRuns.length + 1]; + System.arraycopy(allRuns, 0, newAllRuns, 0, i + 1); + System.arraycopy(allRuns, i + 1, newAllRuns, i + 2, allRuns.length - i - 1); + allRuns = newAllRuns; + allRuns[i + 1] = newRun; + } + if (i != allRuns.length - 2) { + run.softBreak = run.lineBreak = true; + } + } + lineWidth += run.width; + if (run.lineBreak) { + lineStart = i + 1; + lineWidth = 0; + lineCount++; + } + } + lineWidth = 0; + runs = new StyleItem[lineCount][]; + lineOffset = new int[lineCount + 1]; + lineY = new int[lineCount + 1]; + this.lineWidth = new int[lineCount]; + int lineRunCount = 0, line = 0; + int ascent = Math.max(0, this.ascent); + int descent = Math.max(0, this.descent); + StyleItem[] lineRuns = new StyleItem[allRuns.length]; + for (int i=0; i + *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the gc is null
    • + *
    + */ +public void draw (GC gc, int x, int y) { + draw(gc, x, y, -1, -1, null, null); +} + +/** + * Draws the receiver's text using the specified GC at the specified + * point. + * + * @param gc the GC to draw + * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn + * @param selectionStart the offset where the selections starts, or -1 indicating no selection + * @param selectionEnd the offset where the selections ends, or -1 indicating no selection + * @param selectionForeground selection foreground, or NULL to use the system default color + * @param selectionBackground selection background, or NULL to use the system default color + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the gc is null
    • + *
    + */ +public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) { + checkLayout(); + if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (selectionForeground != null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (selectionBackground != null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + int length = text.length(); + if (length == 0) return; + computeRuns(gc); + boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1; + if (hasSelection) { + selectionStart = Math.min(Math.max(0, selectionStart), length - 1); + selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1); + if (selectionForeground == null) selectionForeground = device.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); + if (selectionBackground == null) selectionBackground = device.getSystemColor(SWT.COLOR_LIST_SELECTION); + } + final Color foreground = gc.getForeground(); + final Color background = gc.getBackground(); + final Font gcFont = gc.getFont(); + Rectangle clip = gc.getClipping(); + for (int line=0; line clip.x + clip.width) continue; + if (drawX + lineWidth[line] < clip.x) continue; + int baseline = Math.max(0, this.ascent); + for (int i = 0; i < lineRuns.length; i++) { + baseline = Math.max(baseline, lineRuns[i].ascent); + } + int lineHeight = lineY[line+1] - lineY[line]; + Font lastFont = null, currentFont = null; + int drawRunY = 0; + for (int i = 0; i < lineRuns.length; i++) { + StyleItem run = lineRuns[i]; + if (run.length == 0) continue; + if (drawX > clip.x + clip.width) break; + if (drawX + run.width >= clip.x) { + if (!run.lineBreak || run.softBreak) { + currentFont = getItemFont(run); + if (!currentFont.equals(lastFont)) { + gc.setFont(currentFont); + lastFont = currentFont; + } + drawRunY = drawY + (baseline - run.ascent); + int end = run.start + run.length - 1; + boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end; + if (fullSelection) { + gc.setBackground(selectionBackground); + gc.fillRectangle(drawX, drawY, run.width, lineHeight); + if (!run.tab && !(run.style != null && run.style.metrics != null)) { + gc.setForeground(selectionForeground); + String string = text.substring(run.start, run.start + run.length); + gc.drawString(string, drawX, drawRunY, true); + if (run.style != null && run.style.underline) { + int underlineY = drawRunY + run.ascent + 1 - run.style.rise; + gc.drawLine (drawX, underlineY, drawX + run.width, underlineY); + } + if (run.style != null && run.style.strikeout) { + int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1; + gc.drawLine (drawX, strikeoutY, drawX + run.width, strikeoutY); + } + } + } else { + if (run.style != null && run.style.background != null) { + Color bg = run.style.background; + gc.setBackground(bg); + gc.fillRectangle(drawX, drawRunY, run.width, run.ascent + run.descent); + } + if (!run.tab) { + Color fg = foreground; + if (run.style != null && run.style.foreground != null) fg = run.style.foreground; + gc.setForeground(fg); + String string = text.substring(run.start, run.start + run.length); + if (!(run.style != null && run.style.metrics != null)) { + gc.drawString(string, drawX, drawRunY, true); + if (run.style != null && run.style.underline) { + int underlineY = drawRunY + run.ascent + 1 - run.style.rise; + gc.drawLine (drawX, underlineY, drawX + run.width, underlineY); + } + if (run.style != null && run.style.strikeout) { + int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1; + gc.drawLine (drawX, strikeoutY, drawX + run.width, strikeoutY); + } + } + boolean partialSelection = hasSelection && !(selectionStart > end || run.start > selectionEnd); + if (partialSelection) { + int selStart = Math.max(selectionStart, run.start); + int selEnd = Math.min(selectionEnd, end); + string = text.substring(run.start, selStart); + int selX = drawX + gc.stringExtent(string).x; + string = text.substring(selStart, selEnd + 1); + int selWidth = gc.stringExtent(string).x; + gc.setBackground(selectionBackground); + gc.fillRectangle(selX, drawY, selWidth, lineHeight); + if (fg != selectionForeground && !(run.style != null && run.style.metrics != null)) { + gc.setForeground(selectionForeground); + gc.drawString(string, selX, drawRunY, true); + if (run.style != null && run.style.underline) { + int underlineY = drawRunY + run.ascent + 1 - run.style.rise; + gc.drawLine (selX, underlineY, selX + selWidth, underlineY); + } + if (run.style != null && run.style.strikeout) { + int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1; + gc.drawLine (selX, strikeoutY, selX + selWidth, strikeoutY); + } + } + } + } + } + } + } + drawX += run.width; + } + } + gc.setForeground(foreground); + gc.setBackground(background); + gc.setFont(gcFont); +} + +void freeRuns() { + runs = null; +} + +/** + * Returns the receiver's horizontal text alignment, which will be one + * of SWT.LEFT, SWT.CENTER or + * SWT.RIGHT. + * + * @return the alignment used to positioned text horizontally + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getAlignment () { + checkLayout(); + return alignment; +} + +/** + * Returns the ascent of the receiver. + * + * @return the ascent + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getDescent() + * @see #setDescent(int) + * @see #setAscent(int) + * @see #getLineMetrics(int) + */ +public int getAscent () { + checkLayout(); + return ascent; +} + +/** + * Returns the bounds of the receiver. + * + * @return the bounds of the receiver + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Rectangle getBounds () { + checkLayout(); + computeRuns(null); + int width = 0; + if (wrapWidth != -1) { + width = wrapWidth; + } else { + for (int line=0; line + *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • + * + */ +public Rectangle getBounds (int start, int end) { + checkLayout(); + int length = text.length(); + if (length == 0) return new Rectangle(0, 0, 0, 0); + if (start > end) return new Rectangle(0, 0, 0, 0); + start = Math.min(Math.max(0, start), length - 1); + end = Math.min(Math.max(0, end), length - 1); + computeRuns(null); + int startLine = getLineIndex(start); + int endLine = getLineIndex(end); + + Rectangle rect = new Rectangle(0, 0, 0, 0); + rect.y = lineY[startLine]; + rect.height = lineY[endLine + 1] - rect.y - lineSpacing; + if (startLine == endLine) { + rect.x = getLocation(start, false).x; + rect.width = getLocation(end, true).x - rect.x; + } else { + while (startLine <= endLine) { + rect.width = Math.max(rect.width, lineWidth[startLine++]); + } + } + return rect; +} + +/** + * Returns the descent of the receiver. + * + * @return the descent + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getAscent() + * @see #setAscent(int) + * @see #setDescent(int) + * @see #getLineMetrics(int) + */ +public int getDescent () { + checkLayout(); + return descent; +} + +/** + * Returns the default font currently being used by the receiver + * to draw and measure text. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Font getFont () { + checkLayout(); + return font; +} + + +/** +* Returns the receiver's indent. +* +* @return the receiver's indent +* +* @exception SWTException
      +*
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • +*
    +* +* @since 3.2 +*/ +public int getIndent () { + checkLayout(); + return indent; +} + +/** +* Returns the receiver's justification. +* +* @return the receiver's justification +* +* @exception SWTException
      +*
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • +*
    +* +* @since 3.2 +*/ +public boolean getJustify () { + checkLayout(); + return justify; +} + +/** + * Returns the embedding level for the specified character offset. The + * embedding level is usually used to determine the directionality of a + * character in bidirectional text. + * + * @param offset the charecter offset + * @return the embedding level + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the character offset is out of range
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + */ +public int getLevel (int offset) { + checkLayout(); + int length = text.length(); + if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE); + return 0; +} + +/** + * Returns the line offsets. Each value in the array is the + * offset for the first character in a line except for the last + * value, which contains the length of the text. + * + * @return the line offsets + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public int[] getLineOffsets () { + checkLayout(); + computeRuns(null); + int[] offsets = new int[lineOffset.length]; + System.arraycopy(lineOffset, 0, offsets, 0, offsets.length); + return offsets; +} + +/** + * Returns the bounds of the line for the specified line index. + * + * @param lineIndex the line index + * @return the line bounds + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the line index is out of range
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public Rectangle getLineBounds(int lineIndex) { + checkLayout(); + computeRuns(null); + if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE); + int x = getLineIndent(lineIndex); + int y = lineY[lineIndex]; + int width = lineWidth[lineIndex]; + int height = lineY[lineIndex + 1] - y - lineSpacing; + return new Rectangle (x, y, width, height); +} + +/** + * Returns the receiver's line count. This includes lines caused + * by wrapping. + * + * @return the line count + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public int getLineCount () { + checkLayout(); + computeRuns(null); + return runs.length; +} + +int getLineIndent (int lineIndex) { + int lineIndent = 0; + if (lineIndex == 0) { + lineIndent = indent; + } else { + StyleItem[] previousLine = runs[lineIndex - 1]; + StyleItem previousRun = previousLine[previousLine.length - 1]; + if (previousRun.lineBreak && !previousRun.softBreak) { + lineIndent = indent; + } + } + if (wrapWidth != -1) { + boolean partialLine = true; +// if (justify) { +// StyleItem[] lineRun = runs[lineIndex]; +// if (lineRun[lineRun.length - 1].softBreak) { +// partialLine = false; +// } +// } + if (partialLine) { + int lineWidth = this.lineWidth[lineIndex] + lineIndent; + switch (alignment) { + case SWT.CENTER: lineIndent += (wrapWidth - lineWidth) / 2; break; + case SWT.RIGHT: lineIndent += wrapWidth - lineWidth; break; + } + } + } + return lineIndent; +} + +/** + * Returns the index of the line that contains the specified + * character offset. + * + * @param offset the character offset + * @return the line index + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the character offset is out of range
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public int getLineIndex (int offset) { + checkLayout(); + int length = text.length(); + if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE); + computeRuns(null); + for (int line=0; line offset) { + return line; + } + } + return runs.length - 1; +} + +/** + * Returns the font metrics for the specified line index. + * + * @param lineIndex the line index + * @return the font metrics + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the line index is out of range
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public FontMetrics getLineMetrics (int lineIndex) { + checkLayout(); + computeRuns(null); + if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE); + GC gc = new GC(device); + gc.setFont(this.font != null ? this.font : device.getSystemFont()); + FontMetrics metrics = gc.getFontMetrics(); + // This is a bug in SWT: the leading is omited... + // TODO: Check if SWT 3.3+ has added this fix + int ascent = Math.max(metrics.getAscent() + metrics.getLeading(), this.ascent); +// int ascent = Math.max(metrics.getAscent(), this.ascent); + int descent = Math.max(metrics.getDescent(), this.descent); + if (text.length() != 0) { + StyleItem[] lineRuns = runs[lineIndex]; + for (int i = 0; i < lineRuns.length; i++) { + StyleItem run = lineRuns[i]; + if (run.style != null) { + int runAscent = 0; + int runDescent = 0; + if (run.style.metrics != null) { + GlyphMetrics glyphMetrics = run.style.metrics; + runAscent = glyphMetrics.ascent; + runDescent = glyphMetrics.descent; + } else if (run.style.font != null) { + gc.setFont(run.style.font); + metrics = gc.getFontMetrics(); + runAscent = metrics.getAscent(); + runDescent = metrics.getDescent(); + } + ascent = Math.max(ascent, runAscent + run.style.rise); + descent = Math.max(descent, runDescent - run.style.rise); + } + } + } + gc.dispose(); + return FontMetrics.internal_new(ascent, descent, 0, 0, ascent + descent); +} + +/** + * Returns the location for the specified character offset. The + * trailing argument indicates whether the offset + * corresponds to the leading or trailing edge of the cluster. + * + * @param offset the character offset + * @param trailing the trailing flag + * @return the location of the character offset + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getOffset(Point, int[]) + * @see #getOffset(int, int, int[]) + */ +public Point getLocation (int offset, boolean trailing) { + checkLayout(); + int length = text.length(); + if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE); + computeRuns(null); + int line; + for (line=0; line offset) break; + } + line = Math.min(line, runs.length - 1); + StyleItem[] lineRuns = runs[line]; + Point result = null; + if (offset == length) { + result = new Point(lineWidth[line], lineY[line]); + } else { + int width = 0; + for (int i=0; iSWT.MOVEMENT_CHAR, + * SWT.MOVEMENT_CLUSTER or SWT.MOVEMENT_WORD. + * + * @param offset the start offset + * @param movement the movement type + * @return the next offset + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the offset is out of range
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getPreviousOffset(int, int) + */ +public int getNextOffset (int offset, int movement) { + checkLayout(); + computeRuns(null); + int length = text.length(); + if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE); + if (offset == length) return length; + if ((movement & (SWT.MOVEMENT_CHAR | SWT.MOVEMENT_CLUSTER)) != 0) return offset + 1; + int lineEnd = 0; + for (int i=1; i offset) { + lineEnd = Math.max(lineOffset[i - 1], lineOffset[i] - 1); + if (i == runs.length) lineEnd++; + break; + } + } + boolean previousSpaceChar = !Character.isLetterOrDigit(text.charAt(offset)); + offset++; + while (offset < lineEnd) { + boolean spaceChar = !Character.isLetterOrDigit(text.charAt(offset)); + if (!spaceChar && previousSpaceChar) break; + previousSpaceChar = spaceChar; + offset++; + } + return offset; +} + +/** + * Returns the character offset for the specified point. + * For a typical character, the trailing argument will be filled in to + * indicate whether the point is closer to the leading edge (0) or + * the trailing edge (1). When the point is over a cluster composed + * of multiple characters, the trailing argument will be filled with the + * position of the character in the cluster that is closest to + * the point. + * + * @param point the point + * @param trailing the trailing buffer + * @return the character offset + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the trailing length is less than 1
      • + *
      • ERROR_NULL_ARGUMENT - if the point is null
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getLocation(int, boolean) + */ +public int getOffset (Point point, int[] trailing) { + checkLayout(); + if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return getOffset (point.x, point.y, trailing); +} + +/** + * Returns the character offset for the specified point. + * For a typical character, the trailing argument will be filled in to + * indicate whether the point is closer to the leading edge (0) or + * the trailing edge (1). When the point is over a cluster composed + * of multiple characters, the trailing argument will be filled with the + * position of the character in the cluster that is closest to + * the point. + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @param trailing the trailing buffer + * @return the character offset + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the trailing length is less than 1
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getLocation(int, boolean) + */ +public int getOffset (int x, int y, int[] trailing) { + checkLayout(); + if (trailing != null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + computeRuns(null); + int line; + int lineCount = runs.length; + for (line=0; line y) break; + } + line = Math.min(line, runs.length - 1); + x -= getLineIndent(line); + if (x >= lineWidth[line]) x = lineWidth[line] - 1; + if (x < 0) x = 0; + StyleItem[] lineRuns = runs[line]; + int width = 0; + for (int i = 0; i < lineRuns.length; i++) { + StyleItem run = lineRuns[i]; + if (run.lineBreak && !run.softBreak) return run.start; + if (width + run.width > x) { + if (run.style != null && run.style.metrics != null) { + int xRun = x - width; + GlyphMetrics metrics = run.style.metrics; + if (metrics.width > 0) { + if (trailing != null) { + trailing[0] = (xRun % metrics.width < metrics.width / 2) ? 0 : 1; + } + return run.start + xRun / metrics.width; + } + } + if (run.tab) { + if (trailing != null) { + trailing[0] = x < (width + run.width / 2) ? 0 : 1; + } + return run.start; + } + int offset = 0; + GC gc = new GC(device); + gc.setFont(getItemFont(run)); + char[] chars = new char[run.length]; + text.getChars(run.start, run.start + run.length, chars, 0); + for (offset = 0; offset < chars.length; offset++) { + int charWidth = gc.stringExtent(String.valueOf(chars[offset])).x; + if (width + charWidth > x) { + if (trailing != null) { + trailing[0] = x < (width + charWidth / 2) ? 0 : 1; + } + break; + } + width += charWidth; + } + gc.dispose(); + return run.start + offset; + } + width += run.width; + } + if (trailing != null) trailing[0] = 0; + return lineOffset[line + 1]; +} + +/** + * Returns the orientation of the receiver. + * + * @return the orientation style + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + */ +public int getOrientation () { + checkLayout(); + return orientation; +} + +/** + * Returns the previous offset for the specified offset and movement + * type. The movement is one of SWT.MOVEMENT_CHAR, + * SWT.MOVEMENT_CLUSTER or SWT.MOVEMENT_WORD. + * + * @param offset the start offset + * @param movement the movement type + * @return the previous offset + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the offset is out of range
      • + *
      + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getNextOffset(int, int) + */ +public int getPreviousOffset (int offset, int movement) { + checkLayout(); + computeRuns(null); + int length = text.length(); + if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE); + if (offset == 0) return 0; + if ((movement & (SWT.MOVEMENT_CHAR | SWT.MOVEMENT_CLUSTER)) != 0) return offset - 1; + int lineStart = 0; + for (int i=0; i offset) { + lineStart = lineOffset[i]; + break; + } + } + offset--; + boolean previousSpaceChar = !Character.isLetterOrDigit(text.charAt(offset)); + while (lineStart < offset) { + boolean spaceChar = !Character.isLetterOrDigit(text.charAt(offset - 1)); + if (spaceChar && !previousSpaceChar) break; + offset--; + previousSpaceChar = spaceChar; + } + return offset; +} + +/** + * Gets the ranges of text that are associated with a TextStyle. + * + * @return the ranges, an array of offsets representing the start and end of each + * text style. + * + * @exception SWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @see #getStyles() + * + * @since 3.2 + */ +public int[] getRanges () { + checkLayout(); + int[] result = new int[styles.length * 2]; + int count = 0; + for (int i=0; i + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getSpacing () { + checkLayout(); + return lineSpacing; +} + +/** + * Returns the text segments offsets of the receiver. + * + * @return the text segments offsets + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int[] getSegments() { + checkLayout(); + return segments; +} + +/** + * Gets the style of the receiver at the specified character offset. + * + * @param offset the text offset + * @return the style or null if not set + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the character offset is out of range
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public TextStyle getStyle (int offset) { + checkLayout(); + int length = text.length(); + if (!(0 <= offset && offset < length)) SWT.error(SWT.ERROR_INVALID_RANGE); + for (int i=1; i offset) { + return styles[i - 1].style; + } + } + return null; +} + +/** + * Gets all styles of the receiver. + * + * @return the styles + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getRanges() + * + * @since 3.2 + */ +public TextStyle[] getStyles () { + checkLayout(); + TextStyle[] result = new TextStyle[styles.length]; + int count = 0; + for (int i=0; i + *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • + * + */ +public int[] getTabs () { + checkLayout(); + return tabs; +} + +/** + * Gets the receiver's text, which will be an empty + * string if it has never been set. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public String getText () { + checkLayout(); + return text; +} + +/** + * Returns the width of the receiver. + * + * @return the width + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getWidth () { + checkLayout(); + return wrapWidth; +} + +/** + * Returns true if the text layout has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the text layout. + * When a text layout has been disposed, it is an error to + * invoke any other method using the text layout. + *

    + * + * @return true when the text layout is disposed and false otherwise + */ +@Override +public boolean isDisposed () { + return device == null; +} + +/* + * Itemize the receiver text, create run for + */ +StyleItem[] itemize () { + int length = text.length(); + if (length == 0) { + return new StyleItem[]{new StyleItem(), new StyleItem()}; + } + int runCount = 0, start = 0; + StyleItem[] runs = new StyleItem[length]; + char[] chars = text.toCharArray(); + for (int i = 0; iSWT.LEFT, SWT.RIGHT or SWT.CENTER. + *

    + * The default alignment is SWT.LEFT. Note that the receiver's + * width must be set in order to use SWT.RIGHT or SWT.CENTER + * alignment. + *

    + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setWidth(int) + */ +public void setAlignment (int alignment) { + checkLayout(); + int mask = SWT.LEFT | SWT.CENTER | SWT.RIGHT; + alignment &= mask; + if (alignment == 0) return; + if ((alignment & SWT.LEFT) != 0) alignment = SWT.LEFT; + if ((alignment & SWT.RIGHT) != 0) alignment = SWT.RIGHT; + freeRuns(); + this.alignment = alignment; +} + +/** + * Sets the ascent of the receiver. The ascent is distance in pixels + * from the baseline to the top of the line and it is applied to all + * lines. The default value is -1 which means that the + * ascent is calculated from the line fonts. + * + * @param ascent the new ascent + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the ascent is less than -1
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setDescent(int) + * @see #getLineMetrics(int) + */ +public void setAscent (int ascent) { + checkLayout(); + if (ascent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.ascent == ascent) return; + freeRuns(); + this.ascent = ascent; +} + +/** + * Sets the descent of the receiver. The descent is distance in pixels + * from the baseline to the bottom of the line and it is applied to all + * lines. The default value is -1 which means that the + * descent is calculated from the line fonts. + * + * @param descent the new descent + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the descent is less than -1
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setAscent(int) + * @see #getLineMetrics(int) + */ +public void setDescent (int descent) { + checkLayout(); + if (descent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.descent == descent) return; + freeRuns(); + this.descent = descent; +} + +/** + * Sets the default font which will be used by the receiver + * to draw and measure text. If the + * argument is null, then a default font appropriate + * for the platform will be used instead. Note that a text + * style can override the default font. + * + * @param font the new font for the receiver, or null to indicate a default font + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the font has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setFont (Font font) { + checkLayout (); + if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.font == font) return; + if (font != null && font.equals(this.font)) return; + freeRuns(); + this.font = font; +} + +/** + * Sets the indent of the receiver. This indent it applied of the first line of + * each paragraph. + * + * @param indent new indent + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.2 + */ +public void setIndent (int indent) { + checkLayout(); + if (indent < 0) return; + if (this.indent == indent) return; + freeRuns(); + this.indent = indent; +} + +/** + * Sets the justification of the receiver. Note that the receiver's + * width must be set in order to use justification. + * + * @param justify new justify + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.2 + */ +public void setJustify (boolean justify) { + checkLayout(); + if (this.justify == justify) return; + freeRuns(); + this.justify = justify; +} + +/** + * Sets the orientation of the receiver, which must be one + * of SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. + * + * @param orientation new orientation style + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setOrientation (int orientation) { + checkLayout(); + int mask = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT; + orientation &= mask; + if (orientation == 0) return; + if ((orientation & SWT.LEFT_TO_RIGHT) != 0) orientation = SWT.LEFT_TO_RIGHT; + this.orientation = orientation; +} + +/** + * Sets the line spacing of the receiver. The line spacing + * is the space left between lines. + * + * @param spacing the new line spacing + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the spacing is negative
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setSpacing (int spacing) { + checkLayout(); + if (spacing < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.lineSpacing == spacing) return; + freeRuns(); + this.lineSpacing = spacing; +} + +/** + * Sets the offsets of the receiver's text segments. Text segments are used to + * override the default behaviour of the bidirectional algorithm. + * Bidirectional reordering can happen within a text segment but not + * between two adjacent segments. + *

    + * Each text segment is determined by two consecutive offsets in the + * segments arrays. The first element of the array should + * always be zero and the last one should always be equals to length of + * the text. + *

    + * + * @param segments the text segments offset + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setSegments(int[] segments) { + checkLayout(); + if (this.segments == null && segments == null) return; + if (this.segments != null && segments !=null) { + if (this.segments.length == segments.length) { + int i; + for (i = 0; i + *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • + * + */ +public void setStyle (TextStyle style, int start, int end) { + checkLayout(); + int length = text.length(); + if (length == 0) return; + if (start > end) return; + start = Math.min(Math.max(0, start), length - 1); + end = Math.min(Math.max(0, end), length - 1); + int low = -1; + int high = styles.length; + while (high - low > 1) { + int index = (high + low) / 2; + if (styles[index + 1].start > start) { + high = index; + } else { + low = index; + } + } + if (0 <= high && high < styles.length) { + StyleItem item = styles[high]; + if (item.start == start && styles[high + 1].start - 1 == end) { + if (style == null) { + if (item.style == null) return; + } else { + if (style.equals(item.style)) return; + } + } + } + freeRuns(); + int modifyStart = high; + int modifyEnd = modifyStart; + while (modifyEnd < styles.length) { + if (styles[modifyEnd + 1].start > end) break; + modifyEnd++; + } + if (modifyStart == modifyEnd) { + int styleStart = styles[modifyStart].start; + int styleEnd = styles[modifyEnd + 1].start - 1; + if (styleStart == start && styleEnd == end) { + styles[modifyStart].style = style; + return; + } + if (styleStart != start && styleEnd != end) { + StyleItem[] newStyles = new StyleItem[styles.length + 2]; + System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1); + StyleItem item = new StyleItem(); + item.start = start; + item.style = style; + newStyles[modifyStart + 1] = item; + item = new StyleItem(); + item.start = end + 1; + item.style = styles[modifyStart].style; + newStyles[modifyStart + 2] = item; + System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1); + styles = newStyles; + return; + } + } + if (start == styles[modifyStart].start) modifyStart--; + if (end == styles[modifyEnd + 1].start - 1) modifyEnd++; + int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1); + StyleItem[] newStyles = new StyleItem[newLength]; + System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1); + StyleItem item = new StyleItem(); + item.start = start; + item.style = style; + newStyles[modifyStart + 1] = item; + styles[modifyEnd].start = end + 1; + System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd); + styles = newStyles; +} + +/** + * Sets the receiver's tab list. Each value in the tab list specifies + * the space in pixels from the origin of the text layout to the respective + * tab stop. The last tab stop width is repeated continuously. + * + * @param tabs the new tab list + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setTabs (int[] tabs) { + checkLayout(); + if (this.tabs == null && tabs == null) return; + if (this.tabs != null && tabs !=null) { + if (this.tabs.length == tabs.length) { + int i; + for (i = 0; i + *
  • ERROR_NULL_ARGUMENT - if the text is null
  • + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setText (String text) { + checkLayout(); + if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (text.equals(this.text)) return; + freeRuns(); + this.text = text; + styles = new StyleItem[2]; + styles[0] = new StyleItem(); + styles[1] = new StyleItem(); + styles[1].start = text.length(); +} + +/** + * Sets the line width of the receiver, which determines how + * text should be wrapped and aligned. The default value is + * -1 which means wrapping is disabled. + * + * @param width the new width + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the width is 0 or less than -1
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setAlignment(int) + */ +public void setWidth (int width) { + checkLayout(); + if (width < -1 || width == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.wrapWidth == width) return; + freeRuns(); + this.wrapWidth = width; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +@Override +public String toString () { + if (isDisposed()) return "TextLayout {*DISPOSED*}"; + return "TextLayout {}"; +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java new file mode 100644 index 00000000000..6f64fcb1bc9 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java @@ -0,0 +1,324 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; + +import org.eclipse.swt.SWT; + +/** + * Instances of this class represent transformation matrices for + * points expressed as (x, y) pairs of floating point numbers. + *

    + * Application code must explicitly invoke the Transform.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

    + * + * @since 3.1 + */ +public class Transform extends Resource { + + /** + * the OS resource for the Transform + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public AffineTransform handle; + +/** + * Constructs a new identity Transform. + * + * @param device the device on which to allocate the Transform + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Transform (Device device) { + this(device, 1, 0, 0, 1, 0, 0); +} + +/** + * Constructs a new Transform given an array of elements that represent the + * matrix that describes the transformation. + * + * @param device the device on which to allocate the Transform + * @param elements an array of floats that describe the transformation matrix + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device, or the elements array is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the elements array is too small to hold the matrix values
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Transform(Device device, float[] elements) { + this (device, checkTransform(elements)[0], elements[1], elements[2], elements[3], elements[4], elements[5]); +} + +/** + * Constructs a new Transform given all of the elements that represent the + * matrix that describes the transformation. + * + * @param device the device on which to allocate the Transform + * @param m11 the first element of the first row of the matrix + * @param m12 the second element of the first row of the matrix + * @param m21 the first element of the second row of the matrix + * @param m22 the second element of the second row of the matrix + * @param dx the third element of the first row of the matrix + * @param dy the third element of the second row of the matrix + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if device is null and there is no current device
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li> + *
    + * + * @see #dispose() + */ +public Transform (Device device, float m11, float m12, float m21, float m22, float dx, float dy) { + if (device == null) device = Device.getDevice(); + if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.device = device; + handle = new AffineTransform(m11, m12, m21, m22, dx, dy); + if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES); + if (device.tracking) device.new_Object(this); +} + +static float[] checkTransform(float[] elements) { + if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + return elements; +} + +/** + * Disposes of the operating system resources associated with + * the Transform. Applications must dispose of all Transforms that + * they allocate. + */ +public void dispose() { + if (handle == null) return; + if (device.isDisposed()) return; + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Fills the parameter with the values of the transformation matrix + * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}. + * + * @param elements array to hold the matrix values + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the matrix values
    • + *
    + */ +public void getElements(float[] elements) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + double[] matrix = new double[6]; + handle.getMatrix(matrix); + for (int i = 0; i < 6; i++) { + elements[i] = (float) matrix[i]; + } +} + +/** + * Modifies the receiver such that the matrix it represents becomes the + * the mathematical inverse of the matrix it previously represented. + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_CANNOT_INVERT_MATRIX - if the matrix is not invertable
    • + *
    + */ +public void invert() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + try { + handle = handle.createInverse(); + } catch (NoninvertibleTransformException e) { + SWT.error(SWT.ERROR_CANNOT_INVERT_MATRIX); + } +} + +/** + * Returns true if the Transform has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the Transform. + * When a Transform has been disposed, it is an error to + * invoke any other method using the Transform. + * + * @return true when the Transform is disposed, and false otherwise + */ +public boolean isDisposed() { + return handle == null; +} + +/** + * Returns true if the Transform represents the identity matrix + * and false otherwise. + * + * @return true if the receiver is an identity Transform, and false otherwise + */ +public boolean isIdentity() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + return handle.isIdentity(); +} + +/** + * Modifies the receiver such that the matrix it represents becomes the + * the result of multiplying the matrix it previously represented by the + * argument. + * + * @param matrix the matrix to multiply the receiver by + * + * @exception SWTException

      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parameter is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parameter has been disposed
    • + *
    + */ +public void multiply(Transform matrix) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (matrix == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (matrix.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + handle.concatenate(matrix.handle); +} + +/** + * Modifies the receiver so that it represents a transformation that is + * equivalent to its previous transformation rotated by the specified angle. + * The angle is specified in degrees and for the identity transform 0 degrees + * is at the 3 o'clock position. A positive value indicates a clockwise rotation + * while a negative value indicates a counter-clockwise rotation. + * + * @param angle the angle to rotate the transformation by + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void rotate(float angle) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.rotate(angle * Math.PI / 180); +} + +/** + * Modifies the receiver so that it represents a transformation that is + * equivalent to its previous transformation scaled by (scaleX, scaleY). + * + * @param scaleX the amount to scale in the X direction + * @param scaleY the amount to scale in the Y direction + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void scale(float scaleX, float scaleY) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.scale(scaleX, scaleY); +} + +/** + * Modifies the receiver to represent a new transformation given all of + * the elements that represent the matrix that describes that transformation. + * + * @param m11 the first element of the first row of the matrix + * @param m12 the second element of the first row of the matrix + * @param m21 the first element of the second row of the matrix + * @param m22 the second element of the second row of the matrix + * @param dx the third element of the first row of the matrix + * @param dy the third element of the second row of the matrix + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void setElements(float m11, float m12, float m21, float m22, float dx, float dy) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.setTransform(m11, m12, m21, m22, dx, dy); +} + +/** + * Given an array containing points described by alternating x and y values, + * modify that array such that each point has been replaced with the result of + * applying the transformation represented by the receiver to that point. + * + * @param pointArray an array of alternating x and y values to be transformed + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void transform(float[] pointArray) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + handle.transform(pointArray, 0, pointArray, 0, pointArray.length); +} + +/** + * Modifies the receiver so that it represents a transformation that is + * equivalent to its previous transformation translated by (offsetX, offsetY). + * + * @param offsetX the distance to translate in the X direction + * @param offsetY the distance to translate in the Y direction + * + * @exception SWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void translate(float offsetX, float offsetY) { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + handle.translate(offsetX, offsetY); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString() { + if (isDisposed()) return "Transform {*DISPOSED*}"; + float[] elements = new float[6]; + getElements(elements); + return "Transform {" + elements [0] + "," + elements [1] + "," +elements [2] + "," +elements [3] + "," +elements [4] + "," +elements [5] + "}"; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.gif b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.gif new file mode 100644 index 0000000000000000000000000000000000000000..ddc2ea121f059c7823a6ac5ebab1bd9464d7e3b1 GIT binary patch literal 176 zcmZ?wbhEHbRA5kGIK%(~XU_ajOPiUNmS$|6_W%F?GeG|T|B63Z7`YhO8FWA@Kx!G7 zODlHW`DbuyC&OO8h%=5iWS(*+Nc1kzT)5JBkK%1D{lvr5ZTQO)g-b an(7N%xvM+6dwTo&Crq3)d5Rz>gEav2Ur2QT literal 0 HcmV?d00001 diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties new file mode 100644 index 00000000000..cc41f6118c8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties @@ -0,0 +1,13 @@ +# +# @(#) OnItemCursor.properties 1.2 - last change made 07/07/98 +# +# Cursors Properties file +# +# Names GIF89 sources for Custom Cursors and their associated HotSpots +# +# +# The syntax is: Cursor.File= +# Cursor.HotSpot=, +# +Cursor.File=HelpCursor.gif +Cursor.HotSpot=5,2 diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.gif b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.gif new file mode 100644 index 0000000000000000000000000000000000000000..692b1b357edd68150930154ba03ead712e7f3c5f GIT binary patch literal 1341 zcmcK3`%jZ+6bJC4ZQou2DPXxMr4+EGTv~dy;ApAbid=_Z+eA#A!)>T7sV@!s*F=dXgVY_A|veTZ+??0bL5{sW^QTPM6^H z6hB=8uvCDh;aCceN&T2~B``A5aYh=>PRH39fFlDOIpAi3U^yP9h7npAsfE$m5R(He z9bg#%lL1VQW9g8g01O#m$Z>`YGL?Xt3786;DT6E(U@0LxKn>V(z|I701-8wgu)^1)XakDQeI2DoF}Wzlh+>UsLmu3qM;r4|d?6AB6hUDDNGL+00236MP+}2E zG@+zzXj3T?mmomu!4q|-~fykxVNboY`w`pBLAWJ^EUdI&OWh*J=OVSFMu^q|GFViZKq6R8zkkUfvY(#bg zk<&!z9Z>IBHaKyk3v6{S8(ll(-3q>7+HG*(**E$^rf=-IVo!|J&e(&3 zKEba4en5HQ*3~QYvoq+zn*KhTo81<3dojHKI(9bV;0RT8_;M#E`L=1UwP$*mdRY>- ze4oiUJX@7=Vqh?6ns&Cls4w}&)wa#nprH`qgyX^i6vlT)H=* zi4P9{OO?Vp;$EEH`;wM~uQVT{oToDw;g^2eST;Uc-2H^pl!x_XClsVQy9BmwV!_+T zeDu6|TS7bE>ox9}@b+VC`5)PY9w_i;^7mv8@)gsse4*p;;`wf`&)ci!4K>$v3TZjR^ytt zW@VsaVT_TGyjxtO4-Xm-4;2p&6rZ2Cx3|)ekff!hv&hKH&d$%Hq{V7%jg^> 8) & 0xFF); +// byte transBlue = (byte)((background >> 16) & 0xFF); +// final int spinc = dibBM.bmWidthBytes - srcWidth * 4; +// int sp = 3; +// for (int y = 0; y < srcHeight; ++y) { +// for (int x = 0; x < srcWidth; ++x) { +// srcData [sp] = (srcData[sp-1] == transRed && srcData[sp-2] == transGreen && srcData[sp-3] == transBlue) ? 0 : (byte)255; +// sp += 4; +// } +// sp += spinc; +// } +// } +// OS.MoveMemory (dibBM.bmBits, srcData, sizeInBytes); +// +// /* Stretch and free resources */ +// if (srcWidth != destWidth || srcHeight != destHeight) { +// BITMAPINFOHEADER bmiHeader2 = new BITMAPINFOHEADER (); +// bmiHeader2.biSize = BITMAPINFOHEADER.sizeof; +// bmiHeader2.biWidth = destWidth; +// bmiHeader2.biHeight = -destHeight; +// bmiHeader2.biPlanes = 1; +// bmiHeader2.biBitCount = 32; +// bmiHeader2.biCompression = OS.BI_RGB; +// byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof]; +// OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof); +// long [] pBits2 = new long [1]; +// long memDib2 = OS.CreateDIBSection (0, bmi2, OS.DIB_RGB_COLORS, pBits2, 0, 0); +// long memHdc2 = OS.CreateCompatibleDC (hdc); +// long oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2); +// OS.SetStretchBltMode(memHdc2, OS.COLORONCOLOR); +// OS.StretchBlt (memHdc2, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY); +// OS.SelectObject (memHdc2, oldMemBitmap2); +// OS.DeleteDC (memHdc2); +// OS.SelectObject (memHdc, oldMemBitmap); +// OS.DeleteDC (memHdc); +// OS.DeleteObject (memDib); +// memDib = memDib2; +// } else { +// OS.SelectObject (memHdc, oldMemBitmap); +// OS.DeleteDC (memHdc); +// } +// OS.SelectObject (srcHdc, oldSrcBitmap); +// OS.DeleteDC (srcHdc); +// OS.ReleaseDC (0, hdc); +// return memDib; +//} +// +//long createMaskFromAlpha (ImageData data, int destWidth, int destHeight) { +// int srcWidth = data.width; +// int srcHeight = data.height; +// ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1, +// new PaletteData(new RGB [] {new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)}), +// 2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0); +// int ap = 0; +// for (int y = 0; y < mask.height; y++) { +// for (int x = 0; x < mask.width; x++) { +// mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0); +// } +// } +// long hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data); +// if (srcWidth != destWidth || srcHeight != destHeight) { +// long hdc = OS.GetDC (0); +// long hdc1 = OS.CreateCompatibleDC (hdc); +// OS.SelectObject (hdc1, hMask); +// long hdc2 = OS.CreateCompatibleDC (hdc); +// long hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null); +// OS.SelectObject (hdc2, hMask2); +// OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR); +// OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY); +// OS.DeleteDC (hdc1); +// OS.DeleteDC (hdc2); +// OS.ReleaseDC (0, hdc); +// OS.DeleteObject(hMask); +// hMask = hMask2; +// } +// return hMask; +//} +// +//long createMask (long hBitmap, int destWidth, int destHeight, int background, int transparentPixel) { +// BITMAP bm = new BITMAP (); +// OS.GetObject (hBitmap, BITMAP.sizeof, bm); +// int srcWidth = bm.bmWidth; +// int srcHeight = bm.bmHeight; +// long hMask = OS.CreateBitmap (destWidth, destHeight, 1, 1, null); +// long hDC = OS.GetDC (0); +// long hdc1 = OS.CreateCompatibleDC (hDC); +// if (background != -1) { +// OS.SelectObject (hdc1, hBitmap); +// +// /* +// * If the image has a palette with multiple entries having +// * the same color and one of those entries is the transparentPixel, +// * only the first entry becomes transparent. To avoid this +// * problem, temporarily change the image palette to a palette +// * where the transparentPixel is white and everything else is +// * black. +// */ +// boolean isDib = bm.bmBits != 0; +// byte[] originalColors = null; +// if (transparentPixel != -1 && isDib && bm.bmBitsPixel <= 8) { +// int maxColors = 1 << bm.bmBitsPixel; +// byte[] oldColors = new byte[maxColors * 4]; +// OS.GetDIBColorTable(hdc1, 0, maxColors, oldColors); +// int offset = transparentPixel * 4; +// byte[] newColors = new byte[oldColors.length]; +// newColors[offset] = (byte)0xFF; +// newColors[offset+1] = (byte)0xFF; +// newColors[offset+2] = (byte)0xFF; +// OS.SetDIBColorTable(hdc1, 0, maxColors, newColors); +// originalColors = oldColors; +// OS.SetBkColor (hdc1, 0xFFFFFF); +// } else { +// OS.SetBkColor (hdc1, background); +// } +// +// long hdc2 = OS.CreateCompatibleDC (hDC); +// OS.SelectObject (hdc2, hMask); +// if (destWidth != srcWidth || destHeight != srcHeight) { +// OS.SetStretchBltMode (hdc2, OS.COLORONCOLOR); +// OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY); +// } else { +// OS.BitBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, OS.SRCCOPY); +// } +// OS.DeleteDC (hdc2); +// +// /* Put back the original palette */ +// if (originalColors != null) OS.SetDIBColorTable(hdc1, 0, 1 << bm.bmBitsPixel, originalColors); +// } else { +// long hOldBitmap = OS.SelectObject (hdc1, hMask); +// OS.PatBlt (hdc1, 0, 0, destWidth, destHeight, OS.BLACKNESS); +// OS.SelectObject (hdc1, hOldBitmap); +// } +// OS.ReleaseDC (0, hDC); +// OS.DeleteDC (hdc1); +// return hMask; +//} +// +public void dispose () { +// if (handle != 0) OS.ImageList_Destroy (handle); +// handle = 0; +// images = null; +} +// +//public Image get (int index) { +// return images [index]; +//} +// +//public int getStyle () { +// return style; +//} +// +//public long getHandle () { +// return handle; +//} +// +//public Point getImageSize() { +// int [] cx = new int [1], cy = new int [1]; +// OS.ImageList_GetIconSize (handle, cx, cy); +// return new Point (cx [0], cy [0]); +//} +// +//public int indexOf (Image image) { +// int count = OS.ImageList_GetImageCount (handle); +// for (int i=0; i + *
    Styles:
    + *
    ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT
    + *
    UP, DOWN, LEFT, RIGHT, CENTER
    + *
    Events:
    + *
    Selection
    + * + *

    + * Note: Only one of the styles ARROW, CHECK, PUSH, RADIO, and TOGGLE + * may be specified. + *

    + * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified. + *

    + * Note: Only one of the styles UP, DOWN, LEFT, and RIGHT may be specified + * when the ARROW style is specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class Button extends Control { + Image image; + ImageList imageList; + boolean ignoreMouse; + String text; +// static final int ButtonProc; +// static final TCHAR ButtonClass = new TCHAR (0,"BUTTON", true); +// static final char [] SCROLLBAR = new char [] {'S', 'C', 'R', 'O', 'L', 'L', 'B', 'A', 'R', 0}; +// static final int CheckWidth, CheckHeight; +// static { +// int hBitmap = OS.LoadBitmap (0, OS.OBM_CHECKBOXES); +// if (hBitmap == 0) { +// CheckWidth = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CXSMICON : OS.SM_CXVSCROLL); +// CheckHeight = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CYSMICON : OS.SM_CYVSCROLL); +// } else { +// BITMAP bitmap = new BITMAP (); +// OS.GetObject (hBitmap, BITMAP.sizeof, bitmap); +// OS.DeleteObject (hBitmap); +// CheckWidth = bitmap.bmWidth / 4; +// CheckHeight = bitmap.bmHeight / 3; +// } +// WNDCLASS lpWndClass = new WNDCLASS (); +// OS.GetClassInfo (0, ButtonClass, lpWndClass); +// ButtonProc = lpWndClass.lpfnWndProc; +// } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#ARROW + * @see SWT#CHECK + * @see SWT#PUSH + * @see SWT#RADIO + * @see SWT#TOGGLE + * @see SWT#FLAT + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#CENTER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Button (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the control is selected. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// if (handle == 0) return 0; +// return OS.CallWindowProc (ButtonProc, hwnd, msg, wParam, lParam); +//} + +static int checkStyle (int style) { + style = checkBits (style, SWT.PUSH, SWT.ARROW, SWT.CHECK, SWT.RADIO, SWT.TOGGLE, 0); + if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) { + return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0); + } + if ((style & (SWT.CHECK | SWT.RADIO)) != 0) { + return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0); + } + if ((style & SWT.ARROW) != 0) { + style |= SWT.NO_FOCUS; + return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0); + } + return style; +} + +void click () { + ((CButton)handle).doClick(); +// /* +// * Feature in Windows. BM_CLICK sends a fake WM_LBUTTONDOWN and +// * WM_LBUTTONUP in order to click the button. This causes the +// * application to get unexpected mouse events. The fix is to +// * ignore mouse events when they are caused by BM_CLICK. +// */ +// ignoreMouse = true; +// OS.SendMessage (handle, OS.BM_CLICK, 0, 0); +// ignoreMouse = false; +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// int border = getBorderWidth (); +// int width = 0, height = 0; +// if ((style & SWT.ARROW) != 0) { +// if ((style & (SWT.UP | SWT.DOWN)) != 0) { +// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// height += OS.GetSystemMetrics (OS.SM_CYVSCROLL); +// } else { +// width += OS.GetSystemMetrics (OS.SM_CXHSCROLL); +// height += OS.GetSystemMetrics (OS.SM_CYHSCROLL); +// } +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// width += border * 2; height += border * 2; +// return new Point (width, height); +// } +// int extra = 0; +// boolean hasImage; +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST(); +// OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, buttonImageList); +// hasImage = buttonImageList.himl != 0; +// } else { +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) != 0; +// } +// if (!hasImage) { +// int oldFont = 0; +// int hDC = OS.GetDC (handle); +// int newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, lptm); +// int length = OS.GetWindowTextLength (handle); +// if (length == 0) { +// height += lptm.tmHeight; +// } else { +// extra = Math.max (8, lptm.tmAveCharWidth); +// TCHAR buffer = new TCHAR (getCodePage (), length + 1); +// OS.GetWindowText (handle, buffer, length + 1); +// RECT rect = new RECT (); +// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE; +// OS.DrawText (hDC, buffer, length, rect, flags); +// width += rect.right - rect.left; +// height += rect.bottom - rect.top; +// } +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// } else { +// if (image != null) { +// Rectangle rect = image.getBounds (); +// width = rect.width; +// height = rect.height; +// extra = 8; +// } +// } +// if ((style & (SWT.CHECK | SWT.RADIO)) != 0) { +// width += CheckWidth + extra; +// height = Math.max (height, CheckHeight + 3); +// } +// if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) { +// width += 12; height += 10; +// } +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// width += border * 2; height += border * 2; +// return new Point (width, height); +//} + +@Override +public Point computeSize(int wHint, int hHint, boolean changed) { + Point size = super.computeSize(wHint, hHint, changed); + if ((style & SWT.ARROW) != 0) { + if(wHint == SWT.DEFAULT) { + size.x = size.y; + } else if(hHint == SWT.DEFAULT) { + size.y = size.x; + } else { + size.x = size.y; + } + } + return size; +} + +@Override +Container createHandle () { + return (Container)CButton.Factory.newInstance(this, style); +} + +//int defaultBackground () { +// if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) { +// return OS.GetSysColor (OS.COLOR_BTNFACE); +// } +// return super.defaultBackground (); +//} + +//int defaultForeground () { +// return OS.GetSysColor (OS.COLOR_BTNTEXT); +//} + +/** + * Returns a value which describes the position of the + * text or image in the receiver. The value will be one of + * LEFT, RIGHT or CENTER + * unless the receiver is an ARROW button, in + * which case, the alignment will indicate the direction of + * the arrow (one of LEFT, RIGHT, + * UP or DOWN). + * + * @return the alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAlignment () { + checkWidget (); + if ((style & SWT.ARROW) != 0) { + if ((style & SWT.UP) != 0) return SWT.UP; + if ((style & SWT.DOWN) != 0) return SWT.DOWN; + if ((style & SWT.LEFT) != 0) return SWT.LEFT; + if ((style & SWT.RIGHT) != 0) return SWT.RIGHT; + return SWT.UP; + } + if ((style & SWT.LEFT) != 0) return SWT.LEFT; + if ((style & SWT.CENTER) != 0) return SWT.CENTER; + if ((style & SWT.RIGHT) != 0) return SWT.RIGHT; + return SWT.LEFT; +} + +//boolean getDefault () { +// if ((style & SWT.PUSH) == 0) return false; +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// return (bits & OS.BS_DEFPUSHBUTTON) != 0; +//} + +/** + * Returns the receiver's image if it has one, or null + * if it does not. + * + * @return the receiver's image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getImage () { + checkWidget (); + return image; +} + +@Override +String getNameText () { + return getText (); +} + +/** + * Returns true if the receiver is selected, + * and false otherwise. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. When it is of type TOGGLE, + * it is selected when it is pushed in. If the receiver is of any other type, + * this method returns false. + * + * @return the selection state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getSelection () { + checkWidget (); + if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return false; + return ((CButton)handle).isSelected(); +} + +/** + * Returns the receiver's text, which will be an empty + * string if it has never been set or if the receiver is + * an ARROW button. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + if ((style & SWT.ARROW) != 0) return ""; + return text == null? "": text; +} + +@Override +boolean isTabItem () { + //TEMPORARY CODE + //if ((style & SWT.PUSH) != 0) return true; + return super.isTabItem (); +} + +@Override +boolean isTabGroup() { + return (style & SWT.RADIO) == 0; +} + +@Override +boolean mnemonicHit (char ch) { + if (!setFocus ()) return false; + /* + * Feature in Windows. When a radio button gets focus, + * it selects the button in WM_SETFOCUS. Therefore, it + * is not necessary to click the button or send events + * because this has already happened in WM_SETFOCUS. + */ +// if ((style & SWT.RADIO) == 0) click (); + return true; +} + +@Override +boolean mnemonicMatch (char key) { + char mnemonic = findMnemonic (getText ()); + if (mnemonic == '\0') return false; + return Character.toUpperCase (key) == Character.toUpperCase (mnemonic); +} + +@Override +void releaseWidget () { + super.releaseWidget (); + image = null; + if (imageList != null) imageList.dispose (); + imageList = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +//void selectRadio () { +// /* +// * This code is intentionally commented. When two groups +// * of radio buttons with the same parent are separated by +// * another control, the correct behavior should be that +// * the two groups act independently. This is consistent +// * with radio tool and menu items. The commented code +// * implements this behavior. +// */ +//// int index = 0; +//// Control [] children = parent._getChildren (); +//// while (index < children.length && children [index] != this) index++; +//// int i = index - 1; +//// while (i >= 0 && children [i].setRadioSelection (false)) --i; +//// int j = index + 1; +//// while (j < children.length && children [j].setRadioSelection (false)) j++; +//// setSelection (true); +// Control [] children = parent._getChildren (); +// for (int i=0; iLEFT, RIGHT or CENTER + * unless the receiver is an ARROW button, in + * which case, the argument indicates the direction of + * the arrow (one of LEFT, RIGHT, + * UP or DOWN). + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAlignment (int alignment) { + checkWidget (); + if ((style & SWT.ARROW) != 0) { + if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) == 0) return; + style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT); + style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT); + if((alignment & SWT.UP) != 0) { + ((CButton)handle).setAlignment(SwingConstants.NORTH); + } else if((alignment & SWT.DOWN) != 0) { + ((CButton)handle).setAlignment(SwingConstants.SOUTH); + } else if((alignment & SWT.LEFT) != 0) { + ((CButton)handle).setAlignment(SwingConstants.WEST); + } else if((alignment & SWT.RIGHT) != 0) { + ((CButton)handle).setAlignment(SwingConstants.EAST); + } + return; + } + if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return; + style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); + style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if((alignment & SWT.LEFT) != 0) { + ((CButton)handle).setAlignment(SwingConstants.LEFT); + } else if((alignment & SWT.RIGHT) != 0) { + ((CButton)handle).setAlignment(SwingConstants.RIGHT); + } else if((alignment & SWT.CENTER) != 0) { + ((CButton)handle).setAlignment(SwingConstants.CENTER); + } +} + +//void setDefault (boolean value) { +// if ((style & SWT.PUSH) == 0) return; +// int hwndShell = menuShell ().handle; +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// if (value) { +// bits |= OS.BS_DEFPUSHBUTTON; +// OS.SendMessage (hwndShell, OS.DM_SETDEFID, handle, 0); +// } else { +// bits &= ~OS.BS_DEFPUSHBUTTON; +// OS.SendMessage (hwndShell, OS.DM_SETDEFID, 0, 0); +// } +// OS.SendMessage (handle, OS.BM_SETSTYLE, bits, 1); +//} + +/** + * Sets the receiver's image to the argument, which may be + * null indicating that no image should be displayed. + * + * @param image the image to display on the receiver (may be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget (); + if (image != null && image.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT); + this.image = image; + ImageIcon icon = null; + if (image != null && image.handle != null) { + icon = new ImageIcon (image.handle); + } + ((CButton) handle).setIcon (icon); +} + +@Override +boolean setRadioFocus () { + if ((style & SWT.RADIO) == 0 || !getSelection ()) return false; + return setFocus (); +} + +@Override +boolean setRadioSelection (boolean value) { + if ((style & SWT.RADIO) == 0) return false; + if (getSelection () != value) { + setSelection (value); + sendEvent (SWT.Selection); + } + return true; +} + +//boolean setSavedFocus () { +// /* +// * Feature in Windows. When a radio button gets focus, +// * it selects the button in WM_SETFOCUS. If the previous +// * saved focus widget was a radio button, allowing the shell +// * to automatically restore the focus to the previous radio +// * button will unexpectedly check that button. The fix is +// * to disallow focus to be restored to radio button that is +// * not selected. +// */ +// if ((style & SWT.RADIO) != 0 && !getSelection ()) return false; +// return super.setSavedFocus (); +//} + +boolean isAdjustingSelection; + +/** + * Sets the selection state of the receiver, if it is of type CHECK, + * RADIO, or TOGGLE. + * + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. When it is of type TOGGLE, + * it is selected when it is pushed in. + * + * @param selected the new selection state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (boolean selected) { + checkWidget (); + if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return; + isAdjustingSelection = true; + ((CButton)handle).setSelected(selected); + isAdjustingSelection = false; +} + +/** + * Sets the receiver's text. + *

    + * This method sets the button label. The label may include + * the mnemonic character but must not contain line delimiters. + *

    + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, a selection + * event occurs. On most platforms, the mnemonic appears + * underlined but may be emphasised in a platform specific + * manner. The mnemonic indicator character '&' can be + * escaped by doubling it in the string, causing a single + * '&' to be displayed. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.ARROW) != 0) return; + this.text = string; + int mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); + mnemonicIndex -= mnemonicIndex - 1 - s.length(); + mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + CButton cButton = (CButton)handle; + cButton.setText(string); + if(mnemonicIndex >= 0) { + cButton.setMnemonic(string.charAt(mnemonicIndex)); + } + cButton.setDisplayedMnemonicIndex(mnemonicIndex); +} + +//int widgetStyle () { +// int bits = super.widgetStyle (); +// if ((style & SWT.FLAT) != 0) bits |= OS.BS_FLAT; +// if ((style & SWT.ARROW) != 0) return bits | OS.BS_OWNERDRAW; +// if ((style & SWT.LEFT) != 0) bits |= OS.BS_LEFT; +// if ((style & SWT.CENTER) != 0) bits |= OS.BS_CENTER; +// if ((style & SWT.RIGHT) != 0) bits |= OS.BS_RIGHT; +// if ((style & SWT.PUSH) != 0) return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP; +// if ((style & SWT.CHECK) != 0) return bits | OS.BS_CHECKBOX | OS.WS_TABSTOP; +// if ((style & SWT.RADIO) != 0) return bits | OS.BS_RADIOBUTTON; +// if ((style & SWT.TOGGLE) != 0) return bits | OS.BS_PUSHLIKE | OS.BS_CHECKBOX; +// return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP; +//} +// +//TCHAR windowClass () { +// return ButtonClass; +//} +// +//int windowProc () { +// return ButtonProc; +//} +// +//LRESULT WM_GETDLGCODE (int wParam, int lParam) { +// LRESULT result = super.WM_GETDLGCODE (wParam, lParam); +// if (result != null) return result; +// if ((style & SWT.ARROW) != 0) { +// return new LRESULT (OS.DLGC_STATIC); +// } +// return result; +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_KILLFOCUS (wParam, lParam); +// if ((style & SWT.PUSH) != 0 && getDefault ()) { +// menuShell ().setDefaultButton (null, false); +// } +// return result; +//} +// +//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +// if (ignoreMouse) return null; +// return super.WM_LBUTTONDOWN (wParam, lParam); +//} +// +//LRESULT WM_LBUTTONUP (int wParam, int lParam) { +// if (ignoreMouse) return null; +// return super.WM_LBUTTONUP (wParam, lParam); +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// /* +// * Feature in Windows. When Windows sets focus to +// * a radio button, it sets the WM_TABSTOP style. +// * This is undocumented and unwanted. The fix is +// * to save and restore the window style bits. +// */ +// int bits = 0; +// if ((style & SWT.RADIO) != 0) { +// bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// } +// LRESULT result = super.WM_SETFOCUS (wParam, lParam); +// if ((style & SWT.RADIO) != 0) { +// OS.SetWindowLong (handle, OS.GWL_STYLE, bits); +// } +// if ((style & SWT.PUSH) != 0) { +// menuShell ().setDefaultButton (this, false); +// } +// return result; +//} +// +//LRESULT wmColorChild (int wParam, int lParam) { +// LRESULT result = super.wmColorChild (wParam, lParam); +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// Control control = findThemeControl (); +// if (control != null) { +// OS.SetBkMode (wParam, OS.TRANSPARENT); +// RECT rect = new RECT (); +// OS.GetClientRect (control.handle, rect); +// OS.MapWindowPoints (control.handle, handle, rect, 2); +// control.drawThemeBackground (wParam, rect); +// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH)); +// } +// } +// return result; +//} +// +//LRESULT wmCommandChild (int wParam, int lParam) { +// int code = wParam >> 16; +// switch (code) { +// case OS.BN_CLICKED: +// case OS.BN_DOUBLECLICKED: +// if ((style & (SWT.CHECK | SWT.TOGGLE)) != 0) { +// setSelection (!getSelection ()); +// } else { +// if ((style & SWT.RADIO) != 0) { +// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) { +// setSelection (!getSelection ()); +// } else { +// selectRadio (); +// } +// } +// } +// postEvent (SWT.Selection); +// } +// return super.wmCommandChild (wParam, lParam); +//} +// +//LRESULT wmDrawChild (int wParam, int lParam) { +// if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam); +// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof); +// RECT rect = new RECT (); +// OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom); +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// int hTheme = OS.OpenThemeData (handle, SCROLLBAR); +// int iStateId = OS.ABS_LEFTNORMAL; +// switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) { +// case SWT.UP: iStateId = OS.ABS_UPNORMAL; break; +// case SWT.DOWN: iStateId = OS.ABS_DOWNNORMAL; break; +// case SWT.LEFT: iStateId = OS.ABS_LEFTNORMAL; break; +// case SWT.RIGHT: iStateId = OS.ABS_RIGHTNORMAL; break; +// } +// /* +// * NOTE: The normal, hot, pressed and disabled state is +// * computed relying on the fact that the increment between +// * the direction states is invariant (always separated by 4). +// */ +// if (!getEnabled ()) iStateId += OS.ABS_UPDISABLED - OS.ABS_UPNORMAL; +// if ((struct.itemState & OS.ODS_SELECTED) != 0) iStateId += OS.ABS_UPPRESSED - OS.ABS_UPNORMAL; +// OS.DrawThemeBackground (hTheme, struct.hDC, OS.SBP_ARROWBTN, iStateId, rect, null); +// OS.CloseThemeData (hTheme); +// } else { +// int uState = OS.DFCS_SCROLLLEFT; +// switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) { +// case SWT.UP: uState = OS.DFCS_SCROLLUP; break; +// case SWT.DOWN: uState = OS.DFCS_SCROLLDOWN; break; +// case SWT.LEFT: uState = OS.DFCS_SCROLLLEFT; break; +// case SWT.RIGHT: uState = OS.DFCS_SCROLLRIGHT; break; +// } +// if (!getEnabled ()) uState |= OS.DFCS_INACTIVE; +// if ((style & SWT.FLAT) == SWT.FLAT) uState |= OS.DFCS_FLAT; +// if ((struct.itemState & OS.ODS_SELECTED) != 0) uState |= OS.DFCS_PUSHED; +// OS.DrawFrameControl (struct.hDC, rect, OS.DFC_SCROLL, uState); +// } +// return null; +//} + +@Override +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case ActionEvent.ACTION_PERFORMED: if((style & SWT.RADIO) == 0 && (isAdjustingSelection || !hooks(SWT.Selection))) { super.processEvent(e); return; } break; + case ItemEvent.ITEM_STATE_CHANGED: if(isAdjustingSelection || !hooks(SWT.Selection)) { super.processEvent(e); return; } break; + case KeyEvent.KEY_PRESSED: + if((style & SWT.RADIO) != 0) { + switch(((KeyEvent)e).getKeyCode()) { + case KeyEvent.VK_UP: + case KeyEvent.VK_LEFT: + case KeyEvent.VK_DOWN: + case KeyEvent.VK_RIGHT: + break; + default: + super.processEvent(e); + return; + } + } + break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case ActionEvent.ACTION_PERFORMED: + if((style & SWT.RADIO) != 0) { + if(!getSelection()) { + ((CButton)handle).setSelected(true); + } + if((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) { + Component[] components = handle.getParent().getComponents(); + for(int i=0; i + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + * + *

    + * This class may be subclassed by custom control implementors + * who are building controls that are not constructed + * from aggregates of other controls. That is, they are either + * painted using SWT graphics calls or are handled by native + * methods. + *

    + * + * @see Composite + */ + +public class Canvas extends Composite { + Caret caret; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Canvas () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Canvas (Composite parent, int style) { + super (parent, style); +} + +///* +//* Not currently used. +//*/ +//void clearArea (int x, int y, int width, int height) { +// checkWidget (); +// if (OS.IsWindowVisible (handle)) return; +// RECT rect = new RECT (); +// OS.SetRect (rect, x, y, x + width, y + height); +// int hDC = OS.GetDCEx (handle, 0, OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS); +// drawBackground (hDC, rect); +// OS.ReleaseDC (handle, hDC); +//} + +/** + * Returns the caret. + *

    + * The caret for the control is automatically hidden + * and shown when the control is painted or resized, + * when focus is gained or lost and when an the control + * is scrolled. To avoid drawing on top of the caret, + * the programmer must hide and show the caret when + * drawing in the window any other time. + *

    + * + * @return the caret + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Caret getCaret () { + checkWidget (); + return caret; +} + +void releaseChildren (boolean destroy) { + if (caret != null) { + caret.release (false); + caret = null; + } + super.releaseChildren (destroy); +} + +/** + * Fills the interior of the rectangle specified by the arguments, + * with the receiver's background. + * + * @param gc the gc where the rectangle is to be filled + * @param x the x coordinate of the rectangle to be filled + * @param y the y coordinate of the rectangle to be filled + * @param width the width of the rectangle to be filled + * @param height the height of the rectangle to be filled + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the gc is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the gc has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void drawBackground (GC gc, int x, int y, int width, int height) { + checkWidget (); + if (gc == null) error (SWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + Graphics2D g = gc.handle.getGraphics(); + if(backgroundImage != null) { + Shape clip = g.getClip(); + g.clipRect(x, y, width, height); + Dimension size = handle.getSize(); + Utils.paintTiledImage(g, new ImageIcon(backgroundImage.handle), 0, 0, size.width, size.height); + g.setClip(clip); + } else { + java.awt.Color oldColor = g.getColor(); + g.setColor(getBackground().handle); + g.fillRect(x, y, width, height); + g.setColor(oldColor); + } +} + +/** + * Scrolls a rectangular area of the receiver by first copying + * the source area to the destination and then causing the area + * of the source which is not covered by the destination to + * be repainted. Children that intersect the rectangle are + * optionally moved during the operation. In addition, outstanding + * paint events are flushed before the source area is copied to + * ensure that the contents of the canvas are drawn correctly. + * + * @param destX the x coordinate of the destination + * @param destY the y coordinate of the destination + * @param x the x coordinate of the source + * @param y the y coordinate of the source + * @param width the width of the area + * @param height the height of the area + * @param all trueif children should be scrolled, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void scroll (int destX, int destY, int x, int y, int width, int height, boolean all) { + checkWidget (); +// forceResize (); + boolean isFocus = caret != null && caret.isFocusCaret (); + if (isFocus) caret.killFocus (); +// handle.repaint(); + Container clientArea = ((CControl)handle).getClientArea(); + java.awt.Graphics g = clientArea.getGraphics(); + int dx = destX - x; + int dy = destY - y; + g.copyArea(x, y, width, height, dx, dy); + java.awt.Dimension size = clientArea.getSize(); + if(dx < 0) { + clientArea.repaint(size.width + dx, 0, -dx, size.height); + } else if(dx > 0) { + clientArea.repaint(0, 0, dx, size.height); + } + if(dy < 0) { + clientArea.repaint(0, size.height + dy, size.width, -dy); + } else if(dy > 0) { + clientArea.repaint(0, 0, size.width, dy); + } +// RECT sourceRect = new RECT (); +// OS.SetRect (sourceRect, x, y, x + width, y + height); +// RECT clientRect = new RECT (); +// OS.GetClientRect (handle, clientRect); +// if (OS.IntersectRect (clientRect, sourceRect, clientRect)) { +// if (OS.IsWinCE) { +// OS.UpdateWindow (handle); +// } else { +// int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (handle, null, 0, flags); +// } +// } + int deltaX = destX - x, deltaY = destY - y; +// int flags = OS.SW_INVALIDATE | OS.SW_ERASE; +// /* +// * Feature in Windows. If any child in the widget tree partially +// * intersects the scrolling rectangle, Windows moves the child +// * and copies the bits that intersect the scrolling rectangle but +// * does not redraw the child. +// * +// * Feature in Windows. When any child in the widget tree does not +// * intersect the scrolling rectangle but the parent does intersect, +// * Windows does not move the child. This is the documented (but +// * strange) Windows behavior. +// * +// * The fix is to not use SW_SCROLLCHILDREN and move the children +// * explicitly after scrolling. +// */ +//// if (all) flags |= OS.SW_SCROLLCHILDREN; +// OS.ScrollWindowEx (handle, deltaX, deltaY, sourceRect, null, 0, null, flags); + if (all) { + Control [] children = _getChildren (); + for (int i=0; i= Math.max (x, rect.x) && + Math.min (y + height, rect.y + rect.height) >= Math.max (y, rect.y)) { + child.setLocation (rect.x + deltaX, rect.y + deltaY); + } + } + } + if (isFocus) caret.setFocus (); +} + +/** + * Sets the receiver's caret. + *

    + * The caret for the control is automatically hidden + * and shown when the control is painted or resized, + * when focus is gained or lost and when an the control + * is scrolled. To avoid drawing on top of the caret, + * the programmer must hide and show the caret when + * drawing in the window any other time. + *

    + * @param caret the new caret for the receiver, may be null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the caret has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setCaret (Caret caret) { + checkWidget (); + Caret newCaret = caret; + Caret oldCaret = this.caret; + this.caret = newCaret; + if (isFocusControl ()) { + if (oldCaret != null) oldCaret.killFocus (); + if (newCaret != null) { + if (newCaret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + newCaret.setFocus (); + } + } +} + +public void setFont (Font font) { + checkWidget (); + if (caret != null) caret.setFont (font); + super.setFont (font); +} + +//LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) { +// LRESULT result = super.WM_INPUTLANGCHANGE (wParam, lParam); +// if (caret != null) caret.resizeIME (); +// return result; +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_KILLFOCUS (wParam, lParam); +// if (caret != null) caret.killFocus (); +// return result; +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_SETFOCUS (wParam, lParam); +// if (caret != null) caret.setFocus (); +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// LRESULT result = super.WM_SIZE (wParam, lParam); +// if (caret != null) caret.resizeIME (); +// return result; +//} +// +//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) { +// LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam); +// if (result != null) return result; +// /* +// * Bug in Windows. When a window with style WS_EX_LAYOUTRTL +// * that contains a caret is resized, Windows does not move the +// * caret in relation to the mirrored origin in the top right. +// * The fix is to hide the caret in WM_WINDOWPOSCHANGING and +// * show the caret in WM_WINDOWPOSCHANGED. +// */ +// boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret (); +// if (isFocus) caret.setFocus (); +// return result; +//} +// +//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { +// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam); +// if (result != null) return result; +// /* +// * Bug in Windows. When a window with style WS_EX_LAYOUTRTL +// * that contains a caret is resized, Windows does not move the +// * caret in relation to the mirrored origin in the top right. +// * The fix is to hide the caret in WM_WINDOWPOSCHANGING and +// * show the caret in WM_WINDOWPOSCHANGED. +// */ +// boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret (); +// if (isFocus) caret.killFocus (); +// return result; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java new file mode 100644 index 00000000000..2177f1fbcd8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java @@ -0,0 +1,641 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.Timer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.LookAndFeelUtils; + +/** + * Instances of this class provide an i-beam that is typically used + * as the insertion point for text. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class Caret extends Widget { + Canvas parent; + int x, y, width, height; + boolean moved, resized; + boolean isVisible; + Image image; + Font font; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Caret (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +void createWidget () { + isVisible = true; + if (parent.getCaret () == null) { + parent.setCaret (this); + } +} + +Timer timer = new Timer (LookAndFeelUtils.getCaretBlinkRate(), new ActionListener () { + public void actionPerformed (ActionEvent e) { + Caret.this.blink = !Caret.this.blink; + if (Caret.this.parent != null && Caret.this.parent.caret == Caret.this) { + // XXX redraw rect is not correct. for now, redraw all. + // Rectangle r = Caret.this.getBounds(); + // Caret.this.parent.redraw(x, r.y, r.width, r.height, true); + // redraw causes GC to throw exceptions in some conditions. Let's directly call the Swing component + Caret.this.parent.handle.repaint(); + } else { + timer.stop(); + } + } +}) { + public void stop() { + super.stop(); + blink = true; + if(Caret.this.parent != null) { +// Caret.this.parent.redraw (); + Caret.this.parent.handle.repaint(); + } + } +}; + +private boolean blink; + +void paintCaret (GC gc) { + if (blink && isVisible()) { + if(display == null) return; + gc.setXORMode (true); + gc.setBackground (display.getSystemColor (SWT.COLOR_BLACK)); + if (image != null) { + gc.drawImage (image, x, y); + } + gc.fillRectangle (x, y, Math.max(1, width), height); + gc.setXORMode (false); + } +} + +java.awt.Font defaultFont () { + return parent.handle.getFont (); +// int hwnd = parent.handle; +// int hwndIME = OS.ImmGetDefaultIMEWnd (hwnd); +// int hFont = 0; +// if (hwndIME != 0) { +// hFont = OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0); +// } +// if (hFont == 0) { +// hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); +// } +// if (hFont == 0) return parent.defaultFont (); +// return hFont; +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent (or its display if its parent is null). + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds () { + checkWidget(); + if (image != null) { + Rectangle rect = image.getBounds (); + return new Rectangle (x, y, rect.width, rect.height); + } + return new Rectangle (x, y, width, height); +} + +/** + * Returns the font that the receiver will use to paint textual information. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Font getFont () { + checkWidget (); + if (font == null) { + return Font.swing_new (display, defaultFont ()); + } + return font; +// checkWidget(); +// if (font == null) { +// int hFont = defaultFont (); +// return Font.win32_new (display, hFont); +// } +// return font; +} + +/** + * Returns the image that the receiver will use to paint the caret. + * + * @return the receiver's image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getImage () { + checkWidget(); + return image; +} + +/** + * Returns a point describing the receiver's location relative + * to its parent (or its display if its parent is null). + * + * @return the receiver's location + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getLocation () { + checkWidget(); + return new Point (x, y); +} + +/** + * Returns the receiver's parent, which must be a Canvas. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Canvas getParent () { + checkWidget(); + return parent; +} + +/** + * Returns a point describing the receiver's size. + * + * @return the receiver's size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSize () { + checkWidget(); + if (image != null) { + Rectangle rect = image.getBounds (); + return new Point (rect.width, rect.height); + } + return new Point (width, height); +} + +/** + * Returns true if the receiver is visible, and + * false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget(); + return isVisible; +} + +boolean hasFocus () { + return parent.isFocusControl(); +// return parent.handle == OS.GetFocus (); +} + +boolean isFocusCaret () { + return parent.caret == this && hasFocus (); +} + +/** + * Returns true if the receiver is visible and all + * of the receiver's ancestors are visible and false + * otherwise. + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + */ +public boolean isVisible () { + checkWidget(); + return isVisible && parent.isVisible () && hasFocus (); +} + +void killFocus () { + timer.stop (); +// OS.DestroyCaret (); +// if (font != null) restoreIMEFont (); +} + +void move () { +// moved = false; +// if (!OS.SetCaretPos (x, y)) return; +// resizeIME (); + blink = true; +} + +void resizeIME () { +//TODO +// if (!OS.IsDBLocale) return; +// POINT ptCurrentPos = new POINT (); +// if (!OS.GetCaretPos (ptCurrentPos)) return; +// int hwnd = parent.handle; +// RECT rect = new RECT (); +// OS.GetClientRect (hwnd, rect); +// COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM (); +// lpCompForm.dwStyle = OS.CFS_RECT; +// lpCompForm.x = ptCurrentPos.x; +// lpCompForm.y = ptCurrentPos.y; +// lpCompForm.left = rect.left; +// lpCompForm.right = rect.right; +// lpCompForm.top = rect.top; +// lpCompForm.bottom = rect.bottom; +// int hIMC = OS.ImmGetContext (hwnd); +// OS.ImmSetCompositionWindow (hIMC, lpCompForm); +// OS.ImmReleaseContext (hwnd, hIMC); +} + +void releaseParent () { + super.releaseParent (); + if (this == parent.getCaret ()) parent.setCaret (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + image = null; + font = null; +// oldFont = null; +} + +void resize () { +// TODO +// resized = false; +// int hwnd = parent.handle; +// OS.DestroyCaret (); +// int hBitmap = image != null ? image.handle : 0; +// OS.CreateCaret (hwnd, hBitmap, width, height); +// OS.SetCaretPos (x, y); +// OS.ShowCaret (hwnd); +// move (); +} + +void restoreIMEFont () { +//TODO +// if (!OS.IsDBLocale) return; +// if (oldFont == null) return; +// int hwnd = parent.handle; +// int hIMC = OS.ImmGetContext (hwnd); +// OS.ImmSetCompositionFont (hIMC, oldFont); +// OS.ImmReleaseContext (hwnd, hIMC); +// oldFont = null; +} + +void saveIMEFont () { +//TODO +// if (!OS.IsDBLocale) return; +// if (oldFont != null) return; +// int hwnd = parent.handle; +// int hIMC = OS.ImmGetContext (hwnd); +// oldFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA (); +// if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null; +// OS.ImmReleaseContext (hwnd, hIMC); +} + +/** + * Sets the receiver's size and location to the rectangular + * area specified by the arguments. The x and + * y arguments are relative to the receiver's + * parent (or its display if its parent is null). + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * @param width the new width for the receiver + * @param height the new height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setBounds (int x, int y, int width, int height) { + checkWidget(); + boolean samePosition = this.x == x && this.y == y; + boolean sameExtent = this.width == width && this.height == height; + if (samePosition && sameExtent) return; + timer.stop(); + this.x = x; this.y = y; + this.width = width; this.height = height; + if (sameExtent) { + moved = true; + if (isVisible && hasFocus ()) move (); + } else { + resized = true; + if (isVisible && hasFocus ()) resize (); + } + timer.start(); +} + +/** + * Sets the receiver's size and location to the rectangular + * area specified by the argument. The x and + * y fields of the rectangle are relative to + * the receiver's parent (or its display if its parent is null). + * + * @param rect the new bounds for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setBounds (Rectangle rect) { + if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); + setBounds (rect.x, rect.y, rect.width, rect.height); +} + +void setFocus () { + timer.start (); +//TODO +// int hwnd = parent.handle; +// int hBitmap = 0; +// if (image != null) hBitmap = image.handle; +// OS.CreateCaret (hwnd, hBitmap, width, height); +// move (); +// if (OS.IsDBLocale) { +// int hFont = 0; +// if (font != null) hFont = font.handle; +// if (hFont == 0) hFont = defaultFont (); +// saveIMEFont (); +// setIMEFont (hFont); +// } +// if (isVisible) OS.ShowCaret (hwnd); +} + +/** + * Sets the font that the receiver will use to paint textual information + * to the font specified by the argument, or to the default font for that + * kind of control if the argument is null. + * + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the font has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setFont (Font font) { +//TODO +// checkWidget(); +// if (font != null && font.isDisposed ()) { +// error (SWT.ERROR_INVALID_ARGUMENT); +// } +// this.font = font; +// if (isVisible && hasFocus ()) { +// int hFont = 0; +// if (font != null) hFont = font.handle; +// if (hFont == 0) hFont = defaultFont (); +// saveIMEFont (); +// setIMEFont (hFont); +// } +} + +/** + * Sets the image that the receiver will use to paint the caret + * to the image specified by the argument, or to the default + * which is a filled rectangle if the argument is null + * + * @param image the new image (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget(); + if (image != null && image.isDisposed ()) { + error (SWT.ERROR_INVALID_ARGUMENT); + } + this.image = image; + if (isVisible && hasFocus ()) resize (); +} + +void setIMEFont (int hFont) { +//TODO +// if (!OS.IsDBLocale) return; +// LOGFONT logFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA (); +// if (OS.GetObject (hFont, LOGFONT.sizeof, logFont) != 0) { +// int hwnd = parent.handle; +// int hIMC = OS.ImmGetContext (hwnd); +// OS.ImmSetCompositionFont (hIMC, logFont); +// OS.ImmReleaseContext (hwnd, hIMC); +// } +} + +/** + * Sets the receiver's location to the point specified by + * the arguments which are relative to the receiver's + * parent (or its display if its parent is null). + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (int x, int y) { + checkWidget(); + if (this.x == x && this.y == y) return; + timer.stop(); + this.x = x; this.y = y; + moved = true; + if (isVisible && hasFocus ()) move (); + timer.start(); +} + +/** + * Sets the receiver's location to the point specified by + * the argument which is relative to the receiver's + * parent (or its display if its parent is null). + * + * @param location the new location for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (Point location) { + checkWidget(); + if (location == null) error (SWT.ERROR_NULL_ARGUMENT); + setLocation (location.x, location.y); +} + +/** + * Sets the receiver's size to the point specified by the arguments. + * + * @param width the new width for the receiver + * @param height the new height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (int width, int height) { + checkWidget(); + if (this.width == width && this.height == height) return; + this.width = width; this.height = height; + resized = true; + if (isVisible && hasFocus ()) resize (); +} + +/** + * Sets the receiver's size to the point specified by the argument. + * + * @param size the new extent for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (Point size) { + checkWidget(); + if (size == null) error (SWT.ERROR_NULL_ARGUMENT); + setSize (size.x, size.y); +} + +/** + * Marks the receiver as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget (); + if (visible == isVisible) return; + isVisible = visible; +//TODO +// checkWidget(); +// if (visible == isVisible) return; +// isVisible = visible; +// int hwnd = parent.handle; +// if (OS.GetFocus () != hwnd) return; +// if (!isVisible) { +// OS.HideCaret (hwnd); +// } else { +// if (resized) { +// resize (); +// } else { +// if (moved) move (); +// } +// OS.ShowCaret (hwnd); +// } + // TODO activate or deactivate caret timer. +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java new file mode 100644 index 00000000000..4a94f00663d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import javax.swing.JColorChooser; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.graphics.RGB; + +/** + * Instances of this class allow the user to select a color + * from a predefined set of available colors. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class ColorDialog extends Dialog { + RGB rgb; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a composite control which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ColorDialog (Shell parent) { + this (parent, SWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ColorDialog (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns the currently selected color in the receiver. + * + * @return the RGB value for the selected color, may be null + * + * @see PaletteData#getRGBs + */ +public RGB getRGB () { + return rgb; +} + +/** + * Makes the receiver visible and brings it to the front + * of the display. + * + * @return the selected color, or null if the dialog was + * cancelled, no color was selected, or an error + * occurred + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public RGB open () { +// JColorChooser cc = new JColorChooser(); +// cc.addPropertyChangeListener(new PropertyChangeListener() { +// public void propertyChange(PropertyChangeEvent e) { +// if("color".equals(e.getPropertyName())) { +// Color color = (Color)e.getNewValue(); +// if(color != null) { +// rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue()); +// } +// } +// } +// }); + java.awt.Color color = null; + if(rgb != null) { + color = new java.awt.Color(rgb.red, rgb.green, rgb.blue); + } + color = JColorChooser.showDialog(getParent().handle, null, color); + if(color == null) return null; + rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue()); + return rgb; +} + +/** + * Sets the receiver's selected color to be the argument. + * + * @param rgb the new RGB value for the selected color, may be + * null to let the platform select a default when + * open() is called + * @see PaletteData#getRGBs + */ +public void setRGB (RGB rgb) { + this.rgb = rgb; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java new file mode 100644 index 00000000000..584caaac25c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java @@ -0,0 +1,1176 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; + +import javax.swing.JButton; +import javax.swing.RootPaneContainer; + +import org.eclipse.swt.internal.swing.CCombo; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.Utils; +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.events.*; + +/** + * Instances of this class are controls that allow the user + * to choose an item from a list of items, or optionally + * enter a new value by typing it into an editable text + * field. Often, Combos are used in the same place + * where a single selection List widget could + * be used but space is limited. A Combo takes + * less space than a List widget and shows + * similar information. + *

    + * Note: Since Combos can contain both a list + * and an editable text field, it is possible to confuse methods + * which access one versus the other (compare for example, + * clearSelection() and deselectAll()). + * The API documentation is careful to indicate either "the + * receiver's list" or the "the receiver's text field" to + * distinguish between the two cases. + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to add children to it, or set a layout on it. + *

    + *
    + *
    Styles:
    + *
    DROP_DOWN, READ_ONLY, SIMPLE
    + *
    Events:
    + *
    DefaultSelection, Modify, Selection
    + *
    + *

    + * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see List + */ + +public class Combo extends Composite { + + /** + * the operating system limit for the number of characters + * that the text field in an instance of this class can hold + */ + public static final int LIMIT; + + /* + * These values can be different on different platforms. + * Therefore they are not initialized in the declaration + * to stop the compiler from inlining. + */ + static { + LIMIT = 0x7FFFFFFF; + } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#DROP_DOWN + * @see SWT#READ_ONLY + * @see SWT#SIMPLE + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Combo (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the argument to the end of the receiver's list. + * + * @param string the new item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String,int) + */ +public void add (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + isAdjustingSelection = true; + ((CCombo)handle).addItem(string); + isAdjustingSelection = false; +} + +/** + * Adds the argument to the receiver's list at the given + * zero-relative index. + *

    + * Note: To add an item at the end of the list, use the + * result of calling getItemCount() as the + * index or use add(String). + *

    + * + * @param string the new item + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String) + */ +public void add (String string, int index) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + isAdjustingSelection = true; + ((CCombo)handle).insertElementAt(string, index); + isAdjustingSelection = false; +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is modified, by sending + * it one of the messages defined in the ModifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #removeModifyListener + */ +public void addModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Modify, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's selection changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the combo's list selection changes. + * widgetDefaultSelected is typically called when ENTER is pressed the combo's text area. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is verified, by sending + * it one of the messages defined in the VerifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #removeVerifyListener + * + * @since 3.1 + */ +public void addVerifyListener (VerifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Verify, typedListener); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +static int checkStyle (int style) { + /* + * Even though it is legal to create this widget + * with scroll bars, they serve no useful purpose + * because they do not automatically scroll the + * widget's client area. The fix is to clear + * the SWT style. + */ + style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); + style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0); + if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY; + return style; +} + +/** + * Sets the selection in the receiver's text field to an empty + * selection starting just before the first character. If the + * text field is editable, this has the effect of placing the + * i-beam at the start of the text. + *

    + * Note: To clear the selected items in the receiver's list, + * use deselectAll(). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #deselectAll + */ +public void clearSelection () { + checkWidget (); + isAdjustingSelection = true; + ((CCombo)handle).setEditorCaretPosition(0); + isAdjustingSelection = false; +} + +public Point computeSize (int wHint, int hHint, boolean changed) { + if((style & SWT.SIMPLE) != 0) { + return super.computeSize(wHint, hHint, changed); + } + Dimension preferredSize = handle.getPreferredSize(); + if(wHint == SWT.DEFAULT) { + return new Point(preferredSize.width, preferredSize.height); + } + Point p = super.computeSize(wHint, hHint, changed); + return new Point(p.x, preferredSize.height); +} + +/** + * Copies the selected text. + *

    + * The current selection is copied to the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public void copy () { + checkWidget (); + ((CCombo)handle).copyEditor(); +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CCombo.Factory.newInstance(this, style); +} + +/** + * Cuts the selected text. + *

    + * The current selection is first copied to the + * clipboard and then deleted from the widget. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public void cut () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CCombo)handle).cutEditor(); +} + +/** + * Deselects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already deselected, it remains + * deselected. Indices that are out of range are ignored. + * + * @param index the index of the item to deselect + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselect (int index) { + checkWidget (); + CCombo cCombo = (CCombo)handle; + if(index == cCombo.getSelectedIndex()) { + isAdjustingSelection = true; + cCombo.setSelectedIndex(-1); + isAdjustingSelection = false; + sendEvent (SWT.Modify); + } + // widget could be disposed at this point +} + +/** + * Deselects all selected items in the receiver's list. + *

    + * Note: To clear the selection in the receiver's text field, + * use clearSelection(). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #clearSelection + */ +public void deselectAll () { + checkWidget (); + isAdjustingSelection = true; + ((CCombo)handle).clearEditorSelection(); + isAdjustingSelection = false; + sendEvent (SWT.Modify); + // widget could be disposed at this point +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver's list. Throws an exception if the index is out + * of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_CANNOT_GET_ITEM); + try { + return (String)((CCombo)handle).getItemAt(index); + } catch(Exception e) { + error (SWT.ERROR_INVALID_RANGE); + } + return ""; +} + +/** + * Returns the number of items contained in the receiver's list. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return ((CCombo)handle).getItemCount(); +} + +/** + * Returns the height of the area which would be used to + * display one of the items in the receiver's list. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemHeight () { + checkWidget (); + Utils.notImplemented(); return 15; +// int result = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0); +// if (result == OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT); +// return result; +} + +/** + * Returns a (possibly empty) array of Strings which are + * the items in the receiver's list. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver's list + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String [] getItems () { + checkWidget (); + int count = getItemCount (); + String [] result = new String [count]; + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.1.2 + */ +public int getOrientation () { + checkWidget(); + return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); +} + +/** + * Returns a Point whose x coordinate is the + * character position representing the start of the selection + * in the receiver's text field, and whose y coordinate is the + * character position representing the end of the selection. + * An "empty" selection is indicated by the x and y coordinates + * having the same value. + *

    + * Indexing is zero based. The range of a selection is from + * 0..N where N is the number of characters in the widget. + *

    + * + * @return a point representing the selection start and end + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelection () { + checkWidget (); + if ((style & SWT.DROP_DOWN) != 0 && (style & SWT.READ_ONLY) != 0) { + return new Point (0, getText().length()); + } + CCombo cCombo = (CCombo)handle; + return new Point (cCombo.getEditorSelectionStart(), cCombo.getEditorSelectionEnd()); +} + +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver's list, or -1 if no item is selected. + * + * @return the index of the selected item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionIndex () { + checkWidget (); + return ((CCombo)handle).getSelectedIndex(); +} + +/** + * Returns a string containing a copy of the contents of the + * receiver's text field, or an empty string if there are no + * contents. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + return ((CCombo)handle).getEditorText(); +} + +/** + * Returns the height of the receivers's text field. + * + * @return the text height + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTextHeight () { + checkWidget (); + return ((CCombo)handle).getEditorSize().height; +} + +/** + * Returns the maximum number of characters that the receiver's + * text field is capable of holding. If this has not been changed + * by setTextLimit(), it will be the constant + * Combo.LIMIT. + * + * @return the text limit + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #LIMIT + */ +public int getTextLimit () { + checkWidget (); + return ((CCombo)handle).getEditorTextLimit(); +} + +/** + * Gets the number of items that are visible in the drop + * down portion of the receiver's list. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *

    + * + * @return the number of items that are visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public int getVisibleItemCount () { + checkWidget (); + return ((CCombo)handle).getMaximumRowCount(); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param string the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (String string) { + return indexOf (string, 0); +} + +/** + * Searches the receiver's list starting at the given, + * zero-relative index until an item is found that is equal + * to the argument, and returns the index of that item. If + * no item is found or the starting index is out of range, + * returns -1. + * + * @param string the search item + * @param start the zero-relative index at which to begin the search + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (String string, int start) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = getItemCount (); + for (int i=start; i + * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public void paste () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CCombo)handle).pasteEditor(); +} + +/** + * Removes the item from the receiver's list at the given + * zero-relative index. + * + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_ITEM_NOT_REMOVED); + isAdjustingSelection = true; + ((CCombo)handle).removeItemAt(index); + isAdjustingSelection = false; + sendEvent (SWT.Modify); +} + +/** + * Removes the items from the receiver's list which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int start, int end) { + checkWidget (); + if (start > end) return; + int count = getItemCount(); + if (!(0 <= start && start <= end && end < count)) { + error (SWT.ERROR_INVALID_RANGE); + } + isAdjustingSelection = true; + CCombo cCombo = (CCombo)handle; + for (int i=start; i<=end; i++) { + cCombo.removeItemAt(i); + } + isAdjustingSelection = false; +} + +/** + * Searches the receiver's list starting at the first item + * until an item is found that is equal to the argument, + * and removes that item from the list. + * + * @param string the item to remove + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the string is not found in the list
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + int index = indexOf (string, 0); + if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT); + remove (index); +} + +/** + * Removes all of the items from the receiver's list and clear the + * contents of receiver's text field. + *

    + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void removeAll () { + checkWidget (); + isAdjustingSelection = true; + ((CCombo)handle).removeAllItems(); + isAdjustingSelection = false; + sendEvent (SWT.Modify); + // widget could be disposed at this point +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #addModifyListener + */ +public void removeModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Modify, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's selection changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is verified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #addVerifyListener + * + * @since 3.1 + */ +public void removeVerifyListener (VerifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Verify, listener); +} + +boolean isAdjustingSelection; + +/** + * Selects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already selected, it remains + * selected. Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void select (int index) { + checkWidget (); + int count = getItemCount(); + if (0 <= index && index < count) { + CCombo cCombo = (CCombo)handle; + if(index != cCombo.getSelectedIndex()) { + isAdjustingSelection = true; + cCombo.setSelectedIndex(index); + isAdjustingSelection = false; + sendEvent (SWT.Modify); + } + } +} + +/** + * Sets the text of the item in the receiver's list at the given + * zero-relative index to the string argument. This is equivalent + * to removing the old item at the index, and then adding the new + * item at that index. + * + * @param index the index for the item + * @param string the new text for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItem (int index, String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + remove (index); + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the modify + * event that might be sent when the index is removed. + * If this happens, just exit. + */ + if (isDisposed ()) return; + add (string, index); +} + +/** + * Sets the receiver's list to be the given array of items. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the items array is null
    • + *
    • ERROR_INVALID_ARGUMENT - if an item in the items array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItems (String [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; iSWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. + *

    + * + * @param orientation new orientation style + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1.2 + */ +public void setOrientation (int orientation) { + checkWidget(); + int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT; + if ((orientation & flags) == 0 || (orientation & flags) == flags) return; + style &= ~flags; + style |= orientation & flags; + ComponentOrientation o; + if ((style & SWT.RIGHT_TO_LEFT) != 0) { + o = ComponentOrientation.RIGHT_TO_LEFT; + } else { + o = ComponentOrientation.LEFT_TO_RIGHT; + } + ((CCombo)handle).setComponentOrientation(o); +} + +/** + * Sets the selection in the receiver's text field to the + * range specified by the argument whose x coordinate is the + * start of the selection and whose y coordinate is the end + * of the selection. + * + * @param selection a point representing the new selection start and end + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (Point selection) { + checkWidget (); + if (selection == null) error (SWT.ERROR_NULL_ARGUMENT); + CCombo cCombo = (CCombo)handle; + cCombo.setEditorSelectionStart(selection.x); + cCombo.setEditorSelectionEnd(selection.y); +} + +/** + * Sets the contents of the receiver's text field to the + * given string. + *

    + * Note: The text field in a Combo is typically + * only capable of displaying a single line of text. Thus, + * setting the text to a string containing line breaks or + * other special characters will probably cause it to + * display incorrectly. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.READ_ONLY) != 0) { + int index = indexOf (string); + if (index != -1) select (index); + return; + } + ((CCombo)handle).setEditorText(string); + sendEvent (SWT.Modify); + // widget could be disposed at this point +} + +/** + * Sets the maximum number of characters that the receiver's + * text field is capable of holding to be the argument. + *

    + * To reset this value to the default, use setTextLimit(Combo.LIMIT). + * Specifying a limit value larger than Combo.LIMIT sets the + * receiver's limit to Combo.LIMIT. + *

    + * @param limit new text limit + * + * @exception IllegalArgumentException
      + *
    • ERROR_CANNOT_BE_ZERO - if the limit is zero
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #LIMIT + */ +public void setTextLimit (int limit) { + checkWidget (); + if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO); + ((CCombo)handle).setEditorTextLimit(limit); +} + +/** + * Sets the number of items that are visible in the drop + * down portion of the receiver's list. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *

    + * + * @param count the new number of items to be visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setVisibleItemCount (int count) { + checkWidget (); + if (count < 0) return; + ((CCombo)handle).setMaximumRowCount(count); +} + +boolean traverseEscape () { + if ((style & SWT.DROP_DOWN) != 0) { + return ((CCombo)handle).isPopupVisible(); +// if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) { +// OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0); +// return true; +// } + } + return super.traverseEscape (); +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Traverse) && !hooks(SWT.DefaultSelection)) { + super.processEvent(e); + JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton(); + if(defaultButton != null) { + defaultButton.doClick(); + } + return; + } + break; + case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case ActionEvent.ACTION_PERFORMED: + Event event = new Event(); + event.detail = SWT.TRAVERSE_RETURN; + sendEvent(SWT.Traverse, event); + boolean isSending = true; + if(event.doit) { + JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton(); + if(defaultButton != null) { + isSending = false; + defaultButton.doClick(); + } + } + if(isSending) { + sendEvent(SWT.DefaultSelection); + } + break; + case ItemEvent.ITEM_STATE_CHANGED: + sendEvent(SWT.Selection); + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java new file mode 100644 index 00000000000..4f29a12ff80 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java @@ -0,0 +1,1428 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.*; + +/** + * Instances of this class are controls which are capable + * of containing other controls. + *
    + *
    Styles:
    + *
    NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: The NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, + * and NO_REDRAW_RESIZE styles are intended for use with Canvas. + * They can be used with Composite if you are drawing your own, but their + * behavior is undefined if they are used with subclasses of Composite other + * than Canvas. + *

    + * Note: The CENTER style, although undefined for composites, has the + * same value as EMBEDDED (which is used to embed widgets from other + * widget toolkits into SWT). On some operating systems (GTK, Motif), this may cause + * the children of this composite to be obscured. The EMBEDDED style + * is for use by other widget toolkits and should normally never be used. + *

    + * This class may be subclassed by custom control implementors + * who are building controls that are constructed from aggregates + * of other controls. + *

    + * + * @see Canvas + */ + +public class Composite extends Scrollable { + Layout layout; + int font; +// WINDOWPOS [] lpwp; + Control [] tabList; + int layoutCount = 0; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Composite () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + * + * @see SWT#NO_BACKGROUND + * @see SWT#NO_FOCUS + * @see SWT#NO_MERGE_PAINTS + * @see SWT#NO_REDRAW_RESIZE + * @see SWT#NO_RADIO_GROUP + * @see Widget#getStyle + */ +public Composite (Composite parent, int style) { + super (parent, style); +} + +Control [] _getChildren () { + Component[] children = ((CControl)handle).getClientArea().getComponents(); + if(children.length == 0) { + return new Control[0]; + } + ArrayList controlsList = new ArrayList(children.length); + for(int i=0; i + *
  • ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
  • + *
  • ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void changed (Control[] changed) { + checkWidget (); + if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT); + for (int i=0; i 0 || parent == null? this : parent.findDeferredControl (); +} + +//Menu [] findMenus (Control control) { +// if (control == this) return new Menu [0]; +// Menu result [] = super.findMenus (control); +// Control [] children = _getChildren (); +// for (int i=0; iSWT: + * INHERIT_NONE, INHERIT_DEFAULT, + * INHERTIT_FORCE. + * + * @return the background mode + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + * + * @since 3.2 + */ +public int getBackgroundMode () { + checkWidget (); + return backgroundMode; +} + +/** + * Returns a (possibly empty) array containing the receiver's children. + * Children are returned in the order that they are drawn. The topmost + * control appears at the beginning of the array. Subsequent controls + * draw beneath this control and appear later in the array. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of children, so modifying the array will + * not affect the receiver. + *

    + * + * @return an array of children + * + * @see Control#moveAbove + * @see Control#moveBelow + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Control [] getChildren () { + checkWidget (); + return _getChildren (); +} + +//int getChildrenCount () { +// /* +// * NOTE: The current implementation will count +// * non-registered children. +// */ +// int count = 0; +// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD); +// while (hwndChild != 0) { +// count++; +// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT); +// } +// return count; +//} + +/** + * Returns layout which is associated with the receiver, or + * null if one has not been set. + * + * @return the receiver's layout or null + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Layout getLayout () { + checkWidget (); + return layout; +} + +/** + * Gets the (possibly empty) tabbing order for the control. + * + * @return tabList the ordered list of controls representing the tab order + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setTabList + */ +public Control [] getTabList () { + checkWidget (); + Control [] tabList = _getTabList (); + if (tabList == null) { + int count = 0; + Control [] list =_getChildren (); + for (int i=0; itrue if the receiver has deferred + * the performing of layout, and false otherwise. + * + * @return the receiver's deferred layout state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setLayoutDeferred(boolean) + * @see #isLayoutDeferred() + * + * @since 3.1 + */ +public boolean getLayoutDeferred () { + checkWidget (); + return layoutCount > 0 ; +} + +/** + * Returns true if the receiver or any ancestor + * up to and including the receiver's nearest ancestor shell + * has deferred the performing of layouts. Otherwise, false + * is returned. + * + * @return the receiver's deferred layout state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setLayoutDeferred(boolean) + * @see #getLayoutDeferred() + * + * @since 3.1 + */ +public boolean isLayoutDeferred () { + checkWidget (); + return findDeferredControl () != null; +} + +protected boolean isLayoutManaged() { + return false; +} + +/** + * If the receiver has a layout, asks the layout to lay out + * (that is, set the size and location of) the receiver's children. + * If the receiver does not have a layout, do nothing. + *

    + * This is equivalent to calling layout(true). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void layout () { + checkWidget (); + layout (true); +} + +/** + * If the receiver has a layout, asks the layout to lay out + * (that is, set the size and location of) the receiver's children. + * If the argument is true the layout must not rely + * on any information it has cached about the immediate children. If it + * is false the layout may (potentially) optimize the + * work it is doing by assuming that none of the receiver's + * children has changed state since the last layout. + * If the receiver does not have a layout, do nothing. + *

    + * If a child is resized as a result of a call to layout, the + * resize event will invoke the layout of the child. The layout + * will cascade down through all child widgets in the receiver's widget + * tree until a child is encountered that does not resize. Note that + * a layout due to a resize will not flush any cached information + * (same as layout(false)).

    + * + * @param changed true if the layout must flush its caches, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void layout (boolean changed) { + checkWidget (); + if (layout == null) return; + layout (changed, false); +} + +/** + * If the receiver has a layout, asks the layout to lay out + * (that is, set the size and location of) the receiver's children. + * If the changed argument is true the layout must not rely + * on any information it has cached about its children. If it + * is false the layout may (potentially) optimize the + * work it is doing by assuming that none of the receiver's + * children has changed state since the last layout. + * If the all argument is true the layout will cascade down + * through all child widgets in the receiver's widget tree, regardless of + * whether the child has changed size. The changed argument is applied to + * all layouts. If the all argument is false, the layout will + * not cascade down through all child widgets in the receiver's widget + * tree. However, if a child is resized as a result of a call to layout, the + * resize event will invoke the layout of the child. Note that + * a layout due to a resize will not flush any cached information + * (same as layout(false)).

    + * + * @param changed true if the layout must flush its caches, and false otherwise + * @param all true if all children in the receiver's widget tree should be laid out, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void layout (boolean changed, boolean all) { + checkWidget (); + if (layout == null && !all) return; + markLayout (changed, all); + updateLayout (true, all); +} + +/** + * Forces a lay out (that is, sets the size and location) of all widgets that + * are in the parent hierarchy of the changed control up to and including the + * receiver. The layouts in the hierarchy must not rely on any information + * cached about the changed control or any of its ancestors. The layout may + * (potentially) optimize the work it is doing by assuming that none of the + * peers of the changed control have changed state since the last layout. + * If an ancestor does not have a layout, skip it. + * + * @param changed a control that has had a state change which requires a recalculation of its size + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
    • + *
    • ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void layout (Control [] changed) { + checkWidget (); + if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT); + for (int i=0; i=0; i--) { + update [i].updateLayout (true, false); + } +} + +@Override +void markLayout (boolean changed, boolean all) { + if (layout != null) { + state |= LAYOUT_NEEDED; + if (changed) state |= LAYOUT_CHANGED; + } + if (all) { + Control [] children = _getChildren (); + for (int i=0; i 1) { +//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS; +//// } +// if (defer) { +// hdwp = DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags); +// if (hdwp == 0) return false; +// } else { +// SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags); +// } +// } +// } +// if (defer) return OS.EndDeferWindowPos (hdwp); +// return true; +//} +// +//void resizeEmbeddedHandle(int embeddedHandle, int width, int height) { +// if (embeddedHandle == 0) return; +// int [] processID = new int [1]; +// int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID); +// if (threadId != OS.GetCurrentThreadId ()) { +// if (processID [0] == OS.GetCurrentProcessId ()) { +// if (display.msgHook == 0) { +// if (!OS.IsWinCE) { +// display.getMsgCallback = new Callback (display, "getMsgProc", 3); +// display.getMsgProc = display.getMsgCallback.getAddress (); +// if (display.getMsgProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS); +// display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, OS.GetLibraryHandle(), threadId); +// OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0); +// } +// } +// } +// int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS; +// OS.SetWindowPos (embeddedHandle, 0, 0, 0, width, height, flags); +// } +//} + +int backgroundMode; + +/** + * Sets the background drawing mode to the argument which should + * be one of the following constants defined in class SWT: + * INHERIT_NONE, INHERIT_DEFAULT, + * INHERIT_FORCE. + * + * @param mode the new background mode + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + * + * @since 3.2 + */ +public void setBackgroundMode (int mode) { + checkWidget (); + if(backgroundMode == mode) return; + backgroundMode = mode; + Control [] children = _getChildren (); + for (int i = 0; i < children.length; i++) { + children [i].updateBackgroundMode (); + } + handle.repaint(); +} + +@Override +public boolean setFocus () { + checkWidget (); + Control [] children = _getChildren (); + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void setLayout (Layout layout) { + checkWidget (); + this.layout = layout; +} + +/** + * If the argument is true, causes subsequent layout + * operations in the receiver or any of its children to be ignored. + * No layout of any kind can occur in the receiver or any of its + * children until the flag is set to false. + * Layout operations that occurred while the flag was + * true are remembered and when the flag is set to + * false, the layout operations are performed in an + * optimized manner. Nested calls to this method are stacked. + * + * @param defer the new defer state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #layout(boolean) + * @see #layout(Control[]) + * + * @since 3.1 + */ +public void setLayoutDeferred (boolean defer) { + if (!defer) { + if (--layoutCount == 0) { + if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) { + updateLayout (true, true); + } + } + } else { + layoutCount++; + } +} +/** + * Sets the tabbing order for the specified controls to + * match the order that they occur in the argument list. + * + * @param tabList the ordered list of controls representing the tab order or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed
    • + *
    • ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTabList (Control [] tabList) { + checkWidget (); + if (tabList != null) { + for (int i=0; i 1 && lpwp == null) { +// lpwp = new WINDOWPOS [count]; +// } +// } +//} + +@Override +boolean setTabGroupFocus () { + if (isTabItem ()) return setTabItemFocus (); + boolean takeFocus = (style & SWT.NO_FOCUS) == 0; + if ((state & CANVAS) != 0) { + takeFocus = hooksKeys (); + if ((style & SWT.EMBEDDED) != 0) takeFocus = true; + } + if (takeFocus && setTabItemFocus ()) return true; + Control [] children = _getChildren (); + for (int i=0; i= 6 && OS.IsAppThemed ()) { +// if (findThemeControl () != null) { +// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD); +// while (hwndChild != 0) { +// int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (hwndChild, null, 0, flags); +// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT); +// } +// } +// } +// } +// +// /* Resize the embedded window */ +// if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) { +// resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), lParam & 0xFFFF, lParam >> 16); +// } +// return result; +//} +// +//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) { +// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD); +// while (hwndChild != 0) { +// OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0); +// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT); +// } +// return null; +//} +// +//LRESULT WM_SYSCOMMAND (int wParam, int lParam) { +// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Check to see if the command is a system command or +// * a user menu item that was added to the system menu. +// */ +// if ((wParam & 0xF000) == 0) return result; +// +// /* +// * Bug in Windows. When a vertical or horizontal scroll bar is +// * hidden or shown while the opposite scroll bar is being scrolled +// * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar +// * does not redraw properly. The fix is to detect this case and +// * redraw the non-client area. +// */ +// if (!OS.IsWinCE) { +// int cmd = wParam & 0xFFF0; +// switch (cmd) { +// case OS.SC_HSCROLL: +// case OS.SC_VSCROLL: +// boolean showHBar = horizontalBar != null && horizontalBar.getVisible (); +// boolean showVBar = verticalBar != null && verticalBar.getVisible (); +// int code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam); +// if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) || +// (showVBar != (verticalBar != null && verticalBar.getVisible ()))) { +// int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW; +// OS.RedrawWindow (handle, null, 0, flags); +// } +// if (code == 0) return LRESULT.ZERO; +// return new LRESULT (code); +// } +// } +// /* Return the result */ +// return result; +//} + +@Override +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case ComponentEvent.COMPONENT_RESIZED: if(layout == null) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case ComponentEvent.COMPONENT_RESIZED: + if(layout != null) { + markLayout(false, false); + updateLayout(false, false); +// ((CControl)handle).getClientArea().invalidate(); +// handle.validate(); +// if(handle instanceof JComponent) { +// ((JComponent)handle).revalidate(); +// } else { +// handle.invalidate(); +// handle.validate(); +// } + handle.repaint(); + } + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public int getOrientation() { + throw new UnsupportedOperationException("Not implemented yet"); +} + +public void setOrientation(int a) { + throw new UnsupportedOperationException("Not implemented yet"); +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java new file mode 100644 index 00000000000..b9f42a432d6 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java @@ -0,0 +1,4818 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Insets; +import java.awt.KeyboardFocusManager; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseWheelEvent; +import java.util.EventObject; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.RootPaneContainer; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.accessibility.Accessible; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.HelpListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Drawable; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.GCData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.CGC; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.internal.swing.DisabledStatePanel; +import org.eclipse.swt.internal.swing.NullGraphics2D; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Control is the abstract superclass of all windowed user interface classes. + *

    + *

    + *
    Styles: + *
    BORDER
    + *
    LEFT_TO_RIGHT, RIGHT_TO_LEFT
    + *
    Events: + *
    FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter, + * MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse, + * DragDetect, MenuDetect
    + *
    + *

    + * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public abstract class Control extends Widget implements Drawable { + /** + * the handle to the OS resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public Container handle; + Composite parent; +// Cursor cursor; + Menu menu; +// String toolTipText; + Object layoutData; + Accessible accessible; +// int drawCount, foreground, background; +// long lastPressed = 0; + Image backgroundImage; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Control () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BORDER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Control (Composite parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is moved or resized, by sending + * it one of the messages defined in the ControlListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #removeControlListener + */ +public void addControlListener(ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Resize,typedListener); + addListener (SWT.Move,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control gains or loses focus, by sending + * it one of the messages defined in the FocusListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see FocusListener + * @see #removeFocusListener + */ +public void addFocusListener (FocusListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.FocusIn,typedListener); + addListener (SWT.FocusOut,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when help events are generated for the control, + * by sending it one of the messages defined in the + * HelpListener interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #removeHelpListener + */ +public void addHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Help, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when keys are pressed and released on the system keyboard, by sending + * it one of the messages defined in the KeyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see KeyListener + * @see #removeKeyListener + */ +public void addKeyListener (KeyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.KeyUp,typedListener); + addListener (SWT.KeyDown,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when mouse buttons are pressed and released, by sending + * it one of the messages defined in the MouseListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseListener + * @see #removeMouseListener + */ +public void addMouseListener (MouseListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.MouseDown,typedListener); + addListener (SWT.MouseUp,typedListener); + addListener (SWT.MouseDoubleClick,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the mouse passes or hovers over controls, by sending + * it one of the messages defined in the MouseTrackListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseTrackListener + * @see #removeMouseTrackListener + */ +public void addMouseTrackListener (MouseTrackListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.MouseEnter,typedListener); + addListener (SWT.MouseExit,typedListener); + addListener (SWT.MouseHover,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the mouse moves, by sending it one of the + * messages defined in the MouseMoveListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseMoveListener + * @see #removeMouseMoveListener + */ +public void addMouseMoveListener (MouseMoveListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.MouseMove,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver needs to be painted, by sending it + * one of the messages defined in the PaintListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see PaintListener + * @see #removePaintListener + */ +public void addPaintListener (PaintListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Paint,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when traversal events occur, by sending it + * one of the messages defined in the TraverseListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see TraverseListener + * @see #removeTraverseListener + */ +public void addTraverseListener (TraverseListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Traverse,typedListener); +} + +//int borderHandle () { +// return handle; +//} +// +//void checkBorder () { +// if (getBorderWidth () == 0) style &= ~SWT.BORDER; +//} +// +//boolean checkHandle (int hwnd) { +// return hwnd == handle; +//} +// +//void checkMirrored () { +// if ((style & SWT.RIGHT_TO_LEFT) != 0) { +// int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); +// if ((bits & OS.WS_EX_LAYOUTRTL) != 0) style |= SWT.MIRRORED; +// } +//} +// +/** + * Returns the preferred size of the receiver. + *

    + * The preferred size of a control is the size that it would + * best be displayed at. The width hint and height hint arguments + * allow the caller to ask a control questions such as "Given a particular + * width, how high does the control need to be to show all of the contents?" + * To indicate that the caller does not wish to constrain a particular + * dimension, the constant SWT.DEFAULT is passed for the hint. + *

    + * + * @param wHint the width hint (can be SWT.DEFAULT) + * @param hHint the height hint (can be SWT.DEFAULT) + * @return the preferred size of the control + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Layout + * @see #getBorderWidth + * @see #getBounds + * @see #getSize + * @see #pack(boolean) + * @see "computeTrim, getClientArea for controls that implement them" + */ +public Point computeSize (int wHint, int hHint) { + return computeSize (wHint, hHint, true); +} + +/** + * Returns the preferred size of the receiver. + *

    + * The preferred size of a control is the size that it would + * best be displayed at. The width hint and height hint arguments + * allow the caller to ask a control questions such as "Given a particular + * width, how high does the control need to be to show all of the contents?" + * To indicate that the caller does not wish to constrain a particular + * dimension, the constant SWT.DEFAULT is passed for the hint. + *

    + * If the changed flag is true, it indicates that the receiver's + * contents have changed, therefore any caches that a layout manager + * containing the control may have been keeping need to be flushed. When the + * control is resized, the changed flag will be false, so layout + * manager caches can be retained. + *

    + * + * @param wHint the width hint (can be SWT.DEFAULT) + * @param hHint the height hint (can be SWT.DEFAULT) + * @param changed true if the control's contents have changed, and false otherwise + * @return the preferred size of the control. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Layout + * @see #getBorderWidth + * @see #getBounds + * @see #getSize + * @see #pack(boolean) + * @see "computeTrim, getClientArea for controls that implement them" + */ +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget (); + //TODO: it seems that for some components we have to take the border into account (Shell), and for others not (Button). + // Let's assume for a start that we don't take that into account if the component is the same as the client area. + Container clientArea = ((CControl)handle).getClientArea(); + Dimension size = handle.getPreferredSize(); + Dimension contentSize = clientArea.getPreferredSize(); + if(clientArea != handle) { + Insets insets = clientArea.getInsets(); + contentSize.width -= insets.left + insets.right; + contentSize.height -= insets.top + insets.bottom; + } + int width = size.width; + int height = size.height; + if(wHint != SWT.DEFAULT) { + width = wHint + width - contentSize.width; + } + if(hHint != SWT.DEFAULT) { + height = hHint + height - contentSize.height; + } + return new Point (width, height); +} + +Control computeTabGroup () { + if (isTabGroup ()) return this; + return parent.computeTabGroup (); +} + +Control computeTabRoot () { + Control [] tabList = parent._getTabList (); + if (tabList != null) { + int index = 0; + while (index < tabList.length) { + if (tabList [index] == this) break; + index++; + } + if (index == tabList.length) { + if (isTabGroup ()) return this; + } + } + return parent.computeTabRoot (); +} + +Control [] computeTabList () { + if (isTabGroup ()) { + if (getVisible () && getEnabled ()) { + return new Control [] {this}; + } + } + return new Control [0]; +} + +/** + * Like create handle, but overriden class should call its supertype declaration + */ +void createHandleInit () { + +} + +Container createHandle () { + if(handle != null) return handle; + error (SWT.ERROR_NO_HANDLES); + return null; +} + +boolean autoAddChildren() { + return true; +} + +void createWidget () { + checkOrientation (parent); + createHandleInit (); + handle = createHandle (); + if(!(handle instanceof CControl)) throw new IllegalStateException("The widget should implement the CComponent interface!"); + if(handle instanceof Window) { + Dimension size = ((Window)handle).getSize(); + ((Window)handle).pack(); + handle.setSize(size); + } + if(parent != null && !(handle instanceof Window)) { + if(parent.autoAddChildren()) { + Container clientArea = ((CControl)parent.handle).getClientArea(); + if(!parent.isLayoutManaged()) { + clientArea.setLayout(null); + } + clientArea.add(handle); + updateBackgroundMode(); + ((JComponent)clientArea).revalidate(); + clientArea.repaint(); + } +// if(parent instanceof Shell && parent.getChildren().length == 0) { +// handle.requestFocus(); +// } + } + // TODO: should have a fixInitSize like in old implementation <- Note it seems to be fixed now, but have to check +// if(handle.getSize().equals(new java.awt.Dimension(0, 0))) { +// handle.setSize(handle.getPreferredSize()); +// if(handle instanceof JComponent) { +// JComponent component = (JComponent)handle; +//// component.setOpaque(true); +//// component.revalidate(); +//// } else { +//// handle.validate(); +// } +// } + register (); +// subclass (); +// setDefaultFont (); +// checkMirrored (); +// checkBorder (); +} + +//int defaultBackground () { +// if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_WINDOW); +// return OS.GetSysColor (OS.COLOR_BTNFACE); +//} +// +//int defaultFont () { +// return display.systemFont (); +//} +// +//int defaultForeground () { +// return OS.GetSysColor (OS.COLOR_WINDOWTEXT); +//} + +void deregister () { + display.removeControl (handle); +} + +void destroyWidget () { +// int hwnd = topHandle (); + releaseHandle (); +// if (hwnd != 0) { +// OS.DestroyWindow (hwnd); +// } +} + +//void drawBackground (int hDC) { +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// drawBackground (hDC, getBackgroundPixel (), rect); +//} +// +//void drawBackground (int hDC, int pixel, RECT rect) { +// Control control = null; +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// control = findThemeControl (); +// } +// if (control == null) { +// int hPalette = display.hPalette; +// if (hPalette != 0) { +// OS.SelectPalette (hDC, hPalette, false); +// OS.RealizePalette (hDC); +// } +// int hBrush = findBrush (pixel); +// OS.FillRect (hDC, rect, hBrush); +// } else { +// RECT rect2 = new RECT (); +// OS.GetWindowRect (control.handle, rect2); +// OS.MapWindowPoints (0, handle, rect2, 2); +// control.drawThemeBackground (hDC, rect2); +// } +//} +// +//void drawBackground (int hDC, RECT rect) { +// drawBackground (hDC, getBackgroundPixel (), rect); +//} +// +//void drawThemeBackground (int hDC, RECT rect) { +// /* Do nothing */ +//} +// +//void enableWidget (boolean enabled) { +// handle.setEnabled(enabled); +//} +// +//int findBrush (int pixel) { +// return parent.findBrush (pixel); +//} +// +//Cursor findCursor () { +// if (cursor != null) return cursor; +// return parent.findCursor (); +//} +// +//Control findThemeControl () { +// return background == - 1 ? parent.findThemeControl () : null; +//} + +Menu [] findMenus (Control control) { + if (menu != null && this != control) return new Menu [] {menu}; + return new Menu [0]; +} + +//int findMnemonicIndex (String string) { +// int index = 0; +// int length = string.length (); +// do { +// while (index < length && string.charAt (index) != '&') index++; +// if (++index >= length) return -1; +// if (string.charAt (index) != '&') return index; +// index++; +// } while (index < length); +// return -1; +//} + +char findMnemonic (String string) { + int index = 0; + int length = string.length (); + do { + while (index < length && string.charAt (index) != '&') index++; + if (++index >= length) return '\0'; + if (string.charAt (index) != '&') return string.charAt (index); + index++; + } while (index < length); + return '\0'; +} + +void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) { + oldShell.fixShell (newShell, this); + oldDecorations.fixDecorations (newDecorations, this, menus); +} + +//void fixFocus (Control focusControl) { +// Shell shell = getShell (); +// Control control = this; +// while ((control = control.parent) != null) { +// if (control.setFocus ()) return; +// if (control == shell) break; +// } +// shell.setSavedFocus (focusControl); +// OS.SetFocus (0); +//} + +/** + * Forces the receiver to have the keyboard focus, causing + * all keyboard events to be delivered to it. + * + * @return true if the control got focus, and false if it was unable to. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setFocus + */ +public boolean forceFocus () { + checkWidget (); +// if (display.focusEvent == SWT.FocusOut) return false; +// Decorations shell = menuShell (); +// shell.setSavedFocus (this); + if (!isEnabled () /*|| !isActive ()*/) return false; + if(!handle.isFocusable()) return false; + if (!isVisible ()) { + Window window = SwingUtilities.getWindowAncestor(handle); + if(window != null && !window.isVisible()) { + getShell().setInitialFocusedControl(this); + return true; + } + return false; + } + if (isFocusControl ()) return true; +// shell.setSavedFocus (null); + // return handle.requestFocusInWindow(); + Window window = SwingUtilities.getWindowAncestor(handle); + if(window != null) { + window.setFocusableWindowState(true); + } +// if (handle instanceof JComponent) { +// ((javax.swing.JComponent) handle).grabFocus(); +// } else { + handle.requestFocus(); +// } + return true; + +// return handle.hasFocus(); +// /* +// * This code is intentionally commented. +// * +// * When setting focus to a control, it is +// * possible that application code can set +// * the focus to another control inside of +// * WM_SETFOCUS. In this case, the original +// * control will no longer have the focus +// * and the call to setFocus() will return +// * false indicating failure. +// * +// * We are still working on a solution at +// * this time. +// */ +//// if (OS.GetFocus () != OS.SetFocus (handle)) return false; +// OS.SetFocus (handle); +// if (isDisposed ()) return false; +// shell.setSavedFocus (this); +// return isFocusControl (); +} + +//void forceResize () { +// if (parent == null) return; +// WINDOWPOS [] lpwp = parent.lpwp; +// if (lpwp == null) return; +// for (int i=0; i 1) { +//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS; +//// } +// SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags); +// lpwp [i] = null; +// return; +// } +// } +//} + +/** + * Returns the accessible object for the receiver. + * If this is the first time this object is requested, + * then the object is created and returned. + * + * @return the accessible object + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Accessible#addAccessibleListener + * @see Accessible#addAccessibleControlListener + * + * @since 2.0 + */ +public Accessible getAccessible () { + checkWidget (); + if (accessible == null) accessible = new_Accessible (this); + return accessible; +} + +/** + * Returns the receiver's background color. + * + * @return the background color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Color getBackground () { + checkWidget (); + return Color.swing_new (display, ((CControl)handle).getUserAttributeHandler().getBackground()); +} + +//int getBackgroundPixel () { +// if (background == -1) return defaultBackground (); +// return background; +//} + +/** + * Returns the receiver's background image. + * + * @return the background image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public Image getBackgroundImage () { + checkWidget (); + return backgroundImage; +} + +/** + * Returns the receiver's border width. + * + * @return the border width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getBorderWidth () { + checkWidget (); + java.awt.Rectangle bounds = handle.getBounds(); + java.awt.Rectangle cBounds = ((CControl)handle).getClientArea().getBounds(); + return Math.max((bounds.width - cBounds.width + 1) / 2, (bounds.height - cBounds.height + 1) / 2); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent (or its display if its parent is null), + * unless the receiver is a shell. In this case, the location is + * relative to the display. + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds () { + checkWidget (); + java.awt.Rectangle rect = handle.getBounds(); + Point offset = parent == null? new Point(0, 0): parent.getInternalOffset(); + return new Rectangle (rect.x + offset.x, rect.y + offset.y, rect.width, rect.height); +// +// RECT rect = new RECT (); +// OS.GetWindowRect (topHandle (), rect); +// int hwndParent = parent == null ? 0 : parent.handle; +// OS.MapWindowPoints (0, hwndParent, rect, 2); +// int width = rect.right - rect.left; +// int height = rect.bottom - rect.top; +// return new Rectangle (rect.left, rect.top, width, height); +} + +//int getCodePage () { +// if (OS.IsUnicode) return OS.CP_ACP; +// int hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// LOGFONT logFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA (); +// OS.GetObject (hFont, LOGFONT.sizeof, logFont); +// int cs = logFont.lfCharSet & 0xFF; +// int [] lpCs = new int [8]; +// if (OS.TranslateCharsetInfo (cs, lpCs, OS.TCI_SRCCHARSET)) { +// return lpCs [1]; +// } +// return OS.GetACP (); +//} +// +//String getClipboardText () { +// String string = ""; +// if (OS.OpenClipboard (0)) { +// int hMem = OS.GetClipboardData (OS.IsUnicode ? OS.CF_UNICODETEXT : OS.CF_TEXT); +// if (hMem != 0) { +// /* Ensure byteCount is a multiple of 2 bytes on UNICODE platforms */ +// int byteCount = OS.GlobalSize (hMem) / TCHAR.sizeof * TCHAR.sizeof; +// int ptr = OS.GlobalLock (hMem); +// if (ptr != 0) { +// /* Use the character encoding for the default locale */ +// TCHAR buffer = new TCHAR (0, byteCount / TCHAR.sizeof); +// OS.MoveMemory (buffer, ptr, byteCount); +// string = buffer.toString (0, buffer.strlen ()); +// OS.GlobalUnlock (hMem); +// } +// } +// OS.CloseClipboard (); +// } +// return string; +//} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public boolean getEnabled () { + checkWidget (); + return handle.isEnabled(); +} + +/** + * Returns the font that the receiver will use to paint textual information. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Font getFont () { + checkWidget (); + return Font.swing_new (display, ((CControl)handle).getUserAttributeHandler().getFont()); +} + +/** + * Returns the foreground color that the receiver will use to draw. + * + * @return the receiver's foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Color getForeground () { + checkWidget (); + return Color.swing_new (display, ((CControl)handle).getUserAttributeHandler().getForeground()); +} + +//int getForegroundPixel () { +// if (foreground == -1) return defaultForeground (); +// return foreground; +//} + +/** + * Returns layout data which is associated with the receiver. + * + * @return the receiver's layout data + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Object getLayoutData () { + checkWidget (); + return layoutData; +} + +/** + * Returns a point describing the receiver's location relative + * to its parent (or its display if its parent is null), unless + * the receiver is a shell. In this case, the point is + * relative to the display. + * + * @return the receiver's location + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getLocation () { + checkWidget (); + java.awt.Point location = handle.getLocation(); + Point offset = parent == null? new Point(0, 0): parent.getInternalOffset(); + return new Point (location.x + offset.x, location.y + offset.y); +} + +/** + * Returns the receiver's pop up menu if it has one, or null + * if it does not. All controls may optionally have a pop up + * menu that is displayed when the user requests one for + * the control. The sequence of key strokes, button presses + * and/or button releases that are used to request a pop up + * menu is platform specific. + * + * @return the receiver's menu + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getMenu () { + checkWidget (); + return menu; +} + +/** + * Returns the receiver's monitor. + * + * @return the receiver's monitor + * + * @since 3.0 + */ +public Monitor getMonitor () { + checkWidget (); + GraphicsConfiguration gc = handle.getGraphicsConfiguration(); + Monitor monitor = new Monitor(); + monitor.handle = gc; + java.awt.Rectangle bounds = gc.getBounds(); + monitor.x = bounds.x; + monitor.y = bounds.y; + monitor.width = bounds.width; + monitor.height = bounds.height; + java.awt.Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + monitor.clientX = bounds.x + insets.left; + monitor.clientY = bounds.y + insets.top; + monitor.clientWidth = bounds.width - insets.left - insets.right; + monitor.clientHeight = bounds.height - insets.top - insets.bottom; + return monitor; +} + +/** + * Returns the receiver's parent, which must be a Composite + * or null when the receiver is a shell that was created with null or + * a display for a parent. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Composite getParent () { + checkWidget (); + return parent; +} + +Control [] getPath () { + int count = 0; + Shell shell = getShell (); + Control control = this; + while (control != shell) { + count++; + control = control.parent; + } + control = this; + Control [] result = new Control [count]; + while (control != shell) { + result [--count] = control; + control = control.parent; + } + return result; +} + +/** + * Returns the receiver's shell. For all controls other than + * shells, this simply returns the control's nearest ancestor + * shell. Shells return themselves, even if they are children + * of other shells. + * + * @return the receiver's shell + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getParent + */ +public Shell getShell () { + checkWidget (); + return parent.getShell (); +} + +/** + * Returns a point describing the receiver's size. The + * x coordinate of the result is the width of the receiver. + * The y coordinate of the result is the height of the + * receiver. + * + * @return the receiver's size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSize () { + checkWidget (); + java.awt.Dimension size = handle.getSize(); + return new Point(size.width, size.height); +} + +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getToolTipText () { + checkWidget (); + return toolTipText; +} + +/** + * Returns true if the receiver is visible, and + * false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget (); + return handle.isVisible(); +} + +//boolean hasCursor () { +// RECT rect = new RECT (); +// if (!OS.GetClientRect (handle, rect)) return false; +// OS.MapWindowPoints (handle, 0, rect, 2); +// POINT pt = new POINT (); +// return OS.GetCursorPos (pt) && OS.PtInRect (rect, pt); +//} +// +//boolean hasFocus () { +// /* +// * If a non-SWT child of the control has focus, +// * then this control is considered to have focus +// * even though it does not have focus in Windows. +// */ +// int hwndFocus = OS.GetFocus (); +// while (hwndFocus != 0) { +// if (hwndFocus == handle) return true; +// if (display.getControl (hwndFocus) != null) { +// return false; +// } +// hwndFocus = OS.GetParent (hwndFocus); +// } +// return false; +//} + +/** + * Invokes platform specific functionality to allocate a new GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Control. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param data the platform specific GC data + * @return the platform specific GC handle + */ +public CGC internal_new_GC (GCData data) { + checkWidget(); + if(data != null) { + int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; + if ((data.style & mask) != 0) { + data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? false : true; + } else { + if (!handle.getComponentOrientation().isLeftToRight()) { + data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED; + } else { + data.style |= SWT.LEFT_TO_RIGHT; + } + } + data.device = display; + data.foreground = handle.getForeground(); + data.background = handle.getBackground(); + data.hFont = handle.getFont(); + } +// Component clientArea = ((CControl)handle).getClientArea(); +// final Graphics2D g2D = (Graphics2D)clientArea.getGraphics(); +// if(g2D == null) { +// return null; +// } +// Point internalOffset = getInternalOffset(); +// g2D.translate(-internalOffset.x, -internalOffset.y); +// java.awt.Point point = new java.awt.Point(0, 0); +// point = SwingUtilities.convertPoint(component, point, handle); +// g2D.translate(-point.x, -point.y); + return new CGC.CGCGraphics2D() { + protected Graphics2D internalSwingGraphics2D; + protected Graphics2D graphics2D; + protected boolean isAdjusting; + public Graphics2D getGraphics() { + if(isAdjusting) { + return graphics2D; + } + Container clientArea = ((CControl)handle).getClientArea(); + Graphics2D sGraphics2D = clientArea instanceof JComponent? (Graphics2D)((JComponent)clientArea).getClientProperty(Utils.SWTSwingGraphics2DClientProperty): null; + boolean resetClip = false; + // sGraphics2D == null is needed because it seems it is not always the same GC for the native component. + if(internalSwingGraphics2D != sGraphics2D || sGraphics2D == null || graphics2D == null || graphics2D instanceof NullGraphics2D) { + Graphics2D newGraphics2D = (Graphics2D)clientArea.getGraphics(); + if(newGraphics2D == null) { + newGraphics2D = new NullGraphics2D(); + newGraphics2D.setBackground(clientArea.getBackground()); + newGraphics2D.setColor(clientArea.getForeground()); + newGraphics2D.setFont(clientArea.getFont()); + } + Point internalOffset = getInternalOffset(); + newGraphics2D.translate(-internalOffset.x, -internalOffset.y); + if(graphics2D != null) { + resetClip = true; + newGraphics2D.setBackground(graphics2D.getBackground()); + newGraphics2D.setColor(graphics2D.getColor()); + newGraphics2D.setComposite(graphics2D.getComposite()); + newGraphics2D.setFont(graphics2D.getFont()); + newGraphics2D.setPaint(graphics2D.getPaint()); + newGraphics2D.setRenderingHints(graphics2D.getRenderingHints()); + newGraphics2D.setStroke(graphics2D.getStroke()); + newGraphics2D.setTransform(graphics2D.getTransform()); + } + graphics2D = newGraphics2D; + internalSwingGraphics2D = sGraphics2D; + } + if(resetClip) { + isAdjusting = true; + setUserClip(getUserClip()); + isAdjusting = false; + } + return graphics2D; + } + public Dimension getDeviceSize() { + return ((CControl)handle).getClientArea().getSize(); + } + }; +// int hwnd = handle; +// if (data != null && data.hwnd != 0) { +// hwnd = data.hwnd; +// } +// int hDC = 0; +// if (data == null || data.ps == null) { +// hDC = OS.GetDC (hwnd); +// } else { +// hDC = OS.BeginPaint (hwnd, data.ps); +// } +// if (hDC == 0) SWT.error(SWT.ERROR_NO_HANDLES); +// if (data != null) { +// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) { +// int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; +// if ((data.style & mask) != 0) { +// data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0; +// } else { +// int flags = OS.GetLayout (hDC); +// if ((flags & OS.LAYOUT_RTL) != 0) { +// data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED; +// } else { +// data.style |= SWT.LEFT_TO_RIGHT; +// } +// } +// } else { +// data.style |= SWT.LEFT_TO_RIGHT; +// } +// data.device = display; +// data.foreground = getForegroundPixel (); +// data.background = getBackgroundPixel (); +// data.hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); +// } +// return hDC; +} + +/** + * Invokes platform specific functionality to dispose a GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Control. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param hDC the platform specific GC handle + * @param data the platform specific GC data + */ +public void internal_dispose_GC (CGC hDC, GCData data) { + checkWidget (); +// Component hwnd = handle; +// if (data != null && data.hwnd != null) { +// hwnd = data.hwnd; +// } + hDC.dispose(); +// if (data == null || data.ps == null) { +// OS.ReleaseDC (hwnd, hDC); +// } else { +// OS.EndPaint (hwnd, data.ps); +// } +} +// +//boolean isActive () { +// Shell dialogShell = display.getModalDialogShell (); +// if (dialogShell != null && dialogShell != getShell ()) { +// return false; +// } +// Shell shell = null; +// Shell [] modalShells = display.modalShells; +// if (modalShells != null) { +// int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL; +// int index = modalShells.length; +// while (--index >= 0) { +// Shell modal = modalShells [index]; +// if (modal != null) { +// if ((modal.style & bits) != 0) { +// Control control = this; +// while (control != null) { +// if (control == modal) break; +// control = control.parent; +// } +// if (control != modal) return false; +// break; +// } +// if ((modal.style & SWT.PRIMARY_MODAL) != 0) { +// if (shell == null) shell = getShell (); +// if (modal.parent == shell) return false; +// } +// } +// } +// } +// if (shell == null) shell = getShell (); +// return shell.getEnabled (); +//} + +/** + * Returns true if the receiver is enabled and all + * ancestors up to and including the receiver's nearest ancestor + * shell are enabled. Otherwise, false is returned. + * A disabled control is typically not selectable from the user + * interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public boolean isEnabled () { + checkWidget (); + return getEnabled () && parent.isEnabled (); +} + +/** + * Returns true if the receiver has the user-interface + * focus, and false otherwise. + * + * @return the receiver's focus state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean isFocusControl () { + checkWidget (); + return display.findControl(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner()) == this; +} + +//boolean isFocusAncestor (Control control) { +// while (control != null && control != this) { +// control = control.parent; +// } +// return control == this; +//} + +/** + * Returns true if the underlying operating + * system supports this reparenting, otherwise false + * + * @return true if the widget can be reparented, otherwise false + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean isReparentable () { + checkWidget (); + return true; +} + +//boolean isShowing () { +// /* +// * This is not complete. Need to check if the +// * widget is obscurred by a parent or sibling. +// */ +// if (!isVisible ()) return false; +// Control control = this; +// while (control != null) { +// Point size = control.getSize (); +// if (size.x == 0 || size.y == 0) { +// return false; +// } +// control = control.parent; +// } +// return true; +// /* +// * Check to see if current damage is included. +// */ +//// if (!OS.IsWindowVisible (handle)) return false; +//// int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS; +//// int hDC = OS.GetDCEx (handle, 0, flags); +//// int result = OS.GetClipBox (hDC, new RECT ()); +//// OS.ReleaseDC (handle, hDC); +//// return result != OS.NULLREGION; +//} + +boolean isTabGroup () { + Control [] tabList = parent._getTabList (); + if (tabList != null) { + for (int i=0; itrue if the receiver is visible and all + * ancestors up to and including the receiver's nearest ancestor + * shell are visible. Otherwise, false is returned. + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + */ +public boolean isVisible () { + checkWidget (); + return handle.isShowing(); +} + +//void mapEvent (int hwnd, Event event) { +// if (hwnd != handle) { +// POINT point = new POINT (); +// point.x = event.x; +// point.y = event.y; +// OS.MapWindowPoints (hwnd, handle, point, 1); +// event.x = point.x; +// event.y = point.y; +// } +//} + +void markLayout (boolean changed, boolean all) { + /* Do nothing */ +} + +Decorations menuShell () { + return parent.menuShell (); +} + +boolean mnemonicHit (char key) { + return false; +} + +boolean mnemonicMatch (char key) { + return false; +} + +/** + * Moves the receiver above the specified control in the + * drawing order. If the argument is null, then the receiver + * is moved to the top of the drawing order. The control at + * the top of the drawing order will not be covered by other + * controls even if they occupy intersecting areas. + * + * @param control the sibling control (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Control#moveBelow + * @see Composite#getChildren + */ +public void moveAbove (Control control) { + checkWidget (); + Container cParent = handle.getParent(); + if (control != null) { + if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); + if (handle == control.handle) return; + if (parent != control.parent) return; + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + boolean isFound = false; + for(int i=cParent.getComponentCount()-1; i>=0; i--) { + isFound = control.handle == handle; + if(cParent.getComponent(i) == control.handle) { + cParent.remove(handle); + cParent.add(handle, isFound? i: i-1); + handle.invalidate(); + cParent.validate(); + cParent.repaint(); + break; + } + } + return; + } + int cOrder = cParent.getComponentZOrder(control.handle); + int order = cParent.getComponentZOrder(handle); + if(order < cOrder) { + cOrder--; + } + cParent.setComponentZOrder(handle, cOrder); + } else { + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + cParent.remove(handle); + cParent.add(handle, 0); + handle.invalidate(); + cParent.validate(); + cParent.repaint(); + return; + } + cParent.setComponentZOrder(handle, 0); + } +// int topHandle = topHandle (), hwndAbove = OS.HWND_TOP; +// if (control != null) { +// if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); +// if (parent != control.parent) return; +// int hwnd = control.topHandle (); +// if (hwnd == 0 || hwnd == topHandle) return; +// hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV); +// /* +// * Bug in Windows. For some reason, when GetWindow () +// * with GW_HWNDPREV is used to query the previous window +// * in the z-order with the first child, Windows returns +// * the first child instead of NULL. The fix is to detect +// * this case and move the control to the top. +// */ +// if (hwndAbove == 0 || hwndAbove == hwnd) { +// hwndAbove = OS.HWND_TOP; +// } +// } +// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; +// SetWindowPos (topHandle, hwndAbove, 0, 0, 0, 0, flags); +} + +/** + * Moves the receiver below the specified control in the + * drawing order. If the argument is null, then the receiver + * is moved to the bottom of the drawing order. The control at + * the bottom of the drawing order will be covered by all other + * controls which occupy intersecting areas. + * + * @param control the sibling control (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Control#moveAbove + * @see Composite#getChildren + */ +public void moveBelow (Control control) { + checkWidget (); + Container cParent = handle.getParent(); + if (control != null) { + if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); + if (handle == control.handle) return; + if (parent != control.parent) return; + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + boolean isFound = false; + for(int i=cParent.getComponentCount()-1; i>=0; i--) { + isFound = control.handle == handle; + if(cParent.getComponent(i) == control.handle) { + cParent.remove(handle); + cParent.add(handle, isFound? i: i+1); + handle.invalidate(); + cParent.validate(); + cParent.repaint(); + break; + } + } + return; + } + int cOrder = cParent.getComponentZOrder(control.handle); + int order = cParent.getComponentZOrder(handle); + if(order < cOrder) { + cOrder--; + } + cParent.setComponentZOrder(handle, cOrder + 1); + } else { + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + cParent.remove(handle); + cParent.add(handle); + handle.invalidate(); + cParent.validate(); + cParent.repaint(); + return; + } + cParent.setComponentZOrder(handle, cParent.getComponentCount() - 1); + } +// int topHandle = topHandle (), hwndAbove = OS.HWND_BOTTOM; +// if (control != null) { +// if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); +// if (parent != control.parent) return; +// hwndAbove = control.topHandle (); +// } +// if (hwndAbove == 0 || hwndAbove == topHandle) return; +// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; +// SetWindowPos (topHandle, hwndAbove, 0, 0, 0, 0, flags); +} + +Accessible new_Accessible (Control control) { + return Accessible.internal_new_Accessible (this); +} + +GC new_GC (GCData data) { + return GC.swing_new (this, data); +} + +/** + * Causes the receiver to be resized to its preferred size. + * For a composite, this involves computing the preferred size + * from its layout, if there is one. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #computeSize(int, int, boolean) + */ +public void pack () { + checkWidget (); + pack (true); +} + +/** + * Causes the receiver to be resized to its preferred size. + * For a composite, this involves computing the preferred size + * from its layout, if there is one. + *

    + * If the changed flag is true, it indicates that the receiver's + * contents have changed, therefore any caches that a layout manager + * containing the control may have been keeping need to be flushed. When the + * control is resized, the changed flag will be false, so layout + * manager caches can be retained. + *

    + * + * @param changed whether or not the receiver's contents have changed + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #computeSize(int, int, boolean) + */ +public void pack (boolean changed) { + checkWidget (); + setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed)); +} + +/** + * Causes the entire bounds of the receiver to be marked + * as needing to be redrawn. The next time a paint request + * is processed, the control will be completely painted, + * including the background. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #update + * @see PaintListener + * @see SWT#Paint + * @see SWT#NO_BACKGROUND + * @see SWT#NO_REDRAW_RESIZE + * @see SWT#NO_MERGE_PAINTS + */ +public void redraw () { + checkWidget (); + handle.repaint(); +// if (!OS.IsWindowVisible (handle)) return; +// if (OS.IsWinCE) { +// OS.InvalidateRect (handle, null, true); +// } else { +// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE; +// OS.RedrawWindow (handle, null, 0, flags); +// } +} + +/** + * Causes the rectangular area of the receiver specified by + * the arguments to be marked as needing to be redrawn. + * The next time a paint request is processed, that area of + * the receiver will be painted, including the background. + * If the all flag is true, any + * children of the receiver which intersect with the specified + * area will also paint their intersecting areas. If the + * all flag is false, the children + * will not be painted. + * + * @param x the x coordinate of the area to draw + * @param y the y coordinate of the area to draw + * @param width the width of the area to draw + * @param height the height of the area to draw + * @param all true if children should redraw, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #update + * @see PaintListener + * @see SWT#Paint + * @see SWT#NO_BACKGROUND + * @see SWT#NO_REDRAW_RESIZE + * @see SWT#NO_MERGE_PAINTS + */ +public void redraw (int x, int y, int width, int height, boolean all) { + checkWidget (); + if (width <= 0 || height <= 0) return; + // TODO: what about the "all" setting? +// handle.repaint(); + // TODO: check using the Paint Example why this repaint needs -1 and +2... + ((CControl)handle).getClientArea().repaint(x-1, y-1, width+2, height+2); +// if (!OS.IsWindowVisible (handle)) return; +// RECT rect = new RECT (); +// OS.SetRect (rect, x, y, x + width, y + height); +// if (OS.IsWinCE) { +// OS.InvalidateRect (handle, rect, true); +// } else { +// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE; +// if (all) flags |= OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (handle, rect, 0, flags); +// } +} + +void register () { + display.addControl (handle, this); +} + +void releaseHandle () { + super.releaseHandle (); + handle = null; + parent = null; +} + +void releaseParent () { + Container parent = handle.getParent(); + if(parent != null) { + parent.remove(handle); + ((JComponent)parent).revalidate(); + parent.repaint(); + } + this.parent.removeControl (this); +} + +void releaseWidget () { + if(focusLostRunnable != null && getShell().getActiveControl() == this) { + focusLostRunnable.run(); + } + super.releaseWidget (); +// if (OS.IsDBLocale) { +// OS.ImmAssociateContext (handle, 0); +// } +// if (toolTipText != null) { +// Shell shell = getShell (); +// shell.setToolTipText (handle, null); +// } +// toolTipText = null; + if (menu != null && !menu.isDisposed ()) { + menu.dispose (); + } + menu = null; +// cursor = null; + deregister (); +// unsubclass (); + layoutData = null; + if (accessible != null) { + accessible.internal_dispose_Accessible (); + } + accessible = null; + if(disabledStatePanel != null) { + disabledStatePanel.release(); + disabledStatePanel = null; + } +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is moved or resized. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #addControlListener + */ +public void removeControlListener (ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Move, listener); + eventTable.unhook (SWT.Resize, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control gains or loses focus. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see FocusListener + * @see #addFocusListener + */ +public void removeFocusListener(FocusListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.FocusIn, listener); + eventTable.unhook (SWT.FocusOut, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the help events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #addHelpListener + */ +public void removeHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Help, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when keys are pressed and released on the system keyboard. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see KeyListener + * @see #addKeyListener + */ +public void removeKeyListener(KeyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.KeyUp, listener); + eventTable.unhook (SWT.KeyDown, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the mouse passes or hovers over controls. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseTrackListener + * @see #addMouseTrackListener + */ +public void removeMouseTrackListener(MouseTrackListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.MouseEnter, listener); + eventTable.unhook (SWT.MouseExit, listener); + eventTable.unhook (SWT.MouseHover, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when mouse buttons are pressed and released. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseListener + * @see #addMouseListener + */ +public void removeMouseListener (MouseListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.MouseDown, listener); + eventTable.unhook (SWT.MouseUp, listener); + eventTable.unhook (SWT.MouseDoubleClick, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the mouse moves. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MouseMoveListener + * @see #addMouseMoveListener + */ +public void removeMouseMoveListener(MouseMoveListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.MouseMove, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver needs to be painted. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see PaintListener + * @see #addPaintListener + */ +public void removePaintListener(PaintListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook(SWT.Paint, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when traversal events occur. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see TraverseListener + * @see #addTraverseListener + */ +public void removeTraverseListener(TraverseListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Traverse, listener); +} + +//void showWidget (boolean visible) { +// OS.ShowWindow (handle, visible ? OS.SW_SHOW : OS.SW_HIDE); +//} +// +//boolean sendFocusEvent (int type) { +// Shell shell = getShell (); +// +// /* +// * Feature in Windows. During the processing of WM_KILLFOCUS, +// * when the focus window is queried using GetFocus(), it has +// * already been assigned to the new window. The fix is to +// * remember the control that is losing or gaining focus and +// * answer it during WM_KILLFOCUS. If a WM_SETFOCUS occurs +// * during WM_KILLFOCUS, the focus control needs to be updated +// * to the current control. At any other time, the focus +// * control matches Windows. +// */ +// Display display = this.display; +// display.focusEvent = type; +// display.focusControl = this; +// sendEvent (type); +// // widget could be disposed at this point +// display.focusEvent = SWT.None; +// display.focusControl = null; +// +// /* +// * It is possible that the shell may be +// * disposed at this point. If this happens +// * don't send the activate and deactivate +// * events. +// */ +// if (!shell.isDisposed ()) { +// switch (type) { +// case SWT.FocusIn: +// shell.setActiveControl (this); +// break; +// case SWT.FocusOut: +// if (shell != display.getActiveShell ()) { +// shell.setActiveControl (null); +// } +// break; +// } +// } +// return true; +//} + +/** + * Sets the receiver's background color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setBackground (Color color) { + checkWidget (); + if (color != null) { + if (color.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT); + ((CControl)handle).getUserAttributeHandler().setBackground (color.handle); + } else { + ((CControl)handle).getUserAttributeHandler().setBackground (null); + } + handle.repaint(); +} + +/** + * Sets the receiver's background image to the image specified + * by the argument, or to the default system color for the control + * if the argument is null. The background image is tiled to fill + * the available space. + * + * @param image the new image (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    • ERROR_INVALID_ARGUMENT - if the argument is not a bitmap
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setBackgroundImage (Image image) { + checkWidget (); + if (image != null) { + if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT); + } + if (backgroundImage == image) return; + backgroundImage = image; + ((CControl)handle).setBackgroundImage(backgroundImage == null? null: backgroundImage.handle); + handle.repaint(); +} + +//void setBackgroundPixel (int pixel) { +// if (background == pixel) return; +// background = pixel; +// OS.InvalidateRect (handle, null, true); +//} + +/** + * Sets the receiver's size and location to the rectangular + * area specified by the arguments. The x and + * y arguments are relative to the receiver's + * parent (or its display if its parent is null), unless + * the receiver is a shell. In this case, the x + * and y arguments are relative to the display. + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause that + * value to be set to zero instead. + *

    + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * @param width the new width for the receiver + * @param height the new height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setBounds (int x, int y, int width, int height) { + checkWidget (); + if(width < 0) width = 0; + if(height < 0) height = 0; + Point offset = parent == null? new Point(0, 0): parent.getInternalOffset(); + x -= offset.x; + y -= offset.y; +// java.awt.Point location = new java.awt.Point(x, y); +// Container parent = handle.getParent(); +// if(parent != null) { +// location = SwingUtilities.convertPoint(this.parent.handle, location, parent); +// } + java.awt.Rectangle bounds = handle.getBounds(); + if(bounds.x == x && bounds.y == y && bounds.width == width && bounds.height == height) return; + handle.setBounds(x, y, width, height); + // The notification has to be immediate in SWT, so we force it + if(bounds.width != width || bounds.height != height) { + ((CControl)handle).getClientArea().invalidate(); + handle.validate(); + processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_RESIZED)); + } + // The notification has to be immediate in SWT, so we force it + if(bounds.x != x || bounds.y != y) { + processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_MOVED)); + } + handle.repaint(); +} + +//void setBounds (int x, int y, int width, int height, int flags) { +// setBounds (x, y, width, height, flags, true); +//} +// +//void setBounds (int x, int y, int width, int height, int flags, boolean defer) { +// int topHandle = topHandle (); +// if (defer && parent != null) { +// forceResize (); +// WINDOWPOS [] lpwp = parent.lpwp; +// if (lpwp == null) { +// /* +// * This code is intentionally commented. All widgets that +// * are created by SWT have WS_CLIPSIBLINGS to ensure that +// * application code does not draw outside of the control. +// */ +//// int count = parent.getChildrenCount (); +//// if (count > 1) { +//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) flags |= OS.SWP_NOCOPYBITS; +//// } +// SetWindowPos (topHandle, 0, x, y, width, height, flags); +// } else { +// int index = 0; +// while (index < lpwp.length) { +// if (lpwp [index] == null) break; +// index ++; +// } +// if (index == lpwp.length) { +// WINDOWPOS [] newLpwp = new WINDOWPOS [lpwp.length + 4]; +// System.arraycopy (lpwp, 0, newLpwp, 0, lpwp.length); +// parent.lpwp = lpwp = newLpwp; +// } +// WINDOWPOS wp = new WINDOWPOS (); +// wp.hwnd = topHandle; +// wp.x = x; +// wp.y = y; +// wp.cx = width; +// wp.cy = height; +// wp.flags = flags; +// lpwp [index] = wp; +// } +// } else { +// SetWindowPos (topHandle, 0, x, y, width, height, flags); +// } +//} + +/** + * Sets the receiver's size and location to the rectangular + * area specified by the argument. The x and + * y fields of the rectangle are relative to + * the receiver's parent (or its display if its parent is null). + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause that + * value to be set to zero instead. + *

    + * + * @param rect the new bounds for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setBounds (Rectangle rect) { + checkWidget (); + if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); + setBounds (rect.x, rect.y, rect.width, rect.height); +} + +/** + * If the argument is true, causes the receiver to have + * all mouse events delivered to it until the method is called with + * false as the argument. + * + * @param capture true to capture the mouse, and false to release it + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setCapture (boolean capture) { + checkWidget (); + if (capture) { + Utils.capturedControl = this; + } else { + if (Utils.capturedControl == this) { + Utils.capturedControl = null; + } + } +// if (capture) { +// OS.SetCapture (handle); +// } else { +// if (OS.GetCapture () == handle) { +// OS.ReleaseCapture (); +// } +// } +} + +void sendMouseEvent(int eventType, Event event) { + if(Utils.capturedControl == null || Utils.capturedControl == this) { + sendEvent(eventType, event); + return; + } + Control control = Utils.capturedControl; + switch(eventType) { + case SWT.MouseDown: + case SWT.MouseUp: + Utils.capturedControl = null; + break; + } + java.awt.Point point = SwingUtilities.convertPoint(handle, event.x, event.y, control.handle); + event.x = point.x; + event.y = point.y; + control.sendEvent(eventType, event); +} + +//void setCursor () { +// int lParam = OS.HTCLIENT | (OS.WM_MOUSEMOVE << 16); +// OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam); +//} + +/** + * Sets the receiver's cursor to the cursor specified by the + * argument, or to the default cursor for that kind of control + * if the argument is null. + *

    + * When the mouse pointer passes over a control its appearance + * is changed to match the control's cursor. + *

    + * + * @param cursor the new cursor (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setCursor (Cursor cursor) { + checkWidget (); + if (cursor != null) { + if (cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + ((CControl)handle).getUserAttributeHandler().setCursor(cursor.handle); + } else { + ((CControl)handle).getUserAttributeHandler().setCursor (null); + } +// this.cursor = cursor; +// if (OS.IsWinCE) { +// int hCursor = cursor != null ? cursor.handle : 0; +// OS.SetCursor (hCursor); +// return; +// } +// int hwndCursor = OS.GetCapture (); +// if (hwndCursor == 0) { +// POINT pt = new POINT (); +// if (!OS.GetCursorPos (pt)) return; +// int hwnd = hwndCursor = OS.WindowFromPoint (pt); +// while (hwnd != 0 && hwnd != handle) { +// hwnd = OS.GetParent (hwnd); +// } +// if (hwnd == 0) return; +// } +// Control control = display.getControl (hwndCursor); +// if (control == null) control = this; +// control.setCursor (); +} + +//void setDefaultFont () { +// int hFont = display.systemFont (); +// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0); +//} + +private DisabledStatePanel disabledStatePanel; + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (boolean enabled) { + checkWidget (); + handle.setEnabled(enabled); + if(enabled) { + if(disabledStatePanel != null) { + disabledStatePanel.release(); + disabledStatePanel = null; + } + } else { + if(disabledStatePanel == null) { + disabledStatePanel = new DisabledStatePanel(this); + } + } +// /* +// * Feature in Windows. If the receiver has focus, disabling +// * the receiver causes no window to have focus. The fix is +// * to assign focus to the first ancestor window that takes +// * focus. If no window will take focus, set focus to the +// * desktop. +// */ +// Control control = null; +// boolean fixFocus = false; +// if (!enabled) { +// if (display.focusEvent != SWT.FocusOut) { +// control = display.getFocusControl (); +// fixFocus = isFocusAncestor (control); +// } +// } +// enableWidget (enabled); +// if (fixFocus) fixFocus (control); +} + +/** + * Causes the receiver to have the keyboard focus, + * such that all keyboard events will be delivered to it. Focus + * reassignment will respect applicable platform constraints. + * + * @return true if the control got focus, and false if it was unable to. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #forceFocus + */ +public boolean setFocus () { + checkWidget (); + if ((style & SWT.NO_FOCUS) != 0) return false; + return forceFocus (); +} + +/** + * Sets the font that the receiver will use to paint textual information + * to the font specified by the argument, or to the default font for that + * kind of control if the argument is null. + * + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setFont (Font font) { + checkWidget (); + if (font != null) { + if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + ((CControl)handle).getUserAttributeHandler().setFont(font.handle); + } else { + ((CControl)handle).getUserAttributeHandler().setFont(null); + } + handle.repaint(); +} + +/** + * Sets the receiver's foreground color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setForeground (Color color) { + checkWidget (); + if (color != null) { + if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + ((CControl)handle).getUserAttributeHandler().setForeground(color.handle); + } else { + ((CControl)handle).getUserAttributeHandler().setForeground (null); + } + handle.repaint(); +} + +//void setForegroundPixel (int pixel) { +// if (foreground == pixel) return; +// foreground = pixel; +// OS.InvalidateRect (handle, null, true); +//} + +/** + * Sets the layout data associated with the receiver to the argument. + * + * @param layoutData the new layout data for the receiver. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLayoutData (Object layoutData) { + checkWidget (); + this.layoutData = layoutData; +} + +/** + * Sets the receiver's location to the point specified by + * the arguments which are relative to the receiver's + * parent (or its display if its parent is null), unless + * the receiver is a shell. In this case, the point is + * relative to the display. + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (int x, int y) { + checkWidget (); + Point offset = parent == null? new Point(0, 0): parent.getInternalOffset(); + x -= offset.x; + y -= offset.y; + java.awt.Point location = handle.getLocation(); + if(location.x == x && location.y == y) return; + handle.setLocation(x, y); +// ((CControl)handle).getClientArea().invalidate(); +// handle.validate(); + // The notification has to be immediate in SWT, so we force it + if(location.x != x || location.y != y) { + processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_MOVED)); + } + handle.repaint(); +// Container parent = handle.getParent(); +// if(parent != null) { +// if(parent instanceof JComponent) { +// ((JComponent)parent).revalidate(); +// } else { +// parent.invalidate(); +// parent.validate(); +// } +// parent.repaint(); +// } +} + +/** + * Sets the receiver's location to the point specified by + * the arguments which are relative to the receiver's + * parent (or its display if its parent is null), unless + * the receiver is a shell. In this case, the point is + * relative to the display. + * + * @param location the new location for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (Point location) { + checkWidget (); + if (location == null) error (SWT.ERROR_NULL_ARGUMENT); + setLocation (location.x, location.y); +} + +/** + * Sets the receiver's pop up menu to the argument. + * All controls may optionally have a pop up + * menu that is displayed when the user requests one for + * the control. The sequence of key strokes, button presses + * and/or button releases that are used to request a pop up + * menu is platform specific. + *

    + * Note: Disposing of a control that has a pop up menu will + * dispose of the menu. To avoid this behavior, set the + * menu to null before the control is disposed. + *

    + * + * @param menu the new pop up menu + * + * @exception IllegalArgumentException
      + *
    • ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu
    • + *
    • ERROR_INVALID_PARENT - if the menu is not in the same widget tree
    • + *
    • ERROR_INVALID_ARGUMENT - if the menu has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMenu (Menu menu) { + checkWidget (); + if (menu != null) { + if (menu.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if ((menu.style & SWT.POP_UP) == 0) { + error (SWT.ERROR_MENU_NOT_POP_UP); + } + if (menu.parent != menuShell ()) { + error (SWT.ERROR_INVALID_PARENT); + } + } + this.menu = menu; +} + +boolean setRadioFocus () { + return false; +} + +boolean setRadioSelection (boolean value) { + return false; +} + +/** + * If the argument is false, causes subsequent drawing + * operations in the receiver to be ignored. No drawing of any kind + * can occur in the receiver until the flag is set to true. + * Graphics operations that occurred while the flag was + * false are lost. When the flag is set to true, + * the entire widget is marked as needing to be redrawn. Nested calls + * to this method are stacked. + *

    + * Note: This operation is a hint and may not be supported on some + * platforms or for some widgets. + *

    + * + * @param redraw the new redraw state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #redraw(int, int, int, int, boolean) + * @see #update + */ +public void setRedraw (boolean redraw) { + checkWidget (); + handle.setIgnoreRepaint(!redraw); +} + +//boolean setSavedFocus () { +// return forceFocus (); +//} + +/** + * Sets the receiver's size to the point specified by the arguments. + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause that + * value to be set to zero instead. + *

    + * + * @param width the new width for the receiver + * @param height the new height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (int width, int height) { + checkWidget (); + if(width < 0) width = 0; + if(height < 0) height = 0; + java.awt.Dimension size = handle.getSize(); + handle.setSize(width, height); + // The notification has to be immediate in SWT, so we force it + if(size.width != width || size.height != height) { + ((CControl)handle).getClientArea().invalidate(); + handle.validate(); + processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_RESIZED)); + } + handle.repaint(); +} + +/** + * Sets the receiver's size to the point specified by the argument. + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause them to be + * set to zero instead. + *

    + * + * @param size the new size for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (Point size) { + checkWidget (); + if (size == null) error (SWT.ERROR_NULL_ARGUMENT); + setSize (size.x, size.y); +} + +boolean setTabGroupFocus () { + return setTabItemFocus (); +} + +boolean setTabItemFocus () { + if (!handle.isShowing ()) return false; + return forceFocus (); +} + +String toolTipText; + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setToolTipText (String string) { + checkWidget (); + toolTipText = string; + ((CControl)handle).setToolTipText(Utils.convertStringToHTML(string)); +} + +/** + * Marks the receiver as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget (); + handle.setVisible(visible); +// if (drawCount != 0) { +// if (((state & HIDDEN) == 0) == visible) return; +// } else { +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// if (((bits & OS.WS_VISIBLE) != 0) == visible) return; +// } + // TODO: uncomment the next lines, or attach a listener to components? +// if (visible) { +// sendEvent (SWT.Show); +// if (isDisposed ()) return; +// } + +// /* +// * Feature in Windows. If the receiver has focus, hiding +// * the receiver causes no window to have focus. The fix is +// * to assign focus to the first ancestor window that takes +// * focus. If no window will take focus, set focus to the +// * desktop. +// */ +// Control control = null; +// boolean fixFocus = false; +// if (!visible) { +// if (display.focusEvent != SWT.FocusOut) { +// control = display.getFocusControl (); +// fixFocus = isFocusAncestor (control); +// } +// } +// if (drawCount != 0) { +// state = visible ? state & ~HIDDEN : state | HIDDEN; +// } else { +// showWidget (visible); +// if (isDisposed ()) return; +// } +// if (!visible) { +// sendEvent (SWT.Hide); +// if (isDisposed ()) return; +// } +// if (fixFocus) fixFocus (control); +} + +void sort (int [] items) { + /* Shell Sort from K&R, pg 108 */ + int length = items.length; + for (int gap=length/2; gap>0; gap/=2) { + for (int i=gap; i=0; j-=gap) { + if (items [j] <= items [j + gap]) { + int swap = items [j]; + items [j] = items [j + gap]; + items [j + gap] = swap; + } + } + } + } +} + +//void subclass () { +// int oldProc = windowProc (); +// int newProc = display.windowProc; +// if (oldProc == newProc) return; +// OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc); +//} + +/** + * Returns a point which is the result of converting the + * argument, which is specified in display relative coordinates, + * to coordinates relative to the receiver. + *

    + * @param x the x coordinate to be translated + * @param y the y coordinate to be translated + * @return the translated coordinates + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public Point toControl (int x, int y) { + checkWidget (); + java.awt.Point point = new java.awt.Point(x, y); + Container container = handle; + if(container instanceof RootPaneContainer) { + container = ((RootPaneContainer)container).getContentPane(); + } + SwingUtilities.convertPointFromScreen(point, container); + return new Point(point.x, point.y); +} + +/** + * Returns a point which is the result of converting the + * argument, which is specified in display relative coordinates, + * to coordinates relative to the receiver. + *

    + * @param point the point to be translated (must not be null) + * @return the translated coordinates + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point toControl (Point point) { + checkWidget (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + return toControl (point.x, point.y); +} + +/** + * Returns a point which is the result of converting the + * argument, which is specified in coordinates relative to + * the receiver, to display relative coordinates. + *

    + * @param x the x coordinate to be translated + * @param y the y coordinate to be translated + * @return the translated coordinates + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public Point toDisplay (int x, int y) { + checkWidget (); + java.awt.Point point = new java.awt.Point(x, y); + Container container = handle; + if(container instanceof RootPaneContainer) { + container = ((RootPaneContainer)container).getContentPane(); + } + SwingUtilities.convertPointToScreen(point, container); + return new Point(point.x, point.y); +} + +/** + * Returns a point which is the result of converting the + * argument, which is specified in coordinates relative to + * the receiver, to display relative coordinates. + *

    + * @param point the point to be translated (must not be null) + * @return the translated coordinates + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point toDisplay (Point point) { + checkWidget (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + return toDisplay (point.x, point.y); +} + +//int topHandle () { +// return handle; +//} + +//boolean translateAccelerator (MSG msg) { +// return menuShell ().translateAccelerator (msg); +//} + +boolean translateMnemonic (Event event, Control control) { + if (control == this) return false; + if (!isVisible () || !isEnabled ()) return false; + event.doit = mnemonicMatch (event.character); + return traverse (event); +} + +//boolean translateMnemonic (MSG msg) { +// if (msg.wParam < 0x20) return false; +// int hwnd = msg.hwnd; +// if (OS.GetKeyState (OS.VK_MENU) >= 0) { +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & OS.DLGC_WANTALLKEYS) != 0) return false; +// if ((code & OS.DLGC_BUTTON) == 0) return false; +// } +// Decorations shell = menuShell (); +// if (shell.isVisible () && shell.isEnabled ()) { +// display.lastAscii = msg.wParam; +// display.lastNull = display.lastDead = false; +// Event event = new Event (); +// event.detail = SWT.TRAVERSE_MNEMONIC; +// if (setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) { +// return translateMnemonic (event, null) || shell.translateMnemonic (event, this); +// } +// } +// return false; +//} +// +//boolean translateTraversal (MSG msg) { +// int key = msg.wParam; +// if (key == OS.VK_MENU) { +// Shell shell = getShell (); +// int hwndShell = shell.handle; +// OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); +// return false; +// } +// int hwnd = msg.hwnd; +// int detail = SWT.TRAVERSE_NONE; +// boolean doit = true, all = false; +// boolean lastVirtual = false; +// int lastKey = key, lastAscii = 0; +// switch (key) { +// case OS.VK_ESCAPE: { +// all = true; +// lastAscii = 27; +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & OS.DLGC_WANTALLKEYS) != 0) { +// /* +// * Use DLGC_HASSETSEL to determine that the control +// * is a text widget. A text widget normally wants +// * all keys except VK_ESCAPE. If this bit is not +// * set, then assume the control wants all keys, +// * including VK_ESCAPE. +// */ +// if ((code & OS.DLGC_HASSETSEL) == 0) doit = false; +// } +// detail = SWT.TRAVERSE_ESCAPE; +// break; +// } +// case OS.VK_RETURN: { +// all = true; +// lastAscii = '\r'; +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false; +// detail = SWT.TRAVERSE_RETURN; +// break; +// } +// case OS.VK_TAB: { +// lastAscii = '\t'; +// boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0; +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) != 0) { +// /* +// * Use DLGC_HASSETSEL to determine that the control is a +// * text widget. If the control is a text widget, then +// * Ctrl+Tab and Shift+Tab should traverse out of the widget. +// * If the control is not a text widget, the correct behavior +// * is to give every character, including Tab, Ctrl+Tab and +// * Shift+Tab to the control. +// */ +// if ((code & OS.DLGC_HASSETSEL) != 0) { +// if (next && OS.GetKeyState (OS.VK_CONTROL) >= 0) { +// doit = false; +// } +// } else { +// doit = false; +// } +// } +// if (parent != null && (parent.style & SWT.MIRRORED) != 0) { +// if (key == OS.VK_LEFT || key == OS.VK_RIGHT) next = !next; +// } +// detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS; +// break; +// } +// case OS.VK_UP: +// case OS.VK_LEFT: +// case OS.VK_DOWN: +// case OS.VK_RIGHT: { +// /* +// * On WinCE SP there is no tab key. Focus is assigned +// * using the VK_UP and VK_DOWN keys, not with VK_LEFT +// * or VK_RIGHT. +// */ +// if (OS.IsSP) { +// if (key == OS.VK_LEFT || key == OS.VK_RIGHT) return false; +// } +// lastVirtual = true; +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) != 0) doit = false; +// boolean next = key == OS.VK_DOWN || key == OS.VK_RIGHT; +// detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS; +// break; +// } +// case OS.VK_PRIOR: +// case OS.VK_NEXT: { +// all = true; +// lastVirtual = true; +// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false; +// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); +// if ((code & OS.DLGC_WANTALLKEYS) != 0) { +// /* +// * Use DLGC_HASSETSEL to determine that the control is a +// * text widget. If the control is a text widget, then +// * Ctrl+PgUp and Ctrl+PgDn should traverse out of the widget. +// */ +// if ((code & OS.DLGC_HASSETSEL) == 0) doit = false; +// } +// detail = key == OS.VK_PRIOR ? SWT.TRAVERSE_PAGE_PREVIOUS : SWT.TRAVERSE_PAGE_NEXT; +// break; +// } +// default: +// return false; +// } +// Event event = new Event (); +// event.doit = doit; +// event.detail = detail; +// display.lastKey = lastKey; +// display.lastAscii = lastAscii; +// display.lastVirtual = lastVirtual; +// display.lastNull = display.lastDead = false; +// if (!setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) return false; +// Shell shell = getShell (); +// Control control = this; +// do { +// if (control.traverse (event)) { +// int hwndShell = shell.handle; +// OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); +// return true; +// } +// if (!event.doit && control.hooks (SWT.Traverse)) return false; +// if (control == shell) return false; +// control = control.parent; +// } while (all && control != null); +// return false; +//} + +boolean traverse (Event event) { + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the traverse + * event. If this happens, return true to stop further + * event processing. + */ + sendEvent (SWT.Traverse, event); + if (isDisposed ()) return true; + if (!event.doit) return false; + switch (event.detail) { + case SWT.TRAVERSE_NONE: return true; + case SWT.TRAVERSE_ESCAPE: return traverseEscape (); + case SWT.TRAVERSE_RETURN: return traverseReturn (); + case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true); + case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false); + case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true); + case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false); + case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event.character); + case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true); + case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false); + } + return false; +} + +/** + * Based on the argument, perform one of the expected platform + * traversal action. The argument should be one of the constants: + * SWT.TRAVERSE_ESCAPE, SWT.TRAVERSE_RETURN, + * SWT.TRAVERSE_TAB_NEXT, SWT.TRAVERSE_TAB_PREVIOUS, + * SWT.TRAVERSE_ARROW_NEXT and SWT.TRAVERSE_ARROW_PREVIOUS. + * + * @param traversal the type of traversal + * @return true if the traversal succeeded + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean traverse (int traversal) { + checkWidget (); + Event event = new Event (); + event.doit = true; + event.detail = traversal; + return traverse (event); +} + +boolean traverseEscape () { + return false; +} + +boolean traverseGroup (boolean next) { + Control root = computeTabRoot (); + Control group = computeTabGroup (); + Control [] list = root.computeTabList (); + int length = list.length; + int index = 0; + while (index < length) { + if (list [index] == group) break; + index++; + } + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in focus in + * or out events. Ensure that a disposed widget is + * not accessed. + */ + if (index == length) return false; + int start = index, offset = (next) ? 1 : -1; + while ((index = ((index + offset + length) % length)) != start) { + Control control = list [index]; + if (!control.isDisposed () && control.setTabGroupFocus ()) { + return true; + } + } + if (group.isDisposed ()) return false; + return group.setTabGroupFocus (); +} + +boolean traverseItem (boolean next) { + Control [] children = parent._getChildren (); + int length = children.length; + int index = 0; + while (index < length) { + if (children [index] == this) break; + index++; + } + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in focus in + * or out events. Ensure that a disposed widget is + * not accessed. + */ + if (index == length) return false; + int start = index, offset = (next) ? 1 : -1; + while ((index = (index + offset + length) % length) != start) { + Control child = children [index]; + if (!child.isDisposed () && child.isTabItem ()) { + if (child.setTabItemFocus ()) return true; + } + } + return false; +} + +boolean traverseMnemonic (char key) { + return mnemonicHit (key); +} + +boolean traversePage (boolean next) { + return false; +} + +boolean traverseReturn () { + return false; +} + +//void unsubclass () { +// int newProc = windowProc (); +// int oldProc = display.windowProc; +// if (oldProc == newProc) return; +// OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc); +//} + +/** + * Forces all outstanding paint requests for the widget + * to be processed before this method returns. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #redraw(int, int, int, int, boolean) + * @see PaintListener + * @see SWT#Paint + */ +public void update () { + checkWidget (); + Utils.paintComponentImmediately(handle); +// update (false); +} + +//void update (boolean all) { +//// checkWidget (); +// if (OS.IsWinCE) { +// OS.UpdateWindow (handle); +// } else { +// int flags = OS.RDW_UPDATENOW; +// if (all) flags |= OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (handle, null, 0, flags); +// } +//} +// +//boolean updateFont (Font oldFont, Font newFont) { +// boolean sameFont = getFont ().equals (oldFont); +// /* +// * If the font that the control is using is the +// * same one that was being used from the Control +// * Panel, then use the new Control Panel font. +// */ +// if (sameFont) setFont (newFont); +// return sameFont; +//} + +void updateBackgroundMode() { + switch(parent.getBackgroundMode()) { + case SWT.INHERIT_NONE: ((CControl)handle).setBackgroundInheritance(CControl.NO_BACKGROUND_INHERITANCE); break; + case SWT.INHERIT_DEFAULT: ((CControl)handle).setBackgroundInheritance(CControl.PREFERRED_BACKGROUND_INHERITANCE); break; + case SWT.INHERIT_FORCE: ((CControl)handle).setBackgroundInheritance(CControl.BACKGROUND_INHERITANCE); break; + } + handle.repaint(); +} + +void updateLayout (boolean resize, boolean all) { + /* Do nothing */ +} + +//CREATESTRUCT widgetCreateStruct () { +// return null; +//} +// +//int widgetExtStyle () { +// int bits = 0; +// if (!OS.IsPPC) { +// if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_CLIENTEDGE; +// } +//// if ((style & SWT.BORDER) != 0) { +//// if ((style & SWT.FLAT) == 0) bits |= OS.WS_EX_CLIENTEDGE; +//// } +// /* +// * Feature in Windows NT. When CreateWindowEx() is called with +// * WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT, CreateWindowEx() +// * fails to create the HWND. The fix is to not use these bits. +// */ +// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) { +// return bits; +// } +// bits |= OS.WS_EX_NOINHERITLAYOUT; +// if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL; +// return bits; +//} +// +//int widgetParent () { +// return parent.handle; +//} +// +//int widgetStyle () { +// /* Force clipping of siblings by setting WS_CLIPSIBLINGS */ +// int bits = OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS; +//// if ((style & SWT.BORDER) != 0) { +//// if ((style & SWT.FLAT) != 0) bits |= OS.WS_BORDER; +//// } +// if (OS.IsPPC) { +// if ((style & SWT.BORDER) != 0) bits |= OS.WS_BORDER; +// } +// return bits; +// +// /* +// * This code is intentionally commented. When clipping +// * of both siblings and children is not enforced, it is +// * possible for application code to draw outside of the +// * control. +// */ +//// int bits = OS.WS_CHILD | OS.WS_VISIBLE; +//// if ((style & SWT.CLIP_SIBLINGS) != 0) bits |= OS.WS_CLIPSIBLINGS; +//// if ((style & SWT.CLIP_CHILDREN) != 0) bits |= OS.WS_CLIPCHILDREN; +//// return bits; +//} + +/** + * Changes the parent of the widget to be the one provided if + * the underlying operating system supports this feature. + * Returns true if the parent is successfully changed. + * + * @param parent the new parent for the control. + * @return true if the parent is changed and false otherwise. + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean setParent (Composite parent) { + checkWidget (); + if (parent == null) error (SWT.ERROR_NULL_ARGUMENT); + if (parent.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); + if (this.parent == parent) return true; + if (!isReparentable ()) return false; + releaseParent (); + Shell newShell = parent.getShell (), oldShell = getShell (); + Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell (); + if (oldShell != newShell || oldDecorations != newDecorations) { + Menu [] menus = oldShell.findMenus (this); + fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus); + } + ((CControl)parent.handle).getClientArea().add(handle); + updateBackgroundMode(); +// int topHandle = topHandle (); +// if (OS.SetParent (topHandle, parent.handle) == 0) return false; +// this.parent = parent; +// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; +// SetWindowPos (topHandle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags); + return true; +} + +//abstract TCHAR windowClass (); +// +//abstract int windowProc (); +// +//int windowProc (int hwnd, int msg, int wParam, int lParam) { +// LRESULT result = null; +// switch (msg) { +// case OS.WM_ACTIVATE: result = WM_ACTIVATE (wParam, lParam); break; +// case OS.WM_CAPTURECHANGED: result = WM_CAPTURECHANGED (wParam, lParam); break; +// case OS.WM_CHAR: result = WM_CHAR (wParam, lParam); break; +// case OS.WM_CLEAR: result = WM_CLEAR (wParam, lParam); break; +// case OS.WM_CLOSE: result = WM_CLOSE (wParam, lParam); break; +// case OS.WM_COMMAND: result = WM_COMMAND (wParam, lParam); break; +// case OS.WM_CONTEXTMENU: result = WM_CONTEXTMENU (wParam, lParam); break; +// case OS.WM_CTLCOLORBTN: +// case OS.WM_CTLCOLORDLG: +// case OS.WM_CTLCOLOREDIT: +// case OS.WM_CTLCOLORLISTBOX: +// case OS.WM_CTLCOLORMSGBOX: +// case OS.WM_CTLCOLORSCROLLBAR: +// case OS.WM_CTLCOLORSTATIC: result = WM_CTLCOLOR (wParam, lParam); break; +// case OS.WM_CUT: result = WM_CUT (wParam, lParam); break; +// case OS.WM_DESTROY: result = WM_DESTROY (wParam, lParam); break; +// case OS.WM_DRAWITEM: result = WM_DRAWITEM (wParam, lParam); break; +// case OS.WM_ENDSESSION: result = WM_ENDSESSION (wParam, lParam); break; +// case OS.WM_ENTERIDLE: result = WM_ENTERIDLE (wParam, lParam); break; +// case OS.WM_ERASEBKGND: result = WM_ERASEBKGND (wParam, lParam); break; +// case OS.WM_GETDLGCODE: result = WM_GETDLGCODE (wParam, lParam); break; +// case OS.WM_GETFONT: result = WM_GETFONT (wParam, lParam); break; +// case OS.WM_GETOBJECT: result = WM_GETOBJECT (wParam, lParam); break; +// case OS.WM_GETMINMAXINFO: result = WM_GETMINMAXINFO (wParam, lParam); break; +// case OS.WM_HELP: result = WM_HELP (wParam, lParam); break; +// case OS.WM_HSCROLL: result = WM_HSCROLL (wParam, lParam); break; +// case OS.WM_IME_CHAR: result = WM_IME_CHAR (wParam, lParam); break; +// case OS.WM_IME_COMPOSITION: result = WM_IME_COMPOSITION (wParam, lParam); break; +// case OS.WM_INITMENUPOPUP: result = WM_INITMENUPOPUP (wParam, lParam); break; +// case OS.WM_INPUTLANGCHANGE: result = WM_INPUTLANGCHANGE (wParam, lParam); break; +// case OS.WM_HOTKEY: result = WM_HOTKEY (wParam, lParam); break; +// case OS.WM_KEYDOWN: result = WM_KEYDOWN (wParam, lParam); break; +// case OS.WM_KEYUP: result = WM_KEYUP (wParam, lParam); break; +// case OS.WM_KILLFOCUS: result = WM_KILLFOCUS (wParam, lParam); break; +// case OS.WM_LBUTTONDBLCLK: result = WM_LBUTTONDBLCLK (wParam, lParam); break; +// case OS.WM_LBUTTONDOWN: result = WM_LBUTTONDOWN (wParam, lParam); break; +// case OS.WM_LBUTTONUP: result = WM_LBUTTONUP (wParam, lParam); break; +// case OS.WM_MBUTTONDBLCLK: result = WM_MBUTTONDBLCLK (wParam, lParam); break; +// case OS.WM_MBUTTONDOWN: result = WM_MBUTTONDOWN (wParam, lParam); break; +// case OS.WM_MBUTTONUP: result = WM_MBUTTONUP (wParam, lParam); break; +// case OS.WM_MEASUREITEM: result = WM_MEASUREITEM (wParam, lParam); break; +// case OS.WM_MENUCHAR: result = WM_MENUCHAR (wParam, lParam); break; +// case OS.WM_MENUSELECT: result = WM_MENUSELECT (wParam, lParam); break; +// case OS.WM_MOUSEACTIVATE: result = WM_MOUSEACTIVATE (wParam, lParam); break; +// case OS.WM_MOUSEHOVER: result = WM_MOUSEHOVER (wParam, lParam); break; +// case OS.WM_MOUSELEAVE: result = WM_MOUSELEAVE (wParam, lParam); break; +// case OS.WM_MOUSEMOVE: result = WM_MOUSEMOVE (wParam, lParam); break; +// case OS.WM_MOUSEWHEEL: result = WM_MOUSEWHEEL (wParam, lParam); break; +// case OS.WM_MOVE: result = WM_MOVE (wParam, lParam); break; +// case OS.WM_NCACTIVATE: result = WM_NCACTIVATE (wParam, lParam); break; +// case OS.WM_NCCALCSIZE: result = WM_NCCALCSIZE (wParam, lParam); break; +// case OS.WM_NCHITTEST: result = WM_NCHITTEST (wParam, lParam); break; +// case OS.WM_NCLBUTTONDOWN: result = WM_NCLBUTTONDOWN (wParam, lParam); break; +// case OS.WM_NOTIFY: result = WM_NOTIFY (wParam, lParam); break; +// case OS.WM_PAINT: result = WM_PAINT (wParam, lParam); break; +// case OS.WM_PALETTECHANGED: result = WM_PALETTECHANGED (wParam, lParam); break; +// case OS.WM_PARENTNOTIFY: result = WM_PARENTNOTIFY (wParam, lParam); break; +// case OS.WM_PASTE: result = WM_PASTE (wParam, lParam); break; +// case OS.WM_PRINTCLIENT: result = WM_PRINTCLIENT (wParam, lParam); break; +// case OS.WM_QUERYENDSESSION: result = WM_QUERYENDSESSION (wParam, lParam); break; +// case OS.WM_QUERYNEWPALETTE: result = WM_QUERYNEWPALETTE (wParam, lParam); break; +// case OS.WM_QUERYOPEN: result = WM_QUERYOPEN (wParam, lParam); break; +// case OS.WM_RBUTTONDBLCLK: result = WM_RBUTTONDBLCLK (wParam, lParam); break; +// case OS.WM_RBUTTONDOWN: result = WM_RBUTTONDOWN (wParam, lParam); break; +// case OS.WM_RBUTTONUP: result = WM_RBUTTONUP (wParam, lParam); break; +// case OS.WM_SETCURSOR: result = WM_SETCURSOR (wParam, lParam); break; +// case OS.WM_SETFOCUS: result = WM_SETFOCUS (wParam, lParam); break; +// case OS.WM_SETFONT: result = WM_SETFONT (wParam, lParam); break; +// case OS.WM_SETTINGCHANGE: result = WM_SETTINGCHANGE (wParam, lParam); break; +// case OS.WM_SETREDRAW: result = WM_SETREDRAW (wParam, lParam); break; +// case OS.WM_SHOWWINDOW: result = WM_SHOWWINDOW (wParam, lParam); break; +// case OS.WM_SIZE: result = WM_SIZE (wParam, lParam); break; +// case OS.WM_SYSCHAR: result = WM_SYSCHAR (wParam, lParam); break; +// case OS.WM_SYSCOLORCHANGE: result = WM_SYSCOLORCHANGE (wParam, lParam); break; +// case OS.WM_SYSCOMMAND: result = WM_SYSCOMMAND (wParam, lParam); break; +// case OS.WM_SYSKEYDOWN: result = WM_SYSKEYDOWN (wParam, lParam); break; +// case OS.WM_SYSKEYUP: result = WM_SYSKEYUP (wParam, lParam); break; +// case OS.WM_TIMER: result = WM_TIMER (wParam, lParam); break; +// case OS.WM_UNDO: result = WM_UNDO (wParam, lParam); break; +// case OS.WM_VSCROLL: result = WM_VSCROLL (wParam, lParam); break; +// case OS.WM_WINDOWPOSCHANGED: result = WM_WINDOWPOSCHANGED (wParam, lParam); break; +// case OS.WM_WINDOWPOSCHANGING: result = WM_WINDOWPOSCHANGING (wParam, lParam); break; +// case OS.WM_XBUTTONDBLCLK: result = WM_XBUTTONDBLCLK (wParam, lParam); break; +// case OS.WM_XBUTTONDOWN: result = WM_XBUTTONDOWN (wParam, lParam); break; +// case OS.WM_XBUTTONUP: result = WM_XBUTTONUP (wParam, lParam); break; +// } +// if (result != null) return result.value; +// return callWindowProc (hwnd, msg, wParam, lParam); +//} +// +//LRESULT WM_ACTIVATE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_CAPTURECHANGED (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_CHAR (int wParam, int lParam) { +// return wmChar (handle, wParam, lParam); +//} +// +//LRESULT WM_CLEAR (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_CLOSE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_COMMAND (int wParam, int lParam) { +// /* +// * When the WM_COMMAND message is sent from a +// * menu, the HWND parameter in LPARAM is zero. +// */ +// if (lParam == 0) { +// Decorations shell = menuShell (); +// if (shell.isEnabled ()) { +// int id = wParam & 0xFFFF; +// MenuItem item = display.getMenuItem (id); +// if (item != null && item.isEnabled ()) { +// return item.wmCommandChild (wParam, lParam); +// } +// } +// return null; +// } +// Control control = display.getControl (lParam); +// if (control == null) return null; +// return control.wmCommandChild (wParam, lParam); +//} +// +//LRESULT WM_CONTEXTMENU (int wParam, int lParam) { +// return wmContextMenu (handle, wParam, lParam); +//} +// +//LRESULT WM_CTLCOLOR (int wParam, int lParam) { +// int hPalette = display.hPalette; +// if (hPalette != 0) { +// OS.SelectPalette (wParam, hPalette, false); +// OS.RealizePalette (wParam); +// } +// Control control = display.getControl (lParam); +// if (control == null) return null; +// return control.wmColorChild (wParam, lParam); +//} +// +//LRESULT WM_CUT (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_DESTROY (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_DRAWITEM (int wParam, int lParam) { +// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof); +// if (struct.CtlType == OS.ODT_MENU) { +// MenuItem item = display.getMenuItem (struct.itemID); +// if (item == null) return null; +// return item.wmDrawChild (wParam, lParam); +// } +// Control control = display.getControl (struct.hwndItem); +// if (control == null) return null; +// return control.wmDrawChild (wParam, lParam); +//} +// +//LRESULT WM_ENDSESSION (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_ENTERIDLE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_GETDLGCODE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_GETFONT (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_GETOBJECT (int wParam, int lParam) { +// if (accessible != null) { +// int result = accessible.internal_WM_GETOBJECT (wParam, lParam); +// if (result != 0) return new LRESULT (result); +// } +// return null; +//} +// +//LRESULT WM_GETMINMAXINFO (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_HOTKEY (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_HELP (int wParam, int lParam) { +// if (OS.IsWinCE) return null; +// HELPINFO lphi = new HELPINFO (); +// OS.MoveMemory (lphi, lParam, HELPINFO.sizeof); +// Decorations shell = menuShell (); +// if (!shell.isEnabled ()) return null; +// if (lphi.iContextType == OS.HELPINFO_MENUITEM) { +// MenuItem item = display.getMenuItem (lphi.iCtrlId); +// if (item != null && item.isEnabled ()) { +// Widget widget = null; +// if (item.hooks (SWT.Help)) { +// widget = item; +// } else { +// Menu menu = item.parent; +// if (menu.hooks (SWT.Help)) widget = menu; +// } +// if (widget != null) { +// int hwndShell = shell.handle; +// OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0); +// widget.postEvent (SWT.Help); +// return LRESULT.ONE; +// } +// } +// return null; +// } +// if (hooks (SWT.Help)) { +// postEvent (SWT.Help); +// return LRESULT.ONE; +// } +// return null; +//} +// +//LRESULT WM_HSCROLL (int wParam, int lParam) { +// if (lParam == 0) return null; +// Control control = display.getControl (lParam); +// if (control == null) return null; +// return control.wmScrollChild (wParam, lParam); +//} +// +//LRESULT WM_IME_CHAR (int wParam, int lParam) { +// return wmIMEChar (handle, wParam, lParam); +//} +// +//LRESULT WM_IME_COMPOSITION (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_INITMENUPOPUP (int wParam, int lParam) { +// +// /* Ignore WM_INITMENUPOPUP for an accelerator */ +// if (display.accelKeyHit) return null; +// +// /* +// * If the high order word of LPARAM is non-zero, +// * the menu is the system menu and we can ignore +// * WPARAM. Otherwise, use WPARAM to find the menu. +// */ +// Shell shell = getShell (); +// Menu oldMenu = shell.activeMenu, newMenu = null; +// if ((lParam >> 16) == 0) { +// newMenu = menuShell ().findMenu (wParam); +// } +// Menu menu = newMenu; +// while (menu != null && menu != oldMenu) { +// menu = menu.getParentMenu (); +// } +// if (menu == null) { +// menu = shell.activeMenu; +// while (menu != null) { +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the hide +// * event. If this happens, stop searching up the +// * ancestor list because there is no longer a link +// * to follow. +// */ +// menu.sendEvent (SWT.Hide); +// if (menu.isDisposed ()) break; +// menu = menu.getParentMenu (); +// Menu ancestor = newMenu; +// while (ancestor != null && ancestor != menu) { +// ancestor = ancestor.getParentMenu (); +// } +// if (ancestor != null) break; +// } +// } +// +// /* +// * The shell and the new menu may be disposed because of +// * sending the hide event to the ancestor menus but setting +// * a field to null in a disposed shell is not harmful. +// */ +// if (newMenu != null && newMenu.isDisposed ()) newMenu = null; +// shell.activeMenu = newMenu; +// +// /* Send the show event */ +// if (newMenu != null && newMenu != oldMenu) { +// newMenu.sendEvent (SWT.Show); +// // widget could be disposed at this point +// } +// return null; +//} +// +//LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_KEYDOWN (int wParam, int lParam) { +// return wmKeyDown (handle, wParam, lParam); +//} +// +//LRESULT WM_KEYUP (int wParam, int lParam) { +// return wmKeyUp (handle, wParam, lParam); +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// return wmKillFocus (handle, wParam, lParam); +//} +// +//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { +// return wmLButtonDblClk (handle, wParam, lParam); +//} +// +//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +// return wmLButtonDown (handle, wParam, lParam); +//} +// +//LRESULT WM_LBUTTONUP (int wParam, int lParam) { +// return wmLButtonUp (handle, wParam, lParam); +//} +// +//LRESULT WM_MBUTTONDBLCLK (int wParam, int lParam) { +// return wmMButtonDblClk (handle, wParam, lParam); +//} +// +//LRESULT WM_MBUTTONDOWN (int wParam, int lParam) { +// return wmMButtonDown (handle, wParam, lParam); +//} +// +//LRESULT WM_MBUTTONUP (int wParam, int lParam) { +// return wmMButtonUp (handle, wParam, lParam); +//} +// +//LRESULT WM_MEASUREITEM (int wParam, int lParam) { +// MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof); +// if (struct.CtlType == OS.ODT_MENU) { +// MenuItem item = display.getMenuItem (struct.itemID); +// if (item == null) return null; +// return item.wmMeasureChild (wParam, lParam); +// } +// int hwnd = OS.GetDlgItem (handle, struct.CtlID); +// Control control = display.getControl (hwnd); +// if (control == null) return null; +// return control.wmMeasureChild (wParam, lParam); +//} +// +//LRESULT WM_MENUCHAR (int wParam, int lParam) { +// /* +// * Feature in Windows. When the user types Alt+ +// * and does not match a mnemonic in the System +// * menu or the menu bar, Windows beeps. This beep is +// * unexpected and unwanted by applications that look +// * for Alt+. The fix is to detect the case and +// * stop Windows from beeping by closing the menu. +// */ +// int type = wParam >> 16; +// if (type == 0 || type == OS.MF_SYSMENU) { +// display.mnemonicKeyHit = false; +// return new LRESULT (OS.MNC_CLOSE << 16); +// } +// return null; +//} +// +//LRESULT WM_MENUSELECT (int wParam, int lParam) { +// int code = wParam >> 16; +// Shell shell = getShell (); +// if (code == -1 && lParam == 0) { +// Menu menu = shell.activeMenu; +// while (menu != null) { +// /* +// * When the user cancels any menu that is not the +// * menu bar, assume a mnemonic key was pressed to open +// * the menu from WM_SYSCHAR. When the menu was invoked +// * using the mouse, this assumption is wrong but not +// * harmful. This variable is only used in WM_SYSCHAR +// * and WM_SYSCHAR is only sent after the user has pressed +// * a mnemonic. +// */ +// display.mnemonicKeyHit = true; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the hide +// * event. If this happens, stop searching up the +// * parent list because there is no longer a link +// * to follow. +// */ +// menu.sendEvent (SWT.Hide); +// if (menu.isDisposed ()) break; +// menu = menu.getParentMenu (); +// } +// /* +// * The shell may be disposed because of sending the hide +// * event to the last active menu menu but setting a field +// * to null in a destroyed widget is not harmful. +// */ +// shell.activeMenu = null; +// return null; +// } +// if ((code & OS.MF_SYSMENU) != 0) return null; +// if ((code & OS.MF_HILITE) != 0) { +// MenuItem item = null; +// Decorations menuShell = menuShell (); +// if ((code & OS.MF_POPUP) != 0) { +// int index = wParam & 0xFFFF; +// MENUITEMINFO info = new MENUITEMINFO (); +// info.cbSize = MENUITEMINFO.sizeof; +// info.fMask = OS.MIIM_SUBMENU; +// if (OS.GetMenuItemInfo (lParam, index, true, info)) { +// Menu newMenu = menuShell.findMenu (info.hSubMenu); +// if (newMenu != null) item = newMenu.cascade; +// } +// } else { +// Menu newMenu = menuShell.findMenu (lParam); +// if (newMenu != null) { +// int id = wParam & 0xFFFF; +// item = display.getMenuItem (id); +// } +// Menu oldMenu = shell.activeMenu; +// if (oldMenu != null) { +// Menu ancestor = oldMenu; +// while (ancestor != null && ancestor != newMenu) { +// ancestor = ancestor.getParentMenu (); +// } +// if (ancestor == newMenu) { +// ancestor = oldMenu; +// while (ancestor != newMenu) { +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the hide +// * event or the item about to be armed. If this +// * happens, stop searching up the ancestor list +// * because there is no longer a link to follow. +// */ +// ancestor.sendEvent (SWT.Hide); +// if (ancestor.isDisposed ()) break; +// ancestor = ancestor.getParentMenu (); +// } +// /* +// * The shell and/or the item could be disposed when +// * processing hide events from above. If this happens, +// * ensure that the shell is not accessed and that no +// * arm event is sent to the item. +// */ +// if (!shell.isDisposed ()) { +// if (newMenu != null && newMenu.isDisposed ()) { +// newMenu = null; +// } +// shell.activeMenu = newMenu; +// } +// if (item != null && item.isDisposed ()) item = null; +// } +// } +// } +// if (item != null) item.sendEvent (SWT.Arm); +// } +// return null; +//} +// +//LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_MOUSEHOVER (int wParam, int lParam) { +// return wmMouseHover (handle, wParam, lParam); +//} +// +//LRESULT WM_MOUSELEAVE (int wParam, int lParam) { +// return wmMouseLeave (handle, wParam, lParam); +//} +// +//LRESULT WM_MOUSEMOVE (int wParam, int lParam) { +// return wmMouseMove (handle, wParam, lParam); +//} +// +//LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { +// return wmMouseWheel (handle, wParam, lParam); +//} +// +//LRESULT WM_MOVE (int wParam, int lParam) { +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// if (OS.IsWindowVisible (handle)) { +// if (findThemeControl () != null) { +// int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (handle, null, 0, flags); +// } +// } +// } +// sendEvent (SWT.Move); +// // widget could be disposed at this point +// return null; +//} +// +//LRESULT WM_NCACTIVATE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_NCCALCSIZE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_NCHITTEST (int wParam, int lParam) { +// if (!OS.IsWindowEnabled (handle)) return null; +// if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT); +// return null; +//} +// +//LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_NOTIFY (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// int hwnd = hdr.hwndFrom; +// if (hwnd == 0) return null; +// Control control = display.getControl (hwnd); +// if (control == null) return null; +// return control.wmNotifyChild (wParam, lParam); +//} +// +//LRESULT WM_PAINT (int wParam, int lParam) { +// return super.wmPaint (handle, wParam, lParam); +//} +// +//LRESULT WM_PALETTECHANGED (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_PARENTNOTIFY (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_PASTE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_PRINTCLIENT (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_QUERYENDSESSION (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_QUERYOPEN (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_RBUTTONDBLCLK (int wParam, int lParam) { +// return wmRButtonDblClk (handle, wParam, lParam); +//} +// +//LRESULT WM_RBUTTONDOWN (int wParam, int lParam) { +// return wmRButtonDown (handle, wParam, lParam); +//} +// +//LRESULT WM_RBUTTONUP (int wParam, int lParam) { +// return wmRButtonUp (handle, wParam, lParam); +//} +// +//LRESULT WM_SETCURSOR (int wParam, int lParam) { +// int hitTest = (short) (lParam & 0xFFFF); +// if (hitTest == OS.HTCLIENT) { +// Control control = display.getControl (wParam); +// if (control == null) return null; +// Cursor cursor = control.findCursor (); +// if (cursor != null) { +// OS.SetCursor (cursor.handle); +// return LRESULT.ONE; +// } +// } +// return null; +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// return wmSetFocus (handle, wParam, lParam); +//} +// +//LRESULT WM_SETTINGCHANGE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SETFONT (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SETREDRAW (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SHOWWINDOW (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// sendEvent (SWT.Resize); +// // widget could be disposed at this point +// return null; +//} +// +//LRESULT WM_SYSCHAR (int wParam, int lParam) { +// return wmSysChar (handle, wParam, lParam); +//} +// +//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SYSCOMMAND (int wParam, int lParam) { +// /* +// * Check to see if the command is a system command or +// * a user menu item that was added to the System menu. +// * When a user item is added to the System menu, +// * WM_SYSCOMMAND must always return zero. +// */ +// if ((wParam & 0xF000) == 0) { +// Decorations shell = menuShell (); +// if (shell.isEnabled ()) { +// MenuItem item = display.getMenuItem (wParam & 0xFFFF); +// if (item != null) item.wmCommandChild (wParam, lParam); +// } +// return LRESULT.ZERO; +// } +// +// /* Process the System Command */ +// int cmd = wParam & 0xFFF0; +// switch (cmd) { +// case OS.SC_CLOSE: +// int hwndShell = menuShell ().handle; +// int bits = OS.GetWindowLong (hwndShell, OS.GWL_STYLE); +// if ((bits & OS.WS_SYSMENU) == 0) return LRESULT.ZERO; +// break; +// case OS.SC_KEYMENU: +// /* +// * When lParam is zero, one of F10, Shift+F10, Ctrl+F10 or +// * Ctrl+Shift+F10 was pressed. If there is no menu bar and +// * the focus control is interested in keystrokes, give the +// * key to the focus control. Normally, F10 with no menu bar +// * moves focus to the System menu but this can be achieved +// * using Alt+Space. To allow the application to see F10, +// * avoid running the default window proc. +// * +// * NOTE: When F10 is pressed, WM_SYSCOMMAND is sent to the +// * shell, not the focus control. This is undocumented Windows +// * behavior. +// */ +// if (lParam == 0) { +// Decorations shell = menuShell (); +// Menu menu = shell.getMenuBar (); +// if (menu == null) { +// Control control = display._getFocusControl (); +// if (control != null) { +// if (control.hooks (SWT.KeyDown) || control.hooks (SWT.KeyUp)) { +// display.mnemonicKeyHit = false; +// return LRESULT.ZERO; +// } +// } +// } +// } else { +// /* +// * When lParam is not zero, Alt+ was pressed. If the +// * application is interested in keystrokes and there is a +// * menu bar, check to see whether the key that was pressed +// * matches a mnemonic on the menu bar. Normally, Windows +// * matches the first character of a menu item as well as +// * matching the mnemonic character. To allow the application +// * to see the keystrokes in this case, avoid running the default +// * window proc. +// * +// * NOTE: When the user types Alt+Space, the System menu is +// * activated. In this case the application should not see +// * the keystroke. +// */ +// if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) { +// if (lParam != ' ') { +// Decorations shell = menuShell (); +// Menu menu = shell.getMenuBar (); +// if (menu != null) { +// char key = Display.mbcsToWcs (lParam); +// if (key != 0) { +// key = Character.toUpperCase (key); +// MenuItem [] items = menu.getItems (); +// for (int i=0; i 0 && mnemonic == 0) { +// char ch = text.charAt (0); +// if (Character.toUpperCase (ch) == key) { +// display.mnemonicKeyHit = false; +// return LRESULT.ZERO; +// } +// } +// } +// } +// } else { +// display.mnemonicKeyHit = false; +// } +// } +// } +// } +// // FALL THROUGH +// case OS.SC_HSCROLL: +// case OS.SC_VSCROLL: +// /* +// * Do not allow keyboard traversal of the menu bar +// * or scrolling when the shell is not enabled. +// */ +// Decorations shell = menuShell (); +// if (!shell.isEnabled () || !shell.isActive ()) { +// return LRESULT.ZERO; +// } +// break; +// case OS.SC_MINIMIZE: +// /* Save the focus widget when the shell is minimized */ +// menuShell ().saveFocus (); +// break; +// } +// return null; +//} +// +//LRESULT WM_SYSKEYDOWN (int wParam, int lParam) { +// return wmSysKeyDown (handle, wParam, lParam); +//} +// +//LRESULT WM_SYSKEYUP (int wParam, int lParam) { +// return wmSysKeyUp (handle, wParam, lParam); +//} +// +//LRESULT WM_TIMER (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_UNDO (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_VSCROLL (int wParam, int lParam) { +// if (lParam == 0) return null; +// Control control = display.getControl (lParam); +// if (control == null) return null; +// return control.wmScrollChild (wParam, lParam); +//} +// +//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_XBUTTONDBLCLK (int wParam, int lParam) { +// return wmXButtonDblClk (handle, wParam, lParam); +//} +// +//LRESULT WM_XBUTTONDOWN (int wParam, int lParam) { +// return wmXButtonDown (handle, wParam, lParam); +//} +// +//LRESULT WM_XBUTTONUP (int wParam, int lParam) { +// return wmXButtonUp (handle, wParam, lParam); +//} +// +//LRESULT wmColorChild (int wParam, int lParam) { +// if (background == -1 && foreground == -1) return null; +// int forePixel = foreground, backPixel = background; +// if (forePixel == -1) forePixel = defaultForeground (); +// if (backPixel == -1) backPixel = defaultBackground (); +// OS.SetTextColor (wParam, forePixel); +// OS.SetBkColor (wParam, backPixel); +// return new LRESULT (findBrush (backPixel)); +//} +// +//LRESULT wmCommandChild (int wParam, int lParam) { +// return null; +//} +// +//LRESULT wmDrawChild (int wParam, int lParam) { +// return null; +//} +// +//LRESULT wmMeasureChild (int wParam, int lParam) { +// return null; +//} +// +//LRESULT wmNotifyChild (int wParam, int lParam) { +// return null; +//} +// +//LRESULT wmScrollChild (int wParam, int lParam) { +// return null; +//} + +private volatile long mouseHoverTimeStamp; +private volatile Thread mouseHoverThread; +private java.awt.event.MouseEvent mouseHoverEvent; + +void adjustMouseHoverState(java.awt.event.MouseEvent me) { + mouseHoverTimeStamp = System.currentTimeMillis() + 500; + mouseHoverEvent = me; + if(mouseHoverThread == null) { + mouseHoverThread = new Thread("Mouse Hover Thread") { + public void run() { + while(mouseHoverThread == this) { + try { + sleep(Math.max(50, mouseHoverTimeStamp - System.currentTimeMillis())); + } catch(Exception e) {} + if(mouseHoverThread != this) { + return; + } + if(mouseHoverTimeStamp - System.currentTimeMillis() < 0) { + final Thread t = this; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if(mouseHoverThread != t) { + return; + } + if(mouseHoverTimeStamp - System.currentTimeMillis() < 0) { + mouseHoverThread = null; + java.awt.event.MouseEvent me = mouseHoverEvent; + mouseHoverEvent = null; + // TODO: the point is incorrect when the wheel mouse is used: cf snippet125 + if(!isDisposed() && me.getComponent().contains(me.getPoint())) { + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + sendMouseEvent(SWT.MouseHover, createMouseEvent(me, false)); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + } + } + }); + } + } + } + }; + mouseHoverThread.setDaemon(true); + mouseHoverThread.start(); + } +} + +/** + * The entry point for callbacks + * (Warning: This method is platform dependent) + *

    + * IMPORTANT: This method is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ +public void processEvent(EventObject e) { +} + +boolean isTraversing; +int lastPressedKeyCode; +char lastPressedKeyChar; +//int lastKeyCode; +static Runnable focusLostRunnable; + +boolean isAdjustingSize; +static boolean isDragging; + +/** + * The entry point for callbacks + * (Warning: This method is platform dependent) + *

    + * IMPORTANT: This method is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case java.awt.event.MouseEvent.MOUSE_CLICKED: { + java.awt.event.MouseEvent me = (java.awt.event.MouseEvent)e; + if(me.getClickCount() != 2) { + return; + } + if(Utils.capturedControl == null && !hooks(SWT.MouseDoubleClick)) return; + break; + } + case java.awt.event.PaintEvent.PAINT: if(!hooks(SWT.Paint)) return; break; + case java.awt.event.MouseEvent.MOUSE_DRAGGED: if(Utils.capturedControl == null && !hooks(SWT.DragDetect) && !hooks(SWT.MouseMove) && !hooks(SWT.MouseHover)) return; break; + case java.awt.event.MouseEvent.MOUSE_MOVED: if(Utils.capturedControl == null && !hooks(SWT.MouseMove) && !hooks(SWT.MouseHover)) return; break; + case java.awt.event.MouseEvent.MOUSE_PRESSED: { + if(Utils.capturedControl == null && !hooks(SWT.MouseDown) && menu == null && (!hooks(SWT.MenuDetect) || !((java.awt.event.MouseEvent)e).isPopupTrigger())) return; + break; + } + case java.awt.event.MouseEvent.MOUSE_RELEASED: { + isDragging = false; + if(Utils.capturedControl == null && !hooks(SWT.MouseUp) && menu == null && (!hooks(SWT.MenuDetect) || !((java.awt.event.MouseEvent)e).isPopupTrigger())) return; + break; + } + case java.awt.event.MouseEvent.MOUSE_WHEEL: { + if(Utils.capturedControl == null && !hooks(SWT.MouseWheel)) { + Object o = e.getSource(); + if(o instanceof Component && !(o instanceof Window)) { + Component c = ((Component)o); + Container cParent = c.getParent(); + if(cParent != null) { + MouseWheelEvent mwe = (MouseWheelEvent)e; + cParent.dispatchEvent(new MouseWheelEvent(cParent, mwe.getID(), mwe.getWhen(), mwe.getModifiers(), mwe.getX() + cParent.getX(), mwe.getY() + cParent.getY(), mwe.getClickCount(), mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation())); + mwe.consume(); + } + } + adjustMouseHoverState((java.awt.event.MouseEvent)e); + return; + } + break; + } + case java.awt.event.MouseEvent.MOUSE_ENTERED: if(!hooks(SWT.MouseEnter)) return; break; + case java.awt.event.MouseEvent.MOUSE_EXITED: if(!hooks(SWT.MouseExit)) {mouseHoverThread = null; return;} break; + case java.awt.event.KeyEvent.KEY_PRESSED: { +// if(!hooks(SWT.KeyDown) && !hooks(SWT.Traverse) && !isTraversalKey((java.awt.event.KeyEvent)e)) { +// return; +// } + break; + } + case java.awt.event.KeyEvent.KEY_RELEASED: if(!hooks(SWT.KeyUp)) {lastPressedKeyCode = -1; lastPressedKeyChar = '\0'; return;} break; + case java.awt.event.KeyEvent.KEY_TYPED: if(!hooks(SWT.KeyDown)) {isTraversing = false; return;} break; + case ComponentEvent.COMPONENT_RESIZED: if(!hooks(SWT.Resize)) return; break; + case ComponentEvent.COMPONENT_MOVED: if(!hooks(SWT.Move)) return; break; + case ComponentEvent.COMPONENT_SHOWN: if(!hooks(SWT.Show)) return; break; + case ComponentEvent.COMPONENT_HIDDEN: if(!hooks(SWT.Hide)) return; break; + case java.awt.event.FocusEvent.FOCUS_GAINED: /*if(!hooks(SWT.FocusIn)) return;*/ break; + case java.awt.event.FocusEvent.FOCUS_LOST: /*if(!hooks(SWT.FocusOut)) return;*/ break; + default: return; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + switch(id) { + case java.awt.event.PaintEvent.PAINT: { + Event event = new Event(); + event.gc = new GC(this); + Rectangle r = this.getBounds (); + event.width = r.width; + event.height = r.height; + sendEvent(SWT.Paint, event); + if (this instanceof Canvas) { + Canvas canvas = (Canvas) this; + if (canvas.caret != null) { + canvas.caret.paintCaret (event.gc); + } + } + break; + } + case java.awt.event.MouseEvent.MOUSE_DRAGGED: { + if(!isDragging) { + isDragging = true; + java.awt.event.MouseEvent me = (java.awt.event.MouseEvent)e; + sendEvent(SWT.DragDetect, createMouseEvent(me, false)); + } + // Fall through + } + case java.awt.event.MouseEvent.MOUSE_MOVED: { + java.awt.event.MouseEvent me = (java.awt.event.MouseEvent)e; + sendMouseEvent(SWT.MouseMove, createMouseEvent(me, false)); + adjustMouseHoverState(me); + break; + } + case java.awt.event.MouseEvent.MOUSE_PRESSED: { + java.awt.event.MouseEvent me = (java.awt.event.MouseEvent)e; + Event event = createMouseEvent(me, true); + sendMouseEvent(SWT.MouseDown, event); + if((menu != null || hooks(SWT.MenuDetect)) && me.isPopupTrigger()) { + java.awt.Point p = new java.awt.Point(event.x, event.y); + SwingUtilities.convertPointToScreen(p, me.getComponent()); + event.x = p.x; + event.y = p.y; + sendEvent(SWT.MenuDetect, event); + showPopup(me); + } + break; + } + case java.awt.event.MouseEvent.MOUSE_RELEASED: { + java.awt.event.MouseEvent me = (java.awt.event.MouseEvent)e; + Event event = createMouseEvent(me, true); + sendMouseEvent(SWT.MouseUp, event); + if((menu != null || hooks(SWT.MenuDetect)) && me.isPopupTrigger()) { + java.awt.Point p = new java.awt.Point(event.x, event.y); + SwingUtilities.convertPointToScreen(p, me.getComponent()); + event.x = p.x; + event.y = p.y; + sendEvent(SWT.MenuDetect, event); + showPopup(me); + } + break; + } + case java.awt.event.MouseEvent.MOUSE_CLICKED: sendMouseEvent(SWT.MouseDoubleClick, createMouseEvent((java.awt.event.MouseEvent)e, false)); break; + case java.awt.event.MouseEvent.MOUSE_WHEEL: { + sendMouseEvent(SWT.MouseWheel, createMouseEvent((java.awt.event.MouseEvent)e, false)); + adjustMouseHoverState((java.awt.event.MouseEvent)e); + break; + } + case java.awt.event.MouseEvent.MOUSE_ENTERED: sendEvent(SWT.MouseEnter, createMouseEvent((java.awt.event.MouseEvent)e, false)); break; + case java.awt.event.MouseEvent.MOUSE_EXITED: + mouseHoverThread = null; + sendEvent(SWT.MouseExit, createMouseEvent((java.awt.event.MouseEvent)e, false)); + break; + case java.awt.event.KeyEvent.KEY_TYPED: { +// if(!isTraversing) { +// java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent)e; +// ke.setKeyCode(lastKeyCode); +// if (ke.getWhen () > lastPressed) { +// Event event = createKeyEvent (ke); +// sendEvent (SWT.KeyDown, event); +// sendEvent (SWT.KeyUp, event); +// } +// } + java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent)e; + if((ke.getModifiers() & KeyEvent.ALT_GRAPH_MASK) != 0) { + if(hooks(SWT.KeyDown)) { + KeyEvent ke2 = new KeyEvent(ke.getComponent(), KeyEvent.KEY_RELEASED, ke.getWhen(), ke.getModifiers(), lastPressedKeyCode, ke.getKeyChar(), ke.getKeyLocation()); + Event event = createKeyEvent(ke2); + event.stateMask |= SWT.CTRL | SWT.ALT; + sendEvent(SWT.KeyDown, event); + } +// lastPressedKeyCode = ke.getKeyCode(); + lastPressedKeyChar = ke.getKeyChar(); + } + isTraversing = false; + break; + } + case java.awt.event.KeyEvent.KEY_PRESSED: { + java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent)e; + int pressedKeyCode = ke.getKeyCode(); + if(pressedKeyCode == lastPressedKeyCode) { + boolean isBlocked = false; + switch(pressedKeyCode) { + case java.awt.event.KeyEvent.VK_CONTROL: + case java.awt.event.KeyEvent.VK_SHIFT: + case java.awt.event.KeyEvent.VK_ALT: + isBlocked = true; + } + if(isBlocked) break; + } + lastPressedKeyCode = pressedKeyCode; + int AltGrMask = KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK; + if((ke.getModifiers() & AltGrMask) == AltGrMask) { + boolean isBlocked = true; + switch(pressedKeyCode) { + case java.awt.event.KeyEvent.VK_CONTROL: + case java.awt.event.KeyEvent.VK_SHIFT: + case java.awt.event.KeyEvent.VK_ALT: + isBlocked = false; + } + if(isBlocked) break; + } + lastPressedKeyChar = ke.getKeyChar(); +// lastKeyCode = lastPressedKeyCode; + if(isTraversalKey(ke)) { + isTraversing = processTraversalKey(ke); + } + if(!isTraversing) { + if(hooks(SWT.KeyDown)) { + sendEvent(SWT.KeyDown, createKeyEvent(ke)); + } +// lastPressed = ke.getWhen (); + } + break; + } + case java.awt.event.KeyEvent.KEY_RELEASED: { + java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent)e; + int AltGrMask = KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK; + boolean isSending = true; + if((ke.getModifiers() & AltGrMask) == AltGrMask) { + KeyEvent ke2 = new KeyEvent(ke.getComponent(), KeyEvent.KEY_RELEASED, ke.getWhen(), ke.getModifiers(), lastPressedKeyCode, lastPressedKeyChar, ke.getKeyLocation()); + sendEvent(SWT.KeyUp, createKeyEvent(ke2)); + isSending = false; + } + lastPressedKeyCode = -1; + lastPressedKeyChar = '\0'; + if(isSending && !isTraversing) { + sendEvent(SWT.KeyUp, createKeyEvent(ke)); + } + break; + } + case ComponentEvent.COMPONENT_RESIZED: if(!isAdjustingSize) sendEvent(SWT.Resize); break; + case ComponentEvent.COMPONENT_MOVED: sendEvent(SWT.Move); break; + case ComponentEvent.COMPONENT_SHOWN: sendEvent(SWT.Show); break; + case ComponentEvent.COMPONENT_HIDDEN: sendEvent(SWT.Hide); break; + case java.awt.event.FocusEvent.FOCUS_GAINED: { + if(focusLostRunnable != null) { + focusLostRunnable.run(); + } + Shell shell = getShell (); + if(!shell.isDisposed()) { + shell.setActiveControl(this); + } + sendEvent(SWT.FocusIn); + break; + } + case java.awt.event.FocusEvent.FOCUS_LOST: { + Runnable runnable = new Runnable() { + public void run() { + if(focusLostRunnable != this) { + return; + } + focusLostRunnable = null; + UIThreadUtils.startExclusiveSection(display); + try { + Shell shell = getShell(); + Display display = getDisplay(); + if (shell != display.getActiveShell ()) { + shell.setActiveControl (null); + } + sendEvent(SWT.FocusOut); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + }; + focusLostRunnable = runnable; + break; + } + } + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +static final Point DEFAULT_EVENT_OFFSET = new Point(0, 0); + +Point getInternalOffset() { + Component clientArea = ((CControl)handle).getClientArea(); + // Code is duplicated in GC.getGraphics() in inverse + if(clientArea != handle) { + if(clientArea.getParent() instanceof JViewport) { + JViewport viewport = (JViewport)clientArea.getParent(); + int offsetX = 0; + int offsetY = 0; + java.awt.Point viewPosition = viewport.getViewPosition(); + offsetX -= viewPosition.x; + offsetY -= viewPosition.y; + JViewport columnHeader = ((JScrollPane)viewport.getParent()).getColumnHeader(); + if(columnHeader != null && columnHeader.isVisible()) { + offsetY += columnHeader.getHeight(); + } + return new Point(offsetX, offsetY); + } + } + return DEFAULT_EVENT_OFFSET; +} + +protected boolean isTraversalKey(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_TAB: + return true; + } + return false; +} + +protected int getTraversalKeyDetail(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_TAB: + if ((ke.getModifiersEx() & java.awt.event.KeyEvent.SHIFT_DOWN_MASK) != 0) { + return SWT.TRAVERSE_TAB_PREVIOUS; + } + return SWT.TRAVERSE_TAB_NEXT; + default: + return -1; + } +} + +protected boolean getTraversalKeyDefault(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_TAB: + return true; + default: + return false; + } +} + +private boolean processTraversalKey(java.awt.event.KeyEvent ke) { + Event event = createKeyEvent(ke); + event.detail = getTraversalKeyDetail(ke); + if(event.detail < 0) { + throw new IllegalArgumentException("The traversal key does not define its action type!"); + } + event.doit = getTraversalKeyDefault(ke); + if(hooks(SWT.Traverse)) { + event.doit = false; + sendEvent(SWT.Traverse, event); + } + validateTraversalKey(ke, event); + return event.doit; +} + +protected void validateTraversalKey(java.awt.event.KeyEvent ke, Event event) { + if(!event.doit) { + return; + } + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_TAB: + ke.consume(); + if ((ke.getModifiersEx() & java.awt.event.KeyEvent.SHIFT_DOWN_MASK) != 0) { + traverse(SWT.TRAVERSE_TAB_PREVIOUS); + } else { + traverse(SWT.TRAVERSE_TAB_NEXT); + } + break; + } +} + +private void showPopup(java.awt.event.MouseEvent e) { + if(menu != null) { + java.awt.Point p = new java.awt.Point(e.getPoint()); + SwingUtilities.convertPointToScreen(p, e.getComponent()); + menu.setLocation(new Point(p.x, p.y)); + menu.setVisible(true); + } +} + +Event createMouseEvent(java.awt.event.MouseEvent me, boolean isPreviousInputState) { + if(me == null) { + return null; + } + Event event = new Event(); + Container container = handle; + java.awt.Point point = me.getPoint(); + Component component = me.getComponent(); + if(container instanceof RootPaneContainer) { + container = ((RootPaneContainer)container).getContentPane(); + point = SwingUtilities.convertPoint(component, point, container); + } else { + point = SwingUtilities.convertPoint(component, point, ((CControl)handle).getClientArea()); + } + Point offset = getInternalOffset(); + event.x = point.x + offset.x; + event.y = point.y + offset.y; + if (SwingUtilities.isLeftMouseButton (me)) { + event.button = 1; + } else if (SwingUtilities.isRightMouseButton (me)) { + event.button = 2; + } else if (SwingUtilities.isMiddleMouseButton (me)) { + event.button = 3; + } + event.stateMask = isPreviousInputState? Display.getPreviousInputState(): Display.getInputState(); + return event; +} + +Event createKeyEvent(java.awt.event.KeyEvent ke) { + if(ke == null) { + return null; + } + Event event = new Event(); + Container container = handle; + if(container instanceof RootPaneContainer) { + container = ((RootPaneContainer)container).getContentPane(); + } + int modifiersEx = ke.getModifiersEx(); + if((modifiersEx & java.awt.event.MouseEvent.BUTTON1_DOWN_MASK) != 0) { + event.button = 1; + } else if((modifiersEx & java.awt.event.MouseEvent.BUTTON2_DOWN_MASK) != 0) { + event.button = 2; + } else if((modifiersEx & java.awt.event.MouseEvent.BUTTON3_DOWN_MASK) != 0) { + event.button = 3; + } + char c = ke.getKeyChar(); + if(c == java.awt.event.KeyEvent.CHAR_UNDEFINED) { + c = 0; + } +// if((modifiersEx & java.awt.event.KeyEvent.SHIFT_DOWN_MASK) != 0 && (modifiersEx & java.awt.event.KeyEvent.CTRL_DOWN_MASK) != 0) { + int keyCode = ke.getKeyCode(); + if(keyCode >= java.awt.event.KeyEvent.VK_A && keyCode <= java.awt.event.KeyEvent.VK_Z) { + event.keyCode = (char)('a' - java.awt.event.KeyEvent.VK_A + keyCode); + } else if(keyCode >= java.awt.event.KeyEvent.VK_0 && keyCode <= java.awt.event.KeyEvent.VK_9) { + event.keyCode = (char)('0' - java.awt.event.KeyEvent.VK_0 + keyCode); + } +// } + if(ke.getKeyLocation() != java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_ALT: event.keyCode = SWT.ALT; break; + case java.awt.event.KeyEvent.VK_SHIFT: event.keyCode = SWT.SHIFT; break; + case java.awt.event.KeyEvent.VK_CONTROL: event.keyCode = SWT.CONTROL; break; + case java.awt.event.KeyEvent.VK_WINDOWS: event.keyCode = SWT.COMMAND; break; + /* Non-Numeric Keypad Keys */ + case java.awt.event.KeyEvent.VK_UP: event.keyCode = SWT.ARROW_UP; break; + case java.awt.event.KeyEvent.VK_DOWN: event.keyCode = SWT.ARROW_DOWN; break; + case java.awt.event.KeyEvent.VK_LEFT: event.keyCode = SWT.ARROW_LEFT; break; + case java.awt.event.KeyEvent.VK_RIGHT: event.keyCode = SWT.ARROW_RIGHT; break; + case java.awt.event.KeyEvent.VK_PAGE_UP: event.keyCode = SWT.PAGE_UP; break; + case java.awt.event.KeyEvent.VK_PAGE_DOWN: event.keyCode = SWT.PAGE_DOWN; break; + case java.awt.event.KeyEvent.VK_HOME: event.keyCode = SWT.HOME; break; + case java.awt.event.KeyEvent.VK_END: event.keyCode = SWT.END; break; + case java.awt.event.KeyEvent.VK_INSERT: event.keyCode = SWT.INSERT; break; + /* Virtual and Ascii Keys */ + case java.awt.event.KeyEvent.VK_BACK_SPACE: event.keyCode = SWT.BS; break; + case java.awt.event.KeyEvent.VK_ENTER: event.keyCode = SWT.CR; break; + case java.awt.event.KeyEvent.VK_DELETE: event.keyCode = SWT.DEL; break; + case java.awt.event.KeyEvent.VK_ESCAPE: event.keyCode = SWT.ESC; break; +// case java.awt.event.KeyEvent.VK_ENTER: event.keyCode = SWT.LF; break; + case java.awt.event.KeyEvent.VK_TAB: event.keyCode = SWT.TAB; break; + /* Functions Keys */ + case java.awt.event.KeyEvent.VK_F1: event.keyCode = SWT.F1; break; + case java.awt.event.KeyEvent.VK_F2: event.keyCode = SWT.F2; break; + case java.awt.event.KeyEvent.VK_F3: event.keyCode = SWT.F3; break; + case java.awt.event.KeyEvent.VK_F4: event.keyCode = SWT.F4; break; + case java.awt.event.KeyEvent.VK_F5: event.keyCode = SWT.F5; break; + case java.awt.event.KeyEvent.VK_F6: event.keyCode = SWT.F6; break; + case java.awt.event.KeyEvent.VK_F7: event.keyCode = SWT.F7; break; + case java.awt.event.KeyEvent.VK_F8: event.keyCode = SWT.F8; break; + case java.awt.event.KeyEvent.VK_F9: event.keyCode = SWT.F9; break; + case java.awt.event.KeyEvent.VK_F10: event.keyCode = SWT.F10; break; + case java.awt.event.KeyEvent.VK_F11: event.keyCode = SWT.F11; break; + case java.awt.event.KeyEvent.VK_F12: event.keyCode = SWT.F12; break; + case java.awt.event.KeyEvent.VK_F13: event.keyCode = SWT.F13; break; + case java.awt.event.KeyEvent.VK_F14: event.keyCode = SWT.F14; break; + case java.awt.event.KeyEvent.VK_F15: event.keyCode = SWT.F15; break; + /* Other keys */ + case java.awt.event.KeyEvent.VK_CAPS_LOCK: event.keyCode = SWT.CAPS_LOCK; break; + case java.awt.event.KeyEvent.VK_NUM_LOCK: event.keyCode = SWT.NUM_LOCK; break; + case java.awt.event.KeyEvent.VK_SCROLL_LOCK: event.keyCode = SWT.SCROLL_LOCK; break; + case java.awt.event.KeyEvent.VK_PAUSE: event.keyCode = SWT.PAUSE; break; + case java.awt.event.KeyEvent.VK_CANCEL: event.keyCode = SWT.BREAK; break; + case java.awt.event.KeyEvent.VK_PRINTSCREEN: event.keyCode = SWT.PRINT_SCREEN; break; + case java.awt.event.KeyEvent.VK_HELP: event.keyCode = SWT.HELP; break; + } + } else { + /* Numeric Keypad Keys */ + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_MULTIPLY: event.keyCode = SWT.KEYPAD_MULTIPLY; break; + case java.awt.event.KeyEvent.VK_ADD: event.keyCode = SWT.KEYPAD_ADD; break; + case java.awt.event.KeyEvent.VK_ENTER: event.keyCode = SWT.KEYPAD_CR; break; + case java.awt.event.KeyEvent.VK_SUBTRACT: event.keyCode = SWT.KEYPAD_SUBTRACT; break; + case java.awt.event.KeyEvent.VK_DECIMAL: event.keyCode = SWT.KEYPAD_DECIMAL; break; + case java.awt.event.KeyEvent.VK_DIVIDE: event.keyCode = SWT.KEYPAD_DIVIDE; break; + case java.awt.event.KeyEvent.VK_NUMPAD0: event.keyCode = SWT.KEYPAD_0; break; + case java.awt.event.KeyEvent.VK_NUMPAD1: event.keyCode = SWT.KEYPAD_1; break; + case java.awt.event.KeyEvent.VK_NUMPAD2: event.keyCode = SWT.KEYPAD_2; break; + case java.awt.event.KeyEvent.VK_NUMPAD3: event.keyCode = SWT.KEYPAD_3; break; + case java.awt.event.KeyEvent.VK_NUMPAD4: event.keyCode = SWT.KEYPAD_4; break; + case java.awt.event.KeyEvent.VK_NUMPAD5: event.keyCode = SWT.KEYPAD_5; break; + case java.awt.event.KeyEvent.VK_NUMPAD6: event.keyCode = SWT.KEYPAD_6; break; + case java.awt.event.KeyEvent.VK_NUMPAD7: event.keyCode = SWT.KEYPAD_7; break; + case java.awt.event.KeyEvent.VK_NUMPAD8: event.keyCode = SWT.KEYPAD_8; break; + case java.awt.event.KeyEvent.VK_NUMPAD9: event.keyCode = SWT.KEYPAD_9; break; + case java.awt.event.KeyEvent.VK_EQUALS: event.keyCode = SWT.KEYPAD_EQUAL; break; + } + } + event.character = c; + event.stateMask = Display.getInputState(); + switch(event.keyCode) { + case SWT.CONTROL: + case SWT.SHIFT: + case SWT.ALT: + if(ke.getID() == KeyEvent.KEY_PRESSED) { + event.stateMask &= ~event.keyCode; + } else { + event.stateMask |= event.keyCode; + } + break; + } + return event; +} + +} + diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolBar.java new file mode 100644 index 00000000000..d8606caa3f1 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolBar.java @@ -0,0 +1,1088 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Component; +import java.awt.Container; +import java.util.ArrayList; + +import javax.swing.JComponent; + +import org.eclipse.swt.internal.swing.CCoolBar; +import org.eclipse.swt.internal.swing.CCoolItem; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.internal.swing.JCoolBarItem; +import org.eclipse.swt.internal.swing.Utils; +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; + +/** + * Instances of this class provide an area for dynamically + * positioning the items they contain. + *

    + * The item children that may be added to instances of this class + * must be of type CoolItem. + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to add Control children to it, + * or set a layout on it. + *

    + *

    + *
    Styles:
    + *
    FLAT, HORIZONTAL, VERTICAL
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class CoolBar extends Composite { + ArrayList itemList; + ArrayList originalItemList; +// CoolItem [] originalItems; +// boolean locked; +// boolean ignoreResize; +// static final int SEPARATOR_WIDTH = 2; +// static final int MAX_WIDTH = 0x7FFF; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public CoolBar (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +static int checkStyle (int style) { + style |= SWT.NO_FOCUS; + /* + * Even though it is legal to create this widget + * with scroll bars, they serve no useful purpose + * because they do not automatically scroll the + * widget's client area. The fix is to clear + * the SWT style. + */ + return style & ~(SWT.H_SCROLL | SWT.V_SCROLL); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// int width = 0, height = 0; +// int border = getBorderWidth (); +// int newWidth = wHint == SWT.DEFAULT ? 0x3FFF : wHint + (border * 2); +// int newHeight = hHint == SWT.DEFAULT ? 0x3FFF : hHint + (border * 2); +// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0); +// if (count != 0) { +// ignoreResize = true; +// boolean redraw = false; +// if (OS.IsWindowVisible (handle)) { +// if (OS.COMCTL32_MAJOR >= 6) { +// redraw = true; +// OS.UpdateWindow (handle); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); +// } else { +// redraw = drawCount == 0; +// if (redraw) { +// OS.UpdateWindow (handle); +// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// } +// } +// } +// RECT oldRect = new RECT (); +// OS.GetWindowRect (handle, oldRect); +// int oldWidth = oldRect.right - oldRect.left; +// int oldHeight = oldRect.bottom - oldRect.top; +// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER; +// SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags); +// RECT rect = new RECT (); +// OS.SendMessage (handle, OS.RB_GETRECT, count - 1, rect); +// height = Math.max (height, rect.bottom); +// SetWindowPos (handle, 0, 0, 0, oldWidth, oldHeight, flags); +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_IDEALSIZE | OS.RBBIM_STYLE; +// int rowWidth = 0; +// int separator = (style & SWT.FLAT) == 0 ? SEPARATOR_WIDTH : 0; +// for (int i = 0; i < count; i++) { +// OS.SendMessage(handle, OS.RB_GETBANDINFO, i, rbBand); +// if ((rbBand.fStyle & OS.RBBS_BREAK) != 0) { +// width = Math.max(width, rowWidth - separator); +// rowWidth = 0; +// } +// rowWidth += rbBand.cxIdeal + getMargin (i) + separator; +// } +// width = Math.max(width, rowWidth - separator); +// if (redraw) { +// if (OS.COMCTL32_MAJOR >= 6) { +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); +// } else { +// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// } +// } +// ignoreResize = false; +// } +// if (width == 0) width = DEFAULT_WIDTH; +// if (height == 0) height = DEFAULT_HEIGHT; +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// height += border * 2; +// width += border * 2; +// return new Point (width, height); +//} + +boolean autoAddChildren() { + return false; +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CCoolBar.Factory.newInstance(this, style); +} + +//void createHandle () { +// super.createHandle (); +// state &= ~CANVAS; +// +// /* +// * Feature in Windows. When the control is created, +// * it does not use the default system font. A new HFONT +// * is created and destroyed when the control is destroyed. +// * This means that a program that queries the font from +// * this control, uses the font in another control and then +// * destroys this control will have the font unexpectedly +// * destroyed in the other control. The fix is to assign +// * the font ourselves each time the control is created. +// * The control will not destroy a font that it did not +// * create. +// */ +// int hFont = OS.GetStockObject (OS.SYSTEM_FONT); +// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0); +//} + +void createItem (CoolItem item, int index) { + int count = getItemCount(); + if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE); + itemList.add(index, item); +// if (index == 0 && count > 0) { +// getItem (0).setWrap (false); +// } + handle.add(item.handle, index); + originalItemList.add(index, item); +// /* Insert the item */ +// if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, rbBand) == 0) { +// error (SWT.ERROR_ITEM_NOT_ADDED); +// } +// +// /* Resize the next to last item to the ideal size */ +// if (fixLast) { +// resizeToPreferredWidth (lastIndex); +// } +// +// OS.HeapFree (hHeap, 0, lpText); +// items [item.id = id] = item; +// int length = originalItems.length; +// CoolItem [] newOriginals = new CoolItem [length + 1]; +// System.arraycopy (originalItems, 0, newOriginals, 0, index); +// System.arraycopy (originalItems, index, newOriginals, index + 1, length - index); +// newOriginals [index] = item; +// originalItems = newOriginals; +} + +void createWidget () { + super.createWidget (); + itemList = new ArrayList(4); + originalItemList = new ArrayList(4); +// originalItems = new CoolItem [0]; +} + +void destroyItem (CoolItem item) { + if(!itemList.remove(item)) { + return; + } + Component[] components = handle.getComponents(); + for(int i=0; i= 6) { +// MARGINS margins = new MARGINS (); +// OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, margins); +// margin += margins.cxLeftWidth + margins.cxRightWidth; +// } +// RECT rect = new RECT (); +// OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect); +// if ((style & SWT.FLAT) != 0) { +// /* +// * Bug in Windows. When the style bit RBS_BANDBORDERS is not set +// * the rectangle returned by RBS_BANDBORDERS is four pixels too small. +// * The fix is to add four pixels to the result. +// */ +// margin += rect.left + 4; +// } else { +// margin += rect.left + rect.right; +// } +// return margin; +//} + +//Control findThemeControl () { +// return null; +//} + +/** + * Returns the item that is currently displayed at the given, + * zero-relative index. Throws an exception if the index is + * out of range. + * + * @param index the visual index of the item to return + * @return the item at the given visual index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public CoolItem getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + Component component = handle.getComponent(index); + for(int i=itemList.size()-1; i>=0; i--) { + CoolItem coolItem = (CoolItem)itemList.get(i); + if(coolItem.handle == component) { + return coolItem; + } + } + // Should not happen + return null; +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return ((CCoolBar)handle).getItemCount(); +} + +/** + * Returns an array of zero-relative ints that map + * the creation order of the receiver's items to the + * order in which they are currently being displayed. + *

    + * Specifically, the indices of the returned array represent + * the current visual order of the items, and the contents + * of the array represent the creation order of the items. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the current visual order of the receiver's items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int [] getItemOrder () { + checkWidget (); + Utils.notImplemented(); return null; +// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0); +// int [] indices = new int [count]; +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_ID; +// for (int i=0; iCoolItems in the order + * in which they are currently being displayed. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the receiver's items in their current visual order + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public CoolItem [] getItems () { + checkWidget (); + int count = getItemCount(); + CoolItem[] coolItems = new CoolItem[count]; + ArrayList itemList = (ArrayList)this.itemList.clone(); + Component[] components = handle.getComponents(); + for(int i=0; i=0; j--) { + CoolItem coolItem = (CoolItem)itemList.get(j); + if(coolItem.handle == component) { + itemList.remove(j); + coolItems[i] = coolItem; + break; + } + } + } + return coolItems; +} + +/** + * Returns an array of points whose x and y coordinates describe + * the widths and heights (respectively) of the items in the receiver + * in the order in which they are currently being displayed. + * + * @return the receiver's item sizes in their current visual order + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point [] getItemSizes () { + checkWidget (); + Component[] components = handle.getComponents(); + int count = components.length; + Point [] sizes = new Point [count]; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.0 + */ +public boolean getLocked () { + checkWidget (); + return ((CCoolBar)handle).isLocked(); +} + +/** + * Returns an array of ints that describe the zero-relative + * indices of any item(s) in the receiver that will begin on + * a new row. The 0th visible item always begins the first row, + * therefore it does not count as a wrap index. + * + * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int [] getWrapIndices () { + checkWidget (); + Component[] components = handle.getComponents(); + ArrayList wrapIndiceList = new ArrayList(); + for(int i=1; i + *
  • ERROR_NULL_ARGUMENT - if the item is null
  • + *
  • ERROR_INVALID_ARGUMENT - if the item is disposed
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (CoolItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + Component[] components = handle.getComponents(); + for(int i=0; i=0; i--) { + CoolItem item = (CoolItem)itemList.get(i); + if (item != null && !item.isDisposed ()) { + item.release (false); + } + } + itemList = null; + originalItemList = null; + } + super.releaseChildren (destroy); +} + +void removeControl (Control control) { + if(isDisposed()) return; + super.removeControl (control); + int count = itemList.size(); + for (int i=0; i + * The item order is the order in which the items in the receiver + * should be displayed, given in terms of the zero-relative ordering + * of when the items were added. + *

    + * The wrap indices are the indices of all item(s) in the receiver + * that will begin on a new row. The indices are given in the order + * specified by the item order. The 0th item always begins the first + * row, therefore it does not count as a wrap index. If wrap indices + * is null or empty, the items will be placed on one line. + *

    + * The sizes are specified in an array of points whose x and y + * coordinates describe the new widths and heights (respectively) + * of the receiver's items in the order specified by the item order. + *

    + * + * @param itemOrder an array of indices that describe the new order to display the items in + * @param wrapIndices an array of wrap indices, or null + * @param sizes an array containing the new sizes for each of the receiver's items in visual order + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if item order or sizes is null
    • + *
    • ERROR_INVALID_ARGUMENT - if item order or sizes is not the same length as the number of items
    • + *
    + */ +public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) { + checkWidget (); + setRedraw (false); + Utils.notImplemented(); +// setItemOrder (itemOrder); +// setWrapIndices (wrapIndices); +// setItemSizes (sizes); +// setRedraw (true); +} + +///* +// * Sets the order that the items in the receiver should +// * be displayed in to the given argument which is described +// * in terms of the zero-relative ordering of when the items +// * were added. +// * +// * @param itemOrder the new order to display the items in +// * +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT - if the item order is null
    • +// *
    • ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
    • +// *
    +// */ +//void setItemOrder (int [] itemOrder) { +// if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT); +// int itemCount = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0); +// if (itemOrder.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT); +// +// /* Ensure that itemOrder does not contain any duplicates. */ +// boolean [] set = new boolean [itemCount]; +// for (int i=0; i= itemCount) error (SWT.ERROR_INVALID_RANGE); +// if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT); +// set [index] = true; +// } +// +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// for (int i=0; i= 0) { +// resizeToMaximumWidth (index - 1); +// } +// if (i == lastItemDstRow) { +// resizeToMaximumWidth (i); +// } +// } +// } +//} +// +///* +// * Sets the width and height of the receiver's items to the ones +// * specified by the argument, which is an array of points whose x +// * and y coordinates describe the widths and heights (respectively) +// * in the order in which the items are currently being displayed. +// * +// * @param sizes an array containing the new sizes for each of the receiver's items in visual order +// * +// * @exception IllegalArgumentException
      +// *
    • ERROR_NULL_ARGUMENT - if the array of sizes is null
    • +// *
    • ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items
    • +// *
    +// * @exception SWTException
      +// *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • +// *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • +// *
    +// */ +//void setItemSizes (Point [] sizes) { +// if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT); +// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0); +// if (sizes.length != count) error (SWT.ERROR_INVALID_ARGUMENT); +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_ID; +// for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.0 + */ +public void setLocked (boolean locked) { + checkWidget (); + ((CCoolBar)handle).setLocked(locked); +} + +/** + * Sets the indices of all item(s) in the receiver that will + * begin on a new row. The indices are given in the order in + * which they are currently being displayed. The 0th item + * always begins the first row, therefore it does not count + * as a wrap index. If indices is null or empty, the items + * will be placed on one line. + * + * @param indices an array of wrap indices, or null + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setWrapIndices (int [] indices) { + checkWidget (); + if (indices == null) indices = new int [0]; + int count = getItemCount (); + for (int i=0; i= count) { + error (SWT.ERROR_INVALID_RANGE); + } + } + setRedraw (false); + ((CCoolBar)handle).setWrappedIndices(indices); + setRedraw (true); +} + +//int widgetStyle () { +// int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE; +// bits |= OS.RBS_VARHEIGHT | OS.RBS_DBLCLKTOGGLE; +// if ((style & SWT.FLAT) == 0) bits |= OS.RBS_BANDBORDERS; +// return bits; +//} +// +//TCHAR windowClass () { +// return ReBarClass; +//} +// +//int windowProc () { +// return ReBarProc; +//} +// +//LRESULT WM_COMMAND (int wParam, int lParam) { +// /* +// * Feature in Windows. When the coolbar window +// * proc processes WM_COMMAND, it forwards this +// * message to its parent. This is done so that +// * children of this control that send this message +// * type to their parent will notify not only +// * this control but also the parent of this control, +// * which is typically the application window and +// * the window that is looking for the message. +// * If the control did not forward the message, +// * applications would have to subclass the control +// * window to see the message. Because the control +// * window is subclassed by SWT, the message +// * is delivered twice, once by SWT and once when +// * the message is forwarded by the window proc. +// * The fix is to avoid calling the window proc +// * for this control. +// */ +// LRESULT result = super.WM_COMMAND (wParam, lParam); +// if (result != null) return result; +// return LRESULT.ZERO; +//} +// +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// LRESULT result = super.WM_ERASEBKGND (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Feature in Windows. For some reason, Windows +// * does not fully erase the area that the cool bar +// * occupies when the size of the cool bar is larger +// * than the space occupied by the cool bar items. +// * The fix is to erase the cool bar background. +// * +// * NOTE: On versions of Windows prior to XP, for +// * some reason, the cool bar draws separators in +// * WM_ERASEBKGND. Therefore it is essential to run +// * the cool bar window proc after the background has +// * been erased. +// * +// * On XP, this work around is unnecessary because +// * the background is drawn using NM_CUSTOMDRAW. +// */ +// if (OS.COMCTL32_MAJOR < 6) drawBackground (wParam); +// return null; +//} +// +//LRESULT WM_NOTIFY (int wParam, int lParam) { +// /* +// * Feature in Windows. When the cool bar window +// * proc processes WM_NOTIFY, it forwards this +// * message to its parent. This is done so that +// * children of this control that send this message +// * type to their parent will notify not only +// * this control but also the parent of this control, +// * which is typically the application window and +// * the window that is looking for the message. +// * If the control did not forward the message, +// * applications would have to subclass the control +// * window to see the message. Because the control +// * window is subclassed by SWT, the message +// * is delivered twice, once by SWT and once when +// * the message is forwarded by the window proc. +// * The fix is to avoid calling the window proc +// * for this control. +// */ +// LRESULT result = super.WM_NOTIFY (wParam, lParam); +// if (result != null) return result; +// return LRESULT.ZERO; +//} +// +//LRESULT WM_SETREDRAW (int wParam, int lParam) { +// LRESULT result = super.WM_SETREDRAW (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. When redraw is turned off, the rebar +// * control does not call the default window proc. This means +// * that the rebar will redraw and children of the rebar will +// * also redraw. The fix is to call both the rebar window proc +// * and the default window proc. +// * +// * NOTE: The rebar control can resize itself in WM_SETREDRAW. +// * When redraw is turned off by the default window proc, this +// * can leave pixel corruption in the parent. The fix is to +// * detect the size change and damage the previous area in the +// * parent. +// * +// * NOTE: In version 6.00 of COMCTL32.DLL, when WM_SETREDRAW +// * is off, we cannot detect that the size has changed causing +// * pixel corruption. The fix is to disallow WM_SETREDRAW by +// * not running the default window proc or the rebar window +// * proc. +// */ +// if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO; +// Rectangle rect = getBounds (); +// int code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); +// if (!rect.equals (getBounds ())) { +// parent.redraw (rect.x, rect.y, rect.width, rect.height, true); +// } +// return new LRESULT (code); +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// if (ignoreResize) { +// int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam); +// if (code == 0) return LRESULT.ZERO; +// return new LRESULT (code); +// } +// return super.WM_SIZE (wParam, lParam); +//} +// +//LRESULT wmNotifyChild (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// switch (hdr.code) { +// case OS.RBN_CHILDSIZE: +// /* +// * Bug in Windows. When Windows sets the size of the rebar band +// * child and the child is a combo box, the size of the drop down +// * portion of the combo box is resized to zero. The fix is to set +// * the size of the control to the current size after the rebar has +// * already resized it. If the control is not a combo, this does +// * nothing. If the control is a combo, the drop down portion is +// * recalculated. +// */ +// NMREBARCHILDSIZE lprbcs = new NMREBARCHILDSIZE (); +// OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof); +// if (lprbcs.uBand != -1) { +// CoolItem item = items [lprbcs.wID]; +// Control control = item.control; +// if (control != null) { +// int width = lprbcs.rcChild_right - lprbcs.rcChild_left; +// int height = lprbcs.rcChild_bottom - lprbcs.rcChild_top; +// control.setBounds (lprbcs.rcChild_left, lprbcs.rcChild_top, width, height); +// } +// } +// break; +// case OS.RBN_HEIGHTCHANGE: +// if (!ignoreResize) { +// Point size = getSize (); +// int border = getBorderWidth (); +// int height = OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0); +// setSize (size.x, height + (border * 2)); +// } +// break; +// case OS.RBN_CHEVRONPUSHED: +// NMREBARCHEVRON lpnm = new NMREBARCHEVRON (); +// OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof); +// CoolItem item = items [lpnm.wID]; +// if (item != null) { +// Event event = new Event(); +// event.detail = SWT.ARROW; +// event.x = lpnm.left; +// event.y = lpnm.bottom; +// item.postEvent (SWT.Selection, event); +// } +// break; +// case OS.NM_CUSTOMDRAW: +// /* +// * Bug in Windows. On versions of Windows prior to XP, +// * drawing the background color in NM_CUSTOMDRAW erases +// * the separators. The fix is to draw the background +// * in WM_ERASEBKGND. +// */ +// if (OS.COMCTL32_MAJOR < 6) break; +// if (background != -1 || (style & SWT.FLAT) != 0) { +// NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW (); +// OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof); +// switch (nmcd.dwDrawStage) { +// case OS.CDDS_PREERASE: +// return new LRESULT (OS.CDRF_NOTIFYPOSTERASE); +// case OS.CDDS_POSTERASE: +// drawBackground (nmcd.hdc); +// break; +// } +// } +// break; +// } +// return super.wmNotifyChild (wParam, lParam); +//} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java new file mode 100644 index 00000000000..53dd407074f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java @@ -0,0 +1,577 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.JComponent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CCoolItem; +import org.eclipse.swt.internal.swing.Compatibility; + +/** + * Instances of this class are selectable user interface + * objects that represent the dynamically positionable + * areas of a CoolBar. + *
    + *
    Styles:
    + *
    DROP_DOWN
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class CoolItem extends Item { + CoolBar parent; + Control control; + Container handle; + +// int id; +// boolean ideal, minimum; + +/** + * Constructs a new instance of this class given its parent + * (which must be a CoolBar), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index at which to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public CoolItem (CoolBar parent, int style) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a CoolBar), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the index at which to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public CoolItem (CoolBar parent, int style, int index) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, index); +} + +/** + * Adds the listener to the collection of listeners that will + * be notified when the control is selected, by sending it one + * of the messages defined in the SelectionListener + * interface. + *

    + * If widgetSelected is called when the mouse is over + * the drop-down arrow (or 'chevron') portion of the cool item, + * the event object detail field contains the value SWT.ARROW, + * and the x and y fields in the event object represent the point at + * the bottom left of the chevron, where the menu should be popped up. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + * + * @since 2.0 + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +/** + * Returns the preferred size of the receiver. + *

    + * The preferred size of a CoolItem is the size that + * it would best be displayed at. The width hint and height hint arguments + * allow the caller to ask the instance questions such as "Given a particular + * width, how high does it need to be to show all of the contents?" + * To indicate that the caller does not wish to constrain a particular + * dimension, the constant SWT.DEFAULT is passed for the hint. + *

    + * + * @param wHint the width hint (can be SWT.DEFAULT) + * @param hHint the height hint (can be SWT.DEFAULT) + * @return the preferred size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Layout + * @see #getBounds + * @see #getSize + * @see Control#getBorderWidth + * @see Scrollable#computeTrim + * @see Scrollable#getClientArea + */ +public Point computeSize (int wHint, int hHint) { + checkWidget (); + int index = parent.indexOf (this); + if (index == -1) return new Point (0, 0); + int width = wHint, height = hHint; + if (wHint == SWT.DEFAULT) width = handle.getWidth(); + if (hHint == SWT.DEFAULT) height = handle.getHeight(); +// if ((parent.style & SWT.VERTICAL) != 0) { +// height += parent.getMargin (index); +// } else { +// width += parent.getMargin (index); +// } + return new Point (width, height); +} + +Container createHandle () { + return (Container)CCoolItem.Factory.newInstance(this, style); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds () { + checkWidget (); + java.awt.Rectangle bounds = handle.getBounds(); + return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); +} + +///* +//* Not currently used. +//*/ +//Rectangle getClientArea () { +// checkWidget (); +// int index = parent.indexOf (this); +// if (index == -1) return new Rectangle (0, 0, 0, 0); +// int hwnd = parent.handle; +// RECT insetRect = new RECT (); +// OS.SendMessage (hwnd, OS.RB_GETBANDBORDERS, index, insetRect); +// RECT rect = new RECT (); +// OS.SendMessage (hwnd, OS.RB_GETRECT, index, rect); +// int x = rect.left + insetRect.left; +// int y = rect.top; +// int width = rect.right - rect.left - insetRect.left; +// int height = rect.bottom - rect.top; +// if ((parent.style & SWT.FLAT) == 0) { +// y += insetRect.top; +// width -= insetRect.right; +// height -= insetRect.top + insetRect.bottom; +// } +// if (index == 0) { +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_HEADERSIZE; +// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand); +// width = width - rbBand.cxHeader + 1; +// } +// return new Rectangle (x, y, width, height); +//} + +/** + * Returns the control that is associated with the receiver. + * + * @return the control that is contained by the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Control getControl () { + checkWidget (); + return control; +} + +/** + * Returns the receiver's parent, which must be a CoolBar. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public CoolBar getParent () { + checkWidget (); + return parent; +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; + control = null; +} + +/** + * Sets the control that is associated with the receiver + * to the argument. + * + * @param control the new control that will be contained by the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setControl (Control control) { + checkWidget (); + if (control != null) { + if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT); + } + if(this.control != null) { + handle.removeAll(); + } + this.control = control; + if(control != null) { + handle.add(control.handle); + } + handle.invalidate(); + handle.validate(); + handle.repaint(); +} + +/** + * Returns a point describing the receiver's ideal size. + * The x coordinate of the result is the ideal width of the receiver. + * The y coordinate of the result is the ideal height of the receiver. + * + * @return the receiver's ideal size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getPreferredSize () { + checkWidget (); + Dimension preferredSize = handle.getPreferredSize(); + return new Point (preferredSize.width, preferredSize.height); +} + +/** + * Sets the receiver's ideal size to the point specified by the arguments. + * + * @param width the new ideal width for the receiver + * @param height the new ideal height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPreferredSize (int width, int height) { + checkWidget (); + if(Compatibility.IS_JAVA_5_OR_GREATER) { + handle.setPreferredSize(new Dimension(width, height)); + } else if(handle instanceof JComponent) { + ((JComponent)handle).setPreferredSize(new Dimension(width, height)); + } + handle.invalidate(); + handle.validate(); + handle.repaint(); +} + +/** + * Sets the receiver's ideal size to the point specified by the argument. + * + * @param size the new ideal size for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPreferredSize (Point size) { + checkWidget (); + if (size == null) error(SWT.ERROR_NULL_ARGUMENT); + setPreferredSize (size.x, size.y); +} + +/** + * Returns a point describing the receiver's size. The + * x coordinate of the result is the width of the receiver. + * The y coordinate of the result is the height of the + * receiver. + * + * @return the receiver's size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSize() { + checkWidget (); + Dimension size = handle.getSize(); + return new Point (size.width, size.height); +} + +/** + * Sets the receiver's size to the point specified by the arguments. + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause that + * value to be set to zero instead. + *

    + * + * @param width the new width for the receiver + * @param height the new height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (int width, int height) { + checkWidget (); + handle.setSize(new Dimension(width, height)); +} + +/** + * Sets the receiver's size to the point specified by the argument. + *

    + * Note: Attempting to set the width or height of the + * receiver to a negative number will cause them to be + * set to zero instead. + *

    + * + * @param size the new size for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSize (Point size) { + if (size == null) error(SWT.ERROR_NULL_ARGUMENT); + setSize (size.x, size.y); +} + +/** + * Returns the minimum size that the cool item can + * be resized to using the cool item's gripper. + * + * @return a point containing the minimum width and height of the cool item, in pixels + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public Point getMinimumSize () { + checkWidget (); + Dimension minimumSize = handle.getMinimumSize(); + return new Point (minimumSize.width, minimumSize.height); +} + +/** + * Sets the minimum size that the cool item can be resized to + * using the cool item's gripper, to the point specified by the arguments. + * + * @param width the minimum width of the cool item, in pixels + * @param height the minimum height of the cool item, in pixels + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public void setMinimumSize (int width, int height) { + checkWidget (); + if(Compatibility.IS_JAVA_5_OR_GREATER) { + handle.setMinimumSize(new Dimension(width, height)); + } else if(handle instanceof JComponent) { + ((JComponent)handle).setMinimumSize(new Dimension(width, height)); + } +} + +/** + * Sets the minimum size that the cool item can be resized to + * using the cool item's gripper, to the point specified by the argument. + * + * @param size a point representing the minimum width and height of the cool item, in pixels + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public void setMinimumSize (Point size) { + checkWidget (); + if (size == null) error (SWT.ERROR_NULL_ARGUMENT); + setMinimumSize (size.x, size.y); +} + +//boolean getWrap() { +// int index = parent.indexOf (this); +// int hwnd = parent.handle; +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_STYLE; +// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand); +// return (rbBand.fStyle & OS.RBBS_BREAK) != 0; +//} + +//void setWrap(boolean wrap) { +// int index = parent.indexOf (this); +// int hwnd = parent.handle; +// REBARBANDINFO rbBand = new REBARBANDINFO (); +// rbBand.cbSize = REBARBANDINFO.sizeof; +// rbBand.fMask = OS.RBBIM_STYLE; +// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand); +// if (wrap) { +// rbBand.fStyle |= OS.RBBS_BREAK; +// } else { +// rbBand.fStyle &= ~OS.RBBS_BREAK; +// } +// OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, rbBand); +//} + +/** + * Removes the listener from the collection of listeners that + * will be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + * + * @since 2.0 + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java new file mode 100644 index 00000000000..4aec1901ada --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java @@ -0,0 +1,1611 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.util.ArrayList; + +import javax.swing.JMenuBar; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.CButton; +import org.eclipse.swt.internal.swing.CShell; + +/** + * Instances of this class provide the appearance and + * behavior of Shells, but are not top + * level shells or dialogs. Class Shell + * shares a significant amount of code with this class, + * and is a subclass. + *

    + * IMPORTANT: This class was intended to be abstract and + * should never be referenced or instantiated. + * Instead, the class Shell should be used. + *

    + *

    + * Instances are always displayed in one of the maximized, + * minimized or normal states: + *

      + *
    • + * When an instance is marked as maximized, the + * window manager will typically resize it to fill the + * entire visible area of the display, and the instance + * is usually put in a state where it can not be resized + * (even if it has style RESIZE) until it is + * no longer maximized. + *
    • + * When an instance is in the normal state (neither + * maximized or minimized), its appearance is controlled by + * the style constants which were specified when it was created + * and the restrictions of the window manager (see below). + *
    • + * When an instance has been marked as minimized, + * its contents (client area) will usually not be visible, + * and depending on the window manager, it may be + * "iconified" (that is, replaced on the desktop by a small + * simplified representation of itself), relocated to a + * distinguished area of the screen, or hidden. Combinations + * of these changes are also possible. + *
    • + *
    + *

    + * Note: The styles supported by this class must be treated + * as HINTs, since the window manager for the + * desktop on which the instance is visible has ultimate + * control over the appearance and behavior of decorations. + * For example, some window managers only support resizable + * windows and will always assume the RESIZE style, even if + * it is not set. + *
    + *
    Styles:
    + *
    BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL
    + *
    Events:
    + *
    (none)
    + *
    + * Class SWT provides two "convenience constants" + * for the most commonly required style combinations: + *
    + *
    SHELL_TRIM
    + *
    + * the result of combining the constants which are required + * to produce a typical application top level shell: (that + * is, CLOSE | TITLE | MIN | MAX | RESIZE) + *
    + *
    DIALOG_TRIM
    + *
    + * the result of combining the constants which are required + * to produce a typical application dialog shell: (that + * is, TITLE | CLOSE | BORDER) + *
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + * + * @see #getMinimized + * @see #getMaximized + * @see Shell + * @see SWT + */ + +public class Decorations extends Canvas { + Image image, smallImage, largeImage; + Image [] images; + Menu menuBar; + Menu [] menus; +// Control savedFocus; + Button defaultButton, saveDefault; +// int swFlags, hAccel, nAccel; +// boolean moved, resized, opened; + boolean opened; +// int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT; +// int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Decorations () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BORDER + * @see SWT#CLOSE + * @see SWT#MIN + * @see SWT#MAX + * @see SWT#RESIZE + * @see SWT#TITLE + * @see SWT#NO_TRIM + * @see SWT#SHELL_TRIM + * @see SWT#DIALOG_TRIM + * @see SWT#ON_TOP + * @see SWT#TOOL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Decorations (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +void addMenu (Menu menu) { + if (menus == null) menus = new Menu [4]; + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @see #setDefaultButton + */ +public Button getDefaultButton () { + checkWidget (); + return defaultButton; +} + +/** + * Returns the receiver's image if it had previously been + * set using setImage(). The image is typically + * displayed by the window manager when the instance is + * marked as iconified, and may also be displayed somewhere + * in the trim when the instance is in normal or maximized + * states. + *

    + * Note: This method will return null if called before + * setImage() is called. It does not provide + * access to a window manager provided, "default" image + * even if one exists. + *

    + * + * @return the image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getImage () { + checkWidget (); + return image; +} + +/** + * Returns the receiver's images if they had previously been + * set using setImages(). Images are typically + * displayed by the window manager when the instance is + * marked as iconified, and may also be displayed somewhere + * in the trim when the instance is in normal or maximized + * states. Depending where the icon is displayed, the platform + * chooses the icon with the "best" attributes. It is expected + * that the array will contain the same icon rendered at different + * sizes, with different depth and transparency attributes. + * + *

    + * Note: This method will return an empty array if called before + * setImages() is called. It does not provide + * access to a window manager provided, "default" image + * even if one exists. + *

    + * + * @return the images + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Image [] getImages () { + checkWidget (); + if (images == null) return new Image [0]; + Image [] result = new Image [images.length]; + System.arraycopy (images, 0, result, 0, images.length); + return result; +} + +//public Point getLocation () { +// checkWidget (); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) { +// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); +// lpwndpl.length = WINDOWPLACEMENT.sizeof; +// OS.GetWindowPlacement (handle, lpwndpl); +// return new Point (lpwndpl.left, lpwndpl.top); +// } +// } +// return super.getLocation (); +//} + +/** + * Returns true if the receiver is currently + * maximized, and false otherwise. + *

    + * + * @return the maximized state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setMaximized + */ +public boolean getMaximized () { + checkWidget (); + return (((CShell)handle).getExtendedState() & CShell.MAXIMIZED_BOTH) != 0; +} + +/** + * Returns the receiver's menu bar if one had previously + * been set, otherwise returns null. + * + * @return the menu bar or null + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getMenuBar () { + checkWidget (); + return menuBar; +} + +/** + * Returns true if the receiver is currently + * minimized, and false otherwise. + *

    + * + * @return the minimized state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setMinimized + */ +public boolean getMinimized () { + checkWidget (); + return (((CShell)handle).getExtendedState() & CShell.ICONIFIED) != 0; +} + +String getNameText () { + return getText (); +} + +//public Point getSize () { +// checkWidget (); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) { +// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); +// lpwndpl.length = WINDOWPLACEMENT.sizeof; +// OS.GetWindowPlacement (handle, lpwndpl); +// int width = lpwndpl.right - lpwndpl.left; +// int height = lpwndpl.bottom - lpwndpl.top; +// return new Point (width, height); +// } +// } +// return super.getSize (); +//} + +/** + * Returns the receiver's text, which is the string that the + * window manager will typically display as the receiver's + * title. If the text has not previously been set, + * returns an empty string. + * + * @return the text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + String title = ((CShell)handle).getTitle(); + return title == null? "": title; +} + +public boolean isReparentable () { + checkWidget (); + /* + * Feature in Windows. Calling SetParent() for a shell causes + * a kind of fake MDI to happen. It doesn't work well on Windows + * and is not supported on the other platforms. The fix is to + * disallow the SetParent(). + */ + return false; +} + +boolean isTabGroup () { + /* + * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX. + */ + return true; +} + +boolean isTabItem () { + /* + * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX. + */ + return false; +} + +Decorations menuShell () { + return this; +} + +void releaseChildren (boolean destroy) { + if (menuBar != null) { + menuBar.release (false); + menuBar = null; + } + super.releaseChildren (destroy); + if (menus != null) { + do { + int index = 0; + while (index < menus.length) { + Menu menu = menus [index]; + if (menu != null && !menu.isDisposed ()) { + while (menu.getParentMenu () != null) { + menu = menu.getParentMenu (); + } + menu.dispose (); + break; + } + index++; + } + if (index == menus.length) break; + } while (true); + menus = null; + } +} + +void releaseWidget () { + super.releaseWidget (); + if (smallImage != null) smallImage.dispose (); + if (largeImage != null) largeImage.dispose (); + smallImage = largeImage = image = null; + images = null; +// savedFocus = null; + defaultButton = saveDefault = null; +// if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel); +// hAccel = -1; +} + +void removeMenu (Menu menu) { + if (menus == null) return; + for (int i=0; isaved default button). If no default button had + * previously been set, or the saved default button was + * disposed, the receiver's default button will be set to + * null. + *

    + * The default button is the button that is selected when + * the receiver is active and the user presses ENTER. + *

    + * + * @param button the new default button + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the button has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDefaultButton (Button button) { + checkWidget (); + if (button != null) { + if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT); + } + setDefaultButton (button, true); +} + +void setDefaultButton (Button button, boolean save) { + if (button == null) { + if (defaultButton == saveDefault) { + if (save) saveDefault = null; + return; + } + } else { + if ((button.style & SWT.PUSH) == 0) return; + if (button == defaultButton) return; + } + if (defaultButton != null) { + if (!defaultButton.isDisposed ()) ((CShell)handle).setDefaultButton(null); + } + if ((defaultButton = button) == null) defaultButton = saveDefault; + if (defaultButton != null) { + if (!defaultButton.isDisposed ()) ((CShell)handle).setDefaultButton((CButton)defaultButton.handle); + } + if (save) saveDefault = defaultButton; + if (saveDefault != null && saveDefault.isDisposed ()) saveDefault = null; +} + +/** + * Sets the receiver's image to the argument, which may + * be null. The image is typically displayed by the window + * manager when the instance is marked as iconified, and + * may also be displayed somewhere in the trim when the + * instance is in normal or maximized states. + * + * @param image the new image (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget (); + if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + this.image = image; + ((CShell)handle).setIconImage(image.handle); +} + +/** + * Sets the receiver's images to the argument, which may + * be an empty array. Images are typically displayed by the + * window manager when the instance is marked as iconified, + * and may also be displayed somewhere in the trim when the + * instance is in normal or maximized states. Depending where + * the icon is displayed, the platform chooses the icon with + * the "best" attributes. It is expected that the array will + * contain the same icon rendered at different sizes, with + * different depth and transparency attributes. + * + * @param images the new image array + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of images is null
    • + *
    • ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setImages (Image [] images) { + checkWidget (); + if (images == null) error (SWT.ERROR_INVALID_ARGUMENT); + for (int i = 0; i < images.length; i++) { + if (images [i] == null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + } + this.images = images; + + if(images.length > 0) { + java.util.List imageList = new ArrayList(images.length); + for(int i=0; itrue causes the receiver + * to switch to the maximized state, and if the argument is + * false and the receiver was previously maximized, + * causes the receiver to switch back to either the minimized + * or normal states. + *

    + * Note: The result of intermixing calls to setMaximized(true) + * and setMinimized(true) will vary by platform. Typically, + * the behavior will match the platform user's expectations, but not + * always. This should be avoided if possible. + *

    + * + * @param maximized the new maximized state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setMinimized + */ +public void setMaximized (boolean maximized) { + checkWidget (); + CShell cShell = (CShell)handle; + if(maximized) { + cShell.setExtendedState(CShell.MAXIMIZED_BOTH); + } else { + cShell.setExtendedState(cShell.getExtendedState() & ~CShell.MAXIMIZED_BOTH); + } +} + +/** + * Sets the receiver's menu bar to the argument, which + * may be null. + * + * @param menu the new menu bar + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the menu has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the menu is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMenuBar (Menu menu) { + checkWidget (); + if (menuBar == menu) return; + if (menu != null) { + if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR); + if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT); + } + if (menu != null) display.removeBar (menu); + menuBar = menu; + ((CShell)handle).setJMenuBar((JMenuBar)menuBar.handle); +// destroyAccelerators (); +} + +/** + * Sets the minimized stated of the receiver. + * If the argument is true causes the receiver + * to switch to the minimized state, and if the argument is + * false and the receiver was previously minimized, + * causes the receiver to switch back to either the maximized + * or normal states. + *

    + * Note: The result of intermixing calls to setMaximized(true) + * and setMinimized(true) will vary by platform. Typically, + * the behavior will match the platform user's expectations, but not + * always. This should be avoided if possible. + *

    + * + * @param minimized the new maximized state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setMaximized + */ +public void setMinimized (boolean minimized) { + checkWidget (); + CShell cShell = (CShell)handle; + if(minimized) { + cShell.setExtendedState(CShell.ICONIFIED); + } else { + cShell.setExtendedState(cShell.getExtendedState() & ~CShell.ICONIFIED); + } +} + +//void setParent () { +// /* +// * In order for an MDI child window to support +// * a menu bar, setParent () is needed to reset +// * the parent. Otherwise, the MDI child window +// * will appear as a separate shell. This is an +// * undocumented and possibly dangerous Windows +// * feature. +// */ +// int hwndParent = parent.handle; +// display.lockActiveWindow = true; +// OS.SetParent (handle, hwndParent); +// if (!OS.IsWindowVisible (hwndParent)) { +// OS.ShowWindow (handle, OS.SW_SHOWNA); +// } +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// bits &= ~OS.WS_CHILD; +// OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP); +// OS.SetWindowLong (handle, OS.GWL_ID, 0); +// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; +// SetWindowPos (handle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags); +// display.lockActiveWindow = false; +//} +// +//void setPlacement (int x, int y, int width, int height, int flags) { +// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); +// lpwndpl.length = WINDOWPLACEMENT.sizeof; +// OS.GetWindowPlacement (handle, lpwndpl); +// lpwndpl.showCmd = OS.SW_SHOWNA; +// if (OS.IsIconic (handle)) { +// lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE; +// } else { +// if (OS.IsZoomed (handle)) { +// lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED; +// } +// } +// boolean sameOrigin = true; +// if ((flags & OS.SWP_NOMOVE) == 0) { +// sameOrigin = lpwndpl.left != x || lpwndpl.top != y; +// lpwndpl.right = x + (lpwndpl.right - lpwndpl.left); +// lpwndpl.bottom = y + (lpwndpl.bottom - lpwndpl.top); +// lpwndpl.left = x; +// lpwndpl.top = y; +// } +// boolean sameExtent = true; +// if ((flags & OS.SWP_NOSIZE) == 0) { +// sameExtent = lpwndpl.right - lpwndpl.left != width || lpwndpl.bottom - lpwndpl.top != height; +// lpwndpl.right = lpwndpl.left + width; +// lpwndpl.bottom = lpwndpl.top + height; +// } +// OS.SetWindowPlacement (handle, lpwndpl); +// if (OS.IsIconic (handle)) { +// if (sameOrigin) { +// moved = true; +// Point location = getLocation (); +// oldX = location.x; +// oldY = location.y; +// sendEvent (SWT.Move); +// if (isDisposed ()) return; +// } +// if (sameExtent) { +// resized = true; +// Rectangle rect = getClientArea (); +// oldWidth = rect.width; +// oldHeight = rect.height; +// sendEvent (SWT.Resize); +// if (isDisposed ()) return; +// if (layout != null) { +// markLayout (false, false); +// updateLayout (true, false); +// } +// } +// } +//} +// +//void setSavedFocus (Control control) { +// savedFocus = control; +//} +// +//void setSystemMenu () { +// if (OS.IsWinCE) return; +// int hMenu = OS.GetSystemMenu (handle, false); +// if (hMenu == 0) return; +// int oldCount = OS.GetMenuItemCount (hMenu); +// if ((style & SWT.RESIZE) == 0) { +// OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND); +// } +// if ((style & SWT.MIN) == 0) { +// OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND); +// } +// if ((style & SWT.MAX) == 0) { +// OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND); +// } +// if ((style & (SWT.MIN | SWT.MAX)) == 0) { +// OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND); +// } +// int newCount = OS.GetMenuItemCount (hMenu); +// if ((style & SWT.CLOSE) == 0 || newCount != oldCount) { +// OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND); +// MENUITEMINFO info = new MENUITEMINFO (); +// info.cbSize = MENUITEMINFO.sizeof; +// info.fMask = OS.MIIM_ID; +// int index = 0; +// while (index < newCount) { +// if (OS.GetMenuItemInfo (hMenu, index, true, info)) { +// if (info.wID == OS.SC_CLOSE) break; +// } +// index++; +// } +// if (index != newCount) { +// OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION); +// if ((style & SWT.CLOSE) == 0) { +// OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND); +// } +// } +// } +//} + +/** + * Sets the receiver's text, which is the string that the + * window manager will typically display as the receiver's + * title, to the argument, which must not be null. + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + ((CShell)handle).setTitle(string); +} + +public void setVisible (boolean visible) { + checkWidget (); +// if (drawCount != 0) { +// if (((state & HIDDEN) == 0) == visible) return; +// } else { + if (visible == handle.isVisible()) return; +// } + if (visible) { + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the show + * event. If this happens, just return. + */ + sendEvent (SWT.Show); + if (isDisposed ()) return; + handle.setVisible(true); +// if (drawCount != 0) { +// state &= ~HIDDEN; +// } else { +// if (menuBar != null) { +// display.removeBar (menuBar); +// OS.DrawMenuBar (handle); +// } +// OS.ShowWindow (handle, swFlags); + if (isDisposed ()) return; + opened = true; +// if (!moved) { +// moved = true; +// Point location = getLocation (); +// oldX = location.x; +// oldY = location.y; +// } +// if (!resized) { +// resized = true; +// Rectangle rect = getClientArea (); +// oldWidth = rect.width; +// oldHeight = rect.height; +// } +// OS.UpdateWindow (handle); +// } + } else { + handle.setVisible(false); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) { +// swFlags = OS.SW_SHOWMINNOACTIVE; +// } else { +// if (OS.IsZoomed (handle)) { +// swFlags = OS.SW_SHOWMAXIMIZED; +// } else { +// if (handle == OS.GetActiveWindow ()) { +// swFlags = OS.SW_RESTORE; +// } else { +// swFlags = OS.SW_SHOWNOACTIVATE; +// } +// } +// } +// } +// if (drawCount != 0) { +// state |= HIDDEN; +// } else { +// OS.ShowWindow (handle, OS.SW_HIDE); +// } + if (isDisposed ()) return; + sendEvent (SWT.Hide); + } +} + +//void sort (Image [] images, ImageData [] datas, int width, int height, int depth) { +// /* Shell Sort from K&R, pg 108 */ +// int length = images.length; +// if (length <= 1) return; +// for (int gap=length/2; gap>0; gap/=2) { +// for (int i=gap; i=0; j-=gap) { +// if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) { +// Image swap = images [j]; +// images [j] = images [j + gap]; +// images [j + gap] = swap; +// ImageData swapData = datas [j]; +// datas [j] = datas [j + gap]; +// datas [j + gap] = swapData; +// } +// } +// } +// } +//} + +//boolean translateAccelerator (MSG msg) { +// if (!isEnabled () || !isActive ()) return false; +// if (menuBar != null && !menuBar.isEnabled ()) return false; +// if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true; +// Decorations decorations = parent.menuShell (); +// return decorations.translateAccelerator (msg); +//} + +//boolean translateMenuAccelerator (MSG msg) { +// if (hAccel == -1) createAccelerators (); +// return hAccel != 0 && OS.TranslateAccelerator (handle, hAccel, msg) != 0; +//} +// +//boolean translateMDIAccelerator (MSG msg) { +// if (!(this instanceof Shell)) { +// Shell shell = getShell (); +// int hwndMDIClient = shell.hwndMDIClient; +// if (hwndMDIClient != 0 && OS.TranslateMDISysAccel (hwndMDIClient, msg)) { +// return true; +// } +// if (msg.message == OS.WM_KEYDOWN) { +// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false; +// switch (msg.wParam) { +// case OS.VK_F4: +// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); +// return true; +// case OS.VK_F6: +// if (traverseDecorations (true)) return true; +// } +// return false; +// } +// if (msg.message == OS.WM_SYSKEYDOWN) { +// switch (msg.wParam) { +// case OS.VK_F4: +// OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0); +// return true; +// } +// return false; +// } +// } +// return false; +//} + +boolean traverseDecorations (boolean next) { + Control [] children = parent._getChildren (); + int length = children.length; + int index = 0; + while (index < length) { + if (children [index] == this) break; + index++; + } + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in focus in + * or out events. Ensure that a disposed widget is + * not accessed. + */ + int start = index, offset = (next) ? 1 : -1; + while ((index = (index + offset + length) % length) != start) { + Control child = children [index]; + if (!child.isDisposed () && child instanceof Decorations) { + if (child.setFocus ()) return true; + } + } + return false; +} + +boolean traverseItem (boolean next) { + return false; +} + +boolean traverseReturn () { + if (defaultButton == null || defaultButton.isDisposed ()) return false; + if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false; + defaultButton.click (); + return true; +} + +//CREATESTRUCT widgetCreateStruct () { +// return new CREATESTRUCT (); +//} +// +//int widgetExtStyle () { +// int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD; +// bits &= ~OS.WS_EX_CLIENTEDGE; +// if ((style & SWT.NO_TRIM) != 0) return bits; +// if (OS.IsPPC) { +// if ((style & SWT.CLOSE) != 0) bits |= OS.WS_EX_CAPTIONOKBTN; +// } +// if ((style & SWT.RESIZE) != 0) return bits; +// if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME; +// return bits; +//} +// +//int widgetParent () { +// Shell shell = getShell (); +// return shell.hwndMDIClient (); +//} +// +//int widgetStyle () { +// /* +// * Clear WS_VISIBLE and WS_TABSTOP. NOTE: In Windows, WS_TABSTOP +// * has the same value as WS_MAXIMIZEBOX so these bits cannot be +// * used to control tabbing. +// */ +// int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE); +// +// /* Set the title bits and no-trim bits */ +// bits &= ~OS.WS_BORDER; +// if ((style & SWT.NO_TRIM) != 0) return bits; +// if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION; +// +// /* Set the min and max button bits */ +// if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX; +// if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX; +// +// /* Set the resize, dialog border or border bits */ +// if ((style & SWT.RESIZE) != 0) { +// /* +// * Note on WinCE PPC. SWT.RESIZE is used to resize +// * the Shell according to the state of the IME. +// * It does not set the WS_THICKFRAME style. +// */ +// if (!OS.IsPPC) bits |= OS.WS_THICKFRAME; +// } else { +// if ((style & SWT.BORDER) == 0) bits |= OS.WS_BORDER; +// } +// +// /* Set the system menu and close box bits */ +// if (!OS.IsPPC && !OS.IsSP) { +// if ((style & SWT.CLOSE) != 0) bits |= OS.WS_SYSMENU; +// } +// +// return bits; +//} +// +//int windowProc (int hwnd, int msg, int wParam, int lParam) { +// switch (msg) { +// case Display.SWT_GETACCEL: +// case Display.SWT_GETACCELCOUNT: +// if (hAccel == -1) createAccelerators (); +// return msg == Display.SWT_GETACCELCOUNT ? nAccel : hAccel; +// } +// return super.windowProc (hwnd, msg, wParam, lParam); +//} +// +//LRESULT WM_ACTIVATE (int wParam, int lParam) { +// LRESULT result = super.WM_ACTIVATE (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in AWT. When an AWT Window is activated, +// * for some reason, it seems to forward the WM_ACTIVATE +// * message to the parent. Normally, the parent is an +// * AWT Frame. When AWT is embedded in SWT, the SWT +// * shell gets the WM_ACTIVATE and assumes that it came +// * from Windows. When an SWT shell is activated it +// * restores focus to the last control that had focus. +// * If this control is an embedded composite, it takes +// * focus from the AWT Window. The fix is to ignore +// * WM_ACTIVATE messages that come from AWT Windows. +// */ +// if (OS.GetParent (lParam) == handle) { +// TCHAR buffer = new TCHAR (0, 128); +// OS.GetClassName (lParam, buffer, buffer.length ()); +// String className = buffer.toString (0, buffer.strlen ()); +// if (className.equals (Display.AWT_WINDOW_CLASS)) { +// return LRESULT.ZERO; +// } +// } +// if ((wParam & 0xFFFF) != 0) { +// /* +// * When the high word of wParam is non-zero, the activation +// * state of the window is being changed while the window is +// * minimized. If this is the case, do not report activation +// * events or restore the focus. +// */ +// if ((wParam >> 16) != 0) return result; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the activate +// * event. If this happens, end the processing of the +// * Windows message by returning zero as the result of +// * the window proc. +// */ +// Control control = display.findControl (lParam); +// if (control == null || control instanceof Shell) { +// if (this instanceof Shell) { +// sendEvent (SWT.Activate); +// if (isDisposed ()) return LRESULT.ZERO; +// } +// } +// if (restoreFocus ()) return LRESULT.ZERO; +// } else { +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the deactivate +// * event. If this happens, end the processing of the +// * Windows message by returning zero as the result of +// * the window proc. +// */ +// Control control = display.findControl (lParam); +// if (control == null || control instanceof Shell) { +// if (this instanceof Shell) { +// sendEvent (SWT.Deactivate); +// if (isDisposed ()) return LRESULT.ZERO; +// Shell shell = getShell (); +// shell.setActiveControl (null); +// if (isDisposed ()) return LRESULT.ZERO; +// } +// } +// saveFocus (); +// } +// return result; +//} +// +//LRESULT WM_CLOSE (int wParam, int lParam) { +// LRESULT result = super.WM_CLOSE (wParam, lParam); +// if (result != null) return result; +// if (isEnabled () && isActive ()) closeWidget (); +// return LRESULT.ZERO; +//} +// +//LRESULT WM_HOTKEY (int wParam, int lParam) { +// LRESULT result = super.WM_HOTKEY (wParam, lParam); +// if (result != null) return result; +// if (OS.IsSP) { +// /* +// * Feature on WinCE SP. The Back key is either used to close +// * the foreground Dialog or used as a regular Back key in an EDIT +// * control. The article 'Back Key' in MSDN for Smartphone +// * describes how an application should handle it. The +// * workaround is to override the Back key when creating +// * the menubar and handle it based on the style of the Shell. +// * If the Shell has the SWT.CLOSE style, close the Shell. +// * Otherwise, send the Back key to the window with focus. +// */ +// if (((lParam >> 16) & 0xFFFF) == OS.VK_ESCAPE) { +// if ((style & SWT.CLOSE) != 0) { +// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); +// } else { +// OS.SHSendBackToFocusWindow (OS.WM_HOTKEY, wParam, lParam); +// } +// return LRESULT.ZERO; +// } +// } +// return result; +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_KILLFOCUS (wParam, lParam); +// saveFocus (); +// return result; +//} +// +//LRESULT WM_MOVE (int wParam, int lParam) { +// if (moved) { +// Point location = getLocation (); +// if (location.x == oldX && location.y == oldY) { +// return null; +// } +// oldX = location.x; +// oldY = location.y; +// } +// return super.WM_MOVE (wParam, lParam); +//} +// +//LRESULT WM_NCACTIVATE (int wParam, int lParam) { +// LRESULT result = super.WM_NCACTIVATE (wParam, lParam); +// if (result != null) return result; +// if (wParam == 0) { +// if (display.lockActiveWindow) return LRESULT.ZERO; +// Control control = display.findControl (lParam); +// if (control != null) { +// Shell shell = getShell (); +// Decorations decorations = control.menuShell (); +// if (decorations.getShell () == shell) { +// if (this instanceof Shell) return LRESULT.ONE; +// if (display.ignoreRestoreFocus) { +// if (display.lastHittest != OS.HTCLIENT) { +// result = LRESULT.ONE; +// } +// } +// } +// } +// } +// if (!(this instanceof Shell)) { +// int hwndShell = getShell().handle; +// OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam); +// } +// return result; +//} +// +//LRESULT WM_QUERYOPEN (int wParam, int lParam) { +// LRESULT result = super.WM_QUERYOPEN (wParam, lParam); +// if (result != null) return result; +// sendEvent (SWT.Deiconify); +// // widget could be disposed at this point +// return result; +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_SETFOCUS (wParam, lParam); +// if (savedFocus != this) restoreFocus (); +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// LRESULT result = null; +// boolean changed = true; +// if (resized) { +// int newWidth = 0, newHeight = 0; +// switch (wParam) { +// case OS.SIZE_RESTORED: +// case OS.SIZE_MAXIMIZED: +// newWidth = lParam & 0xFFFF; +// newHeight = lParam >> 16; +// break; +// case OS.SIZE_MINIMIZED: +// Rectangle rect = getClientArea (); +// newWidth = rect.width; +// newHeight = rect.height; +// break; +// } +// changed = newWidth != oldWidth || newHeight != oldHeight; +// if (changed) { +// oldWidth = newWidth; +// oldHeight = newHeight; +// } +// } +// if (changed) { +// result = super.WM_SIZE (wParam, lParam); +// if (isDisposed ()) return result; +// } +// if (wParam == OS.SIZE_MINIMIZED) { +// sendEvent (SWT.Iconify); +// // widget could be disposed at this point +// } +// return result; +//} +// +//LRESULT WM_SYSCOMMAND (int wParam, int lParam) { +// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam); +// if (result != null) return result; +// if (!(this instanceof Shell)) { +// int cmd = wParam & 0xFFF0; +// switch (cmd) { +// case OS.SC_CLOSE: { +// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); +// return LRESULT.ZERO; +// } +// case OS.SC_NEXTWINDOW: { +// traverseDecorations (true); +// return LRESULT.ZERO; +// } +// } +// } +// return result; +//} +// +//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { +// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam); +// if (result != null) return result; +// if (display.lockActiveWindow) { +// WINDOWPOS lpwp = new WINDOWPOS (); +// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof); +// lpwp.flags |= OS.SWP_NOZORDER; +// OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof); +// } +// return result; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java new file mode 100644 index 00000000000..bc4f1cb2880 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.io.File; + +import javax.swing.JFileChooser; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; + +/** + * Instances of this class allow the user to navigate + * the file system and select a directory. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class DirectoryDialog extends Dialog { + String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$ + String directoryPath; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a shell which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public DirectoryDialog (Shell parent) { + this (parent, SWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a shell which will be the parent of the new instance + * @param style the style of dialog to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public DirectoryDialog (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns the path which the dialog will use to filter + * the directories it shows. + * + * @return the filter path + * + * @see #setFilterPath + */ +public String getFilterPath () { + return filterPath; +} + +/** + * Returns the dialog's message, which is a description of + * the purpose for which it was opened. This message will be + * visible on the dialog while it is open. + * + * @return the message + */ +public String getMessage () { + return message; +} + +/** + * Makes the dialog visible and brings it to the front + * of the display. + * + * @return a string describing the absolute path of the selected directory, + * or null if the dialog was cancelled or an error occurred + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the dialog has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
    • + *
    + */ +public String open () { + final JFileChooser fileChooser = new JFileChooser(filterPath); + String title = getText(); + if(title != null && title.length() > 0) { + fileChooser.setDialogTitle(title); + } + String fullPath = null; + // TODO: file filters + // TODO: custom message + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int returnValue = 0; + if((style & SWT.SAVE) != 0) { + returnValue = fileChooser.showSaveDialog(getParent().handle); + } else { + returnValue = fileChooser.showOpenDialog(getParent().handle); + } + if(returnValue == JFileChooser.APPROVE_OPTION) { + File directory = fileChooser.getSelectedFile(); + fullPath = directory.getAbsolutePath(); + filterPath = new String(fullPath); + } + return fullPath; +} + +/** + * Sets the path that the dialog will use to filter + * the directories it shows to the argument, which may + * be null. If the string is null, then the operating + * system's default filter path will be used. + *

    + * Note that the path string is platform dependent. + * For convenience, either '/' or '\' can be used + * as a path separator. + *

    + * + * @param string the filter path + */ +public void setFilterPath (String string) { + filterPath = string; +} + +/** + * Sets the dialog's message, which is a description of + * the purpose for which it was opened. This message will be + * visible on the dialog while it is open. + * + * @param string the message + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + */ +public void setMessage (String string) { + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + message = string; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java new file mode 100644 index 00000000000..9fdd6282c70 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java @@ -0,0 +1,2628 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.util.*; +import java.util.function.*; + +import javax.swing.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.swing.*; +import org.eclipse.swt.internal.swing.Compatibility; + +/** + * Instances of this class are responsible for managing the + * connection between SWT and the underlying operating + * system. Their most important function is to implement + * the SWT event loop in terms of the platform event model. + * They also provide various methods for accessing information + * about the operating system, and have overall control over + * the operating system resources which SWT allocates. + *

    + * Applications which are built with SWT will almost always + * require only a single display. In particular, some platforms + * which SWT supports will not allow more than one active + * display. In other words, some platforms do not support + * creating a new display if one already exists that has not been + * sent the dispose() message. + *

    + * In SWT, the thread which creates a Display + * instance is distinguished as the user-interface thread + * for that display. + *

    + * The user-interface thread for a particular display has the + * following special attributes: + *
      + *
    • + * The event loop for that display must be run from the thread. + *
    • + *
    • + * Some SWT API methods (notably, most of the public methods in + * Widget and its subclasses), may only be called + * from the thread. (To support multi-threaded user-interface + * applications, class Display provides inter-thread + * communication methods which allow threads other than the + * user-interface thread to request that it perform operations + * on their behalf.) + *
    • + *
    • + * The thread is not allowed to construct other + * Displays until that display has been disposed. + * (Note that, this is in addition to the restriction mentioned + * above concerning platform support for multiple displays. Thus, + * the only way to have multiple simultaneously active displays, + * even on platforms which support it, is to have multiple threads.) + *
    • + *
    + * Enforcing these attributes allows SWT to be implemented directly + * on the underlying operating system's event model. This has + * numerous benefits including smaller footprint, better use of + * resources, safer memory management, clearer program logic, + * better performance, and fewer overall operating system threads + * required. The down side however, is that care must be taken + * (only) when constructing multi-threaded applications to use the + * inter-thread communication mechanisms which this class provides + * when required. + *

    + * All SWT API methods which may only be called from the user-interface + * thread are distinguished in their documentation by indicating that + * they throw the "ERROR_THREAD_INVALID_ACCESS" + * SWT exception. + *

    + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    Close, Dispose
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * @see #syncExec + * @see #asyncExec + * @see #wake + * @see #readAndDispatch + * @see #sleep + * @see Device#dispose + */ + +public class Display extends Device { + + Consumer runtimeExceptionHandler = DefaultExceptionHandler.RUNTIME_EXCEPTION_HANDLER; + Consumer errorHandler = DefaultExceptionHandler.RUNTIME_ERROR_HANDLER; + + Event [] eventQueue; + EventTable eventTable, filterTable; + Vector timerList = new Vector(); + + /* Menus */ + Menu [] bars, popups; + ArrayList menuItemsList = new ArrayList(); + +// static final String AWT_WINDOW_CLASS = "SunAwtWindow"; + + /* Sync/Async Widget Communication */ + Synchronizer synchronizer = new Synchronizer (this); + Thread thread; + + /* Display Shutdown */ + ArrayList disposeList; +// Runnable [] disposeList; + + /* System Tray */ + Tray tray; + + /* System Images Cache */ + java.awt.Image errorIcon, workingIcon, infoIcon, questionIcon, warningIcon; + + /* System Cursors Cache */ + Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1]; + + /* Display Data */ + Object data; + String [] keys; + Object [] values; + + /* Key Mappings */ + static final int [] [] KeyTable = { + + /* Keyboard and Mouse Masks */ + {java.awt.event.KeyEvent.VK_ALT, SWT.ALT}, + {java.awt.event.KeyEvent.VK_SHIFT, SWT.SHIFT}, + {java.awt.event.KeyEvent.VK_CONTROL, SWT.CONTROL}, + {java.awt.event.KeyEvent.VK_WINDOWS, SWT.COMMAND}, + + /* NOT CURRENTLY USED */ +// {OS.VK_LBUTTON, SWT.BUTTON1}, +// {OS.VK_MBUTTON, SWT.BUTTON3}, +// {OS.VK_RBUTTON, SWT.BUTTON2}, + + /* Non-Numeric Keypad Keys */ + {java.awt.event.KeyEvent.VK_UP, SWT.ARROW_UP}, + {java.awt.event.KeyEvent.VK_DOWN, SWT.ARROW_DOWN}, + {java.awt.event.KeyEvent.VK_LEFT, SWT.ARROW_LEFT}, + {java.awt.event.KeyEvent.VK_RIGHT, SWT.ARROW_RIGHT}, + {java.awt.event.KeyEvent.VK_PAGE_UP, SWT.PAGE_UP}, + {java.awt.event.KeyEvent.VK_PAGE_DOWN, SWT.PAGE_DOWN}, + {java.awt.event.KeyEvent.VK_HOME, SWT.HOME}, + {java.awt.event.KeyEvent.VK_END, SWT.END}, + {java.awt.event.KeyEvent.VK_INSERT, SWT.INSERT}, + + /* Virtual and Ascii Keys */ + {java.awt.event.KeyEvent.VK_BACK_SPACE, SWT.BS}, + {java.awt.event.KeyEvent.VK_ENTER, SWT.CR}, + {java.awt.event.KeyEvent.VK_DELETE, SWT.DEL}, + {java.awt.event.KeyEvent.VK_ESCAPE, SWT.ESC}, + {java.awt.event.KeyEvent.VK_ENTER, SWT.LF}, + {java.awt.event.KeyEvent.VK_TAB, SWT.TAB}, + + /* Functions Keys */ + {java.awt.event.KeyEvent.VK_F1, SWT.F1}, + {java.awt.event.KeyEvent.VK_F2, SWT.F2}, + {java.awt.event.KeyEvent.VK_F3, SWT.F3}, + {java.awt.event.KeyEvent.VK_F4, SWT.F4}, + {java.awt.event.KeyEvent.VK_F5, SWT.F5}, + {java.awt.event.KeyEvent.VK_F6, SWT.F6}, + {java.awt.event.KeyEvent.VK_F7, SWT.F7}, + {java.awt.event.KeyEvent.VK_F8, SWT.F8}, + {java.awt.event.KeyEvent.VK_F9, SWT.F9}, + {java.awt.event.KeyEvent.VK_F10, SWT.F10}, + {java.awt.event.KeyEvent.VK_F11, SWT.F11}, + {java.awt.event.KeyEvent.VK_F12, SWT.F12}, + {java.awt.event.KeyEvent.VK_F13, SWT.F13}, + {java.awt.event.KeyEvent.VK_F14, SWT.F14}, + {java.awt.event.KeyEvent.VK_F15, SWT.F15}, + + /* Numeric Keypad Keys */ + {java.awt.event.KeyEvent.VK_MULTIPLY, SWT.KEYPAD_MULTIPLY}, + {java.awt.event.KeyEvent.VK_ADD, SWT.KEYPAD_ADD}, + {java.awt.event.KeyEvent.VK_ENTER, SWT.KEYPAD_CR}, + {java.awt.event.KeyEvent.VK_SUBTRACT, SWT.KEYPAD_SUBTRACT}, + {java.awt.event.KeyEvent.VK_DECIMAL, SWT.KEYPAD_DECIMAL}, + {java.awt.event.KeyEvent.VK_DIVIDE, SWT.KEYPAD_DIVIDE}, + {java.awt.event.KeyEvent.VK_NUMPAD0, SWT.KEYPAD_0}, + {java.awt.event.KeyEvent.VK_NUMPAD1, SWT.KEYPAD_1}, + {java.awt.event.KeyEvent.VK_NUMPAD2, SWT.KEYPAD_2}, + {java.awt.event.KeyEvent.VK_NUMPAD3, SWT.KEYPAD_3}, + {java.awt.event.KeyEvent.VK_NUMPAD4, SWT.KEYPAD_4}, + {java.awt.event.KeyEvent.VK_NUMPAD5, SWT.KEYPAD_5}, + {java.awt.event.KeyEvent.VK_NUMPAD6, SWT.KEYPAD_6}, + {java.awt.event.KeyEvent.VK_NUMPAD7, SWT.KEYPAD_7}, + {java.awt.event.KeyEvent.VK_NUMPAD8, SWT.KEYPAD_8}, + {java.awt.event.KeyEvent.VK_NUMPAD9, SWT.KEYPAD_9}, +// {java.awt.event.KeyEvent.VK_????, SWT.KEYPAD_EQUAL}, + + /* Other keys */ + {java.awt.event.KeyEvent.VK_CAPS_LOCK, SWT.CAPS_LOCK}, + {java.awt.event.KeyEvent.VK_NUM_LOCK, SWT.NUM_LOCK}, + {java.awt.event.KeyEvent.VK_SCROLL_LOCK, SWT.SCROLL_LOCK}, + {java.awt.event.KeyEvent.VK_PAUSE, SWT.PAUSE}, + {java.awt.event.KeyEvent.VK_CANCEL, SWT.BREAK}, + {java.awt.event.KeyEvent.VK_PRINTSCREEN, SWT.PRINT_SCREEN}, + {java.awt.event.KeyEvent.VK_HELP, SWT.HELP}, + + }; + + /* Multiple Displays */ + static Display Default; + static Display [] Displays = new Display [4]; + + /* Multiple Monitors */ +// static Monitor[] monitors = null; +// static int monitorCount = 0; + + /* Modality */ + Shell [] modalShells; + Shell modalDialogShell; + static boolean TrimEnabled = false; + + /* Package Name */ + static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$ + + static { + Utils.initializeProperties(); + CShell.ModalityHandler.initialize(); + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + protected Window hoveredWindow; + @Override + public void eventDispatched(AWTEvent event) { + java.awt.event.InputEvent ie = (java.awt.event.InputEvent)event; + Utils.storeModifiersEx(ie.getModifiersEx()); + if(ie instanceof MouseEvent) { + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + Utils.trackMouseProperties((MouseEvent)ie); + } + // It seems the mouse wheel event is sent to the wrong window. We have to retarget it in that case. + Component component = ie.getComponent(); + if(component == null) { + return; + } + Window window = component instanceof Window? (Window)component: SwingUtilities.getWindowAncestor(component); + switch(ie.getID()) { + case MouseEvent.MOUSE_WHEEL: + if(window != hoveredWindow && hoveredWindow != null && window != null) { + MouseWheelEvent mwe = (MouseWheelEvent)ie; + mwe.consume(); + java.awt.Point mouseLocation = mwe.getPoint(); + mouseLocation = SwingUtilities.convertPoint(component, mouseLocation, hoveredWindow); + Component c = hoveredWindow.findComponentAt(mouseLocation.x, mouseLocation.y); + mouseLocation = SwingUtilities.convertPoint(hoveredWindow, mouseLocation, c); + if(c != null) { + c.dispatchEvent(new MouseWheelEvent(c, mwe.getID(), mwe.getWhen(), mwe.getModifiers(), mouseLocation.x, mouseLocation.y, mwe.getClickCount(), mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation())); + } + } + break; + case MouseEvent.MOUSE_ENTERED: + break; + case MouseEvent.MOUSE_EXITED: + if(hoveredWindow != null) { + MouseEvent me = (MouseEvent)ie; + java.awt.Point mouseLocation = me.getPoint(); + mouseLocation = SwingUtilities.convertPoint(component, mouseLocation, hoveredWindow); + if(!hoveredWindow.contains(mouseLocation)) { + hoveredWindow = null; + } + } + break; + default: + if(window != null) { + hoveredWindow = window; + } + break; + } + return; + } + if(ie.getID() == KeyEvent.KEY_PRESSED) { + int dumpModifiers = KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK; + if((Utils.modifiersEx & dumpModifiers) == dumpModifiers && ((KeyEvent)ie).getKeyCode() == KeyEvent.VK_F2) { + Component component = ie.getComponent(); + Window window = component instanceof Window? (Window)component: SwingUtilities.getWindowAncestor(component); + if(window instanceof CShell) { + Component targetComponent; + if(Compatibility.IS_JAVA_5_OR_GREATER) { + java.awt.Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(mouseLocation, window); + targetComponent = window.findComponentAt(mouseLocation); + } else { + targetComponent = null; + } + for(; targetComponent != null && !(targetComponent instanceof CControl); targetComponent = targetComponent.getParent()); + Control control; + if(targetComponent != null) { + control = ((CControl)targetComponent).getSWTHandle(); + } else { + control = ((CShell)window).getSWTHandle(); + } + Utils.dumpTree(control); + } + } + } + } + }, AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.KEY_EVENT_MASK); + } + /* + * TEMPORARY CODE. Install the runnable that + * gets the current display. This code will + * be removed in the future. + */ + static { + DeviceFinder = () -> { + Device device = getCurrent (); + if (device == null) { + device = getDefault (); + } + setDevice (device); + }; + } + +/* +* TEMPORARY CODE. +*/ +static void setDevice (Device device) { + CurrentDevice = device; +} + +/** + * Constructs a new instance of this class. + *

    + * Note: The resulting display is marked as the current + * display. If this is the first display which has been + * constructed since the application started, it is also + * marked as the default display. + *

    + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see #getCurrent + * @see #getDefault + * @see Widget#checkSubclass + * @see Shell + */ +public Display () { + this (null); +} + +/** + * Constructs a new instance of this class using the parameter. + * + * @param data the device data + */ +public Display (DeviceData data) { + super (data); + boolean lightweightPopups = Utils.isLightweightPopups(); + ToolTipManager.sharedInstance().setLightWeightPopupEnabled(lightweightPopups); + JPopupMenu.setDefaultLightWeightPopupEnabled(lightweightPopups); + Utils.installDefaultLookAndFeel(); +} + +public static void main(final String[] args) { + UIThreadUtils.main(args); +} + +public static void swtExec(Runnable runnable) { + UIThreadUtils.swtExec(runnable); +} + +void addBar (Menu menu) { + if (bars == null) bars = new Menu [4]; + int length = bars.length; + for (int i=0; iSWT. When the event does occur, + * the listener is notified by sending it the handleEvent() + * message. + *

    + * Setting the type of an event to SWT.None from + * within the handleEvent() method can be used to + * change the event type and stop subsequent Java listeners + * from running. Because event filters run before other listeners, + * event filters can both block other listeners and set arbitrary + * fields within an event. For this reason, event filters are both + * powerful and dangerous. They should generally be avoided for + * performance, debugging and code maintenance reasons. + *

    + * + * @param eventType the type of event to listen for + * @param listener the listener which should be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Listener + * @see SWT + * @see #removeFilter + * @see #removeListener + * + * @since 3.0 + */ +public void addFilter (int eventType, Listener listener) { + checkDevice (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (filterTable == null) filterTable = new EventTable (); + filterTable.hook (eventType, listener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notifed when an event of the given type occurs. The event + * type is one of the event constants defined in class SWT. + * When the event does occur in the display, the listener is notified by + * sending it the handleEvent() message. + * + * @param eventType the type of event to listen for + * @param listener the listener which should be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Listener + * @see SWT + * @see #removeListener + * + * @since 2.0 + */ +public void addListener (int eventType, Listener listener) { + checkDevice (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) eventTable = new EventTable (); + eventTable.hook (eventType, listener); +} + +void addMenuItem (MenuItem item) { + menuItemsList.add(item); +} + +void addPopup (Menu menu) { + if (popups == null) popups = new Menu [4]; + int length = popups.length; + for (int i=0; irun() method of the runnable to + * be invoked by the user-interface thread at the next + * reasonable opportunity. The caller of this method continues + * to run in parallel, and is not notified when the + * runnable has completed. Specifying null as the + * runnable simply wakes the user-interface thread when run. + *

    + * Note that at the time the runnable is invoked, widgets + * that have the receiver as their display may have been + * disposed. Therefore, it is necessary to check for this + * case inside the runnable before accessing the widget. + *

    + * + * @param runnable code to run on the user-interface thread or null + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #syncExec + */ +public void asyncExec (Runnable runnable) { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + synchronizer.asyncExec (runnable); +} + +/** + * Causes the system hardware to emit a short sound + * (if it supports this capability). + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void beep () { + checkDevice (); + Toolkit.getDefaultToolkit().beep(); +} + +/** + * Checks that this class can be subclassed. + *

    + * IMPORTANT: See the comment in Widget.checkSubclass(). + *

    + * + * @exception SWTException
      + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Widget#checkSubclass + */ +protected void checkSubclass () { + if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS); +} + +@Override +protected void checkDevice () { + if (thread == null) error (SWT.ERROR_WIDGET_DISPOSED); + if (thread != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) error (SWT.ERROR_THREAD_INVALID_ACCESS); + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); +} + +static synchronized void checkDisplay (Thread thread, boolean multiple) { + for (int i=0; i + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + * + * @see Device#dispose + * + * @since 2.0 + */ +public void close () { + checkDevice (); + Event event = new Event (); + sendEvent (SWT.Close, event); + if (event.doit) dispose (); +} + +/** + * Creates the device in the operating system. If the device + * does not have a handle, this method may do nothing depending + * on the device. + *

    + * This method is called before init. + *

    + * + * @param data the DeviceData which describes the receiver + * + * @see #init + */ +@Override +protected void create (DeviceData data) { + checkSubclass (); + thread = Thread.currentThread (); + UIThreadUtils.setMainThread(thread); + checkDisplay (thread, true); + createDisplay (data); + register (this); + if (Default == null) Default = this; +} + +void createDisplay (DeviceData data) { +} + +static synchronized void deregister (Display display) { + for (int i=0; i + * This method is called after release. + *

    + * @see Device#dispose + * @see #release + */ +@Override +protected void destroy () { + if (this == Default) Default = null; + deregister (this); + destroyDisplay (); +} + +void destroyDisplay () { + if(UIThreadUtils.isRealDispatch()) { + UIThreadUtils.popQueue(); +// /* +// * When the session is ending, no SWT program can continue +// * to run. In order to avoid running code after the display +// * has been disposed, exit from Java. +// */ +// System.exit (0); + } +} + +/** + * Causes the run() method of the runnable to + * be invoked by the user-interface thread just before the + * receiver is disposed. Specifying a null runnable + * is ignored. + * + * @param runnable code to run at dispose time. + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public void disposeExec (Runnable runnable) { + checkDevice (); + if (disposeList == null) disposeList = new ArrayList(); + disposeList.add(runnable); +} + +/** + * Does whatever display specific cleanup is required, and then + * uses the code in SWTError.error to handle the error. + * + * @param code the descriptive error code + * + * @see SWT#error(int) + */ +void error (int code) { + SWT.error (code); +} + +boolean filterEvent (Event event) { + if (filterTable != null) filterTable.sendEvent (event); + return false; +} + +boolean filters (int eventType) { + if (filterTable == null) return false; + return filterTable.hooks (eventType); +} + +HashMap componentToControlMap = new HashMap(); + +Control findControl (Component handle) { + if (handle == null) return null; + do { + Control control = getControl (handle); + if (control != null) return control; + } while ((handle = handle.getParent()) != null); + return null; +} + +/** + * Returns the display which the given thread is the + * user-interface thread for, or null if the given thread + * is not a user-interface thread for any display. Specifying + * null as the thread will return null + * for the display. + * + * @param thread the user-interface thread + * @return the display for the given thread + */ +public static synchronized Display findDisplay (Thread thread) { + if(Displays.length == 0) return null; + if(Thread.currentThread() == thread && SwingUtilities.isEventDispatchThread()) { + return Displays[0]; + } + for (int i=0; iShell, or null + * if no shell belonging to the currently running application + * is active. + * + * @return the active shell or null + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Shell getActiveShell () { + checkDevice (); + Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if(window == null) return null; + return (Shell)findControl(window); +} + +/** + * Returns a rectangle describing the receiver's size and location. + * + * @return the bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +@Override +public Rectangle getBounds () { + checkDevice (); + java.awt.Rectangle rectangle = new java.awt.Rectangle(); + GraphicsEnvironment ge = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + for(int j=0; j + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + * + * @see #getBounds + */ +@Override +public Rectangle getClientArea () { + checkDevice (); + return getBounds(); +} + +Control getControl (Component handle) { + return (Control)componentToControlMap.get(handle); +} + +/** + * Returns the control which the on-screen pointer is currently + * over top of, or null if it is not currently over one of the + * controls built by the currently running application. + * + * @return the control under the cursor + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Control getCursorControl () { + checkDevice (); + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + return Utils.getTrakedMouseControl(); + } + java.awt.Point point = MouseInfo.getPointerInfo().getLocation(); + // TODO: what about windows? + Frame[] frames = Frame.getFrames(); + for(int i=0; i + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + */ +public Point getCursorLocation () { + checkDevice (); + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + java.awt.Point point = Utils.getTrakedMouseLocation(); + return new Point(point.x, point.y); + } + java.awt.Point point = MouseInfo.getPointerInfo().getLocation(); + return new Point(point.x, point.y); +} + +/** + * Returns an array containing the recommended cursor sizes. + * + * @return the array of cursor sizes + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public Point [] getCursorSizes () { + checkDevice (); + HashSet set = new HashSet(); + Toolkit toolkit = Toolkit.getDefaultToolkit(); + for(int i=8; i<64; i++) { + set.add(toolkit.getBestCursorSize(i, i)); + } + set.remove(new java.awt.Dimension(0, 0)); + Point[] sizes = new Point[set.size()]; + int i=0; + for(Iterator it=set.iterator(); it.hasNext(); ) { + java.awt.Dimension d = ((java.awt.Dimension)it.next()); + sizes[i++] = new Point(d.width, d.height); + } + return sizes; +} + +/** + * Returns the default display. One is created (making the + * thread that invokes this method its user-interface thread) + * if it did not already exist. + * + * @return the default display + */ +public static synchronized Display getDefault () { + if (Default == null) Default = new Display (); + return Default; +} + +static boolean isValidClass (Class clazz) { + String name = clazz.getName (); + int index = name.lastIndexOf ('.'); + return name.substring (0, index + 1).equals (PACKAGE_PREFIX); +} + +/** + * Returns the application defined property of the receiver + * with the specified name, or null if it has not been set. + *

    + * Applications may have associated arbitrary objects with the + * receiver in this fashion. If the objects stored in the + * properties need to be notified when the display is disposed + * of, it is the application's responsibility to provide a + * disposeExec() handler which does so. + *

    + * + * @param key the name of the property + * @return the value of the property or null if it has not been set + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the key is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setData(String, Object) + * @see #disposeExec(Runnable) + */ +public Object getData (String key) { + checkDevice (); + if (key == null) error (SWT.ERROR_NULL_ARGUMENT); +// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) { +// return new Boolean (runMessagesInIdle); +// } + if (keys == null) return null; + for (int i=0; idisplay specific data is a single, + * unnamed field that is stored with every display. + *

    + * Applications may put arbitrary objects in this field. If + * the object stored in the display specific data needs to + * be notified when the display is disposed of, it is the + * application's responsibility to provide a + * disposeExec() handler which does so. + *

    + * + * @return the display specific data + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #setData(Object) + * @see #disposeExec(Runnable) + */ +public Object getData () { + checkDevice (); + return data; +} + +/** + * Returns the button dismissal alignment, one of LEFT or RIGHT. + * The button dismissal alignment is the ordering that should be used when positioning the + * default dismissal button for a dialog. For example, in a dialog that contains an OK and + * CANCEL button, on platforms where the button dismissal alignment is LEFT, the + * button ordering should be OK/CANCEL. When button dismissal alignment is RIGHT, + * the button ordering should be CANCEL/OK. + * + * @return the button dismissal order + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1 + */ +public int getDismissalAlignment () { + checkDevice (); + return SWT.LEFT; +} + + +/** + * Returns the longest duration, in milliseconds, between + * two mouse button clicks that will be considered a + * double click by the underlying operating system. + * + * @return the double click time + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public int getDoubleClickTime () { + checkDevice (); + // TODO: Method in Swing to do that? + return 200; +} + +/** + * Returns the control which currently has keyboard focus, + * or null if keyboard events are not currently going to + * any of the controls built by the currently running + * application. + * + * @return the control under the cursor + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Control getFocusControl () { + checkDevice (); + Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if(component == null) return null; + return findControl(component); +} + +/** + * Returns true when the high contrast mode is enabled. + * Otherwise, false is returned. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *

    + * + * @return the high contrast mode + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public boolean getHighContrast () { + checkDevice (); + // TODO: What about other platforms + Boolean highContrast = (Boolean)Toolkit.getDefaultToolkit().getDesktopProperty("win.highContrast.on"); + return highContrast != null? highContrast.booleanValue(): false; +} + +/** + * Returns the maximum allowed depth of icons on this display, in bits per pixel. + * On some platforms, this may be different than the actual depth of the display. + * + * @return the maximum icon depth + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Device#getDepth + */ +public int getIconDepth () { + checkDevice (); + // TODO: is this correct? + return getDepth(); +} + +/** + * Returns an array containing the recommended icon sizes. + * + * @return the array of icon sizes + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Decorations#setImages(Image[]) + * + * @since 3.0 + */ +public Point [] getIconSizes () { + checkDevice (); + // TODO: method to do so in Swing? + return new Point [] { + new Point (32, 32), + new Point (64, 64), + }; +} + +MenuItem getMenuItem (JComponent component) { + for(int i=0; i + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + */ +public Shell [] getShells () { + checkDevice (); + ArrayList controlsList = new ArrayList(); + for(Iterator it = componentToControlMap.keySet().iterator(); it.hasNext(); ) { + Component component = (Component)it.next(); + // TODO: what about file dialogs and such? + if(component instanceof Window) { + Control control = findControl(component); + if(control instanceof Shell) { + controlsList.add(control); + } + } + } + return (Shell[])controlsList.toArray(new Shell[0]); +} + +/** + * Returns the thread that has invoked syncExec + * or null if no such runnable is currently being invoked by + * the user-interface thread. + *

    + * Note: If a runnable invoked by asyncExec is currently + * running, this method will return null. + *

    + * + * @return the receiver's sync-interface thread + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Thread getSyncThread () { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + return synchronizer.syncThread; +} + +/** + * Returns the matching standard color for the given + * constant, which should be one of the color constants + * specified in class SWT. Any value other + * than one of the SWT color constants which is passed + * in will result in the color black. This color should + * not be free'd because it was allocated by the system, + * not the application. + * + * @param id the color constant + * @return the matching color + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see SWT + */ +@Override +public Color getSystemColor (int id) { + checkDevice (); + java.awt.Color swingColor = LookAndFeelUtils.getSystemColor(id); + if(swingColor == null) { + return super.getSystemColor(id); + } + return Color.swing_new(this, swingColor); +} + +/** + * Returns the matching standard platform cursor for the given + * constant, which should be one of the cursor constants + * specified in class SWT. This cursor should + * not be free'd because it was allocated by the system, + * not the application. A value of null will + * be returned if the supplied constant is not an SWT cursor + * constant. + * + * @param id the SWT cursor constant + * @return the corresponding cursor or null + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see SWT#CURSOR_ARROW + * @see SWT#CURSOR_WAIT + * @see SWT#CURSOR_CROSS + * @see SWT#CURSOR_APPSTARTING + * @see SWT#CURSOR_HELP + * @see SWT#CURSOR_SIZEALL + * @see SWT#CURSOR_SIZENESW + * @see SWT#CURSOR_SIZENS + * @see SWT#CURSOR_SIZENWSE + * @see SWT#CURSOR_SIZEWE + * @see SWT#CURSOR_SIZEN + * @see SWT#CURSOR_SIZES + * @see SWT#CURSOR_SIZEE + * @see SWT#CURSOR_SIZEW + * @see SWT#CURSOR_SIZENE + * @see SWT#CURSOR_SIZESE + * @see SWT#CURSOR_SIZESW + * @see SWT#CURSOR_SIZENW + * @see SWT#CURSOR_UPARROW + * @see SWT#CURSOR_IBEAM + * @see SWT#CURSOR_NO + * @see SWT#CURSOR_HAND + * + * @since 3.0 + */ +public Cursor getSystemCursor (int id) { + checkDevice (); + if (!(0 <= id && id < cursors.length)) return null; + if (cursors [id] == null) { + cursors [id] = new Cursor (this, id); + } + return cursors [id]; +} + +/** + * Returns the matching standard platform image for the given + * constant, which should be one of the icon constants + * specified in class SWT. This image should + * not be free'd because it was allocated by the system, + * not the application. A value of null will + * be returned either if the supplied constant is not an + * SWT icon constant or if the platform does not define an + * image that corresponds to the constant. + * + * @param id the SWT icon constant + * @return the corresponding image or null + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see SWT#ICON_ERROR + * @see SWT#ICON_INFORMATION + * @see SWT#ICON_QUESTION + * @see SWT#ICON_WARNING + * @see SWT#ICON_WORKING + * + * @since 3.0 + */ +public Image getSystemImage (int id) { + checkDevice (); + java.awt.Image hIcon = null; + switch (id) { + case SWT.ICON_ERROR: + if (errorIcon == null) { + errorIcon = getImage(LookAndFeelUtils.getSystemIcon(id)); + } + hIcon = errorIcon; + break; + case SWT.ICON_INFORMATION: + if (infoIcon == null) { + infoIcon = getImage(LookAndFeelUtils.getSystemIcon(id)); + } + hIcon = infoIcon; + break; + case SWT.ICON_WORKING: + if (workingIcon == null) { + workingIcon = getImage(LookAndFeelUtils.getSystemIcon(id)); + } + hIcon = workingIcon; + break; + case SWT.ICON_QUESTION: + if (questionIcon == null) { + questionIcon = getImage(LookAndFeelUtils.getSystemIcon(id)); + } + hIcon = questionIcon; + break; + case SWT.ICON_WARNING: + if (warningIcon == null) { + warningIcon = getImage(LookAndFeelUtils.getSystemIcon(id)); + } + hIcon = warningIcon; + break; + } + if (hIcon == null) return null; + return Image.swing_new (this, SWT.ICON, hIcon); +} + +static java.awt.Image getImage(Icon icon) { + BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + icon.paintIcon(Utils.getDefaultComponent(), g, 0, 0); + g.dispose(); + return image; +} + +/** + * Returns the single instance of the system tray or null + * when there is no system tray available for the platform. + * + * @return the system tray or null + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + */ +public Tray getSystemTray () { + checkDevice (); + if (tray != null) return tray; + if (!Compatibility.IS_JAVA_6_OR_GREATER || !SystemTray.isSupported()) { + return null; + } + return tray = new Tray (this, SWT.NONE); +} + +/** + * Returns the user-interface thread for the receiver. + * + * @return the receiver's user-interface thread + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Thread getThread () { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + return thread; +} + +/** + * Invokes platform specific functionality to allocate a new GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Display. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param data the platform specific GC data + * @return the platform specific GC handle + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * @exception SWTError
      + *
    • ERROR_NO_HANDLES if a handle could not be obtained for gc creation
    • + *
    + */ +@Override +public CGC internal_new_GC (GCData data) { + if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED); + if (data != null) { + data.device = this; + } +// int hDC = OS.GetDC (0); +// if (hDC == 0) SWT.error (SWT.ERROR_NO_HANDLES); +// if (data != null) { +// int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; +// if ((data.style & mask) != 0) { +// data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0; +// } else { +// data.style |= SWT.LEFT_TO_RIGHT; +// } +// data.device = this; +// data.hFont = systemFont (); +// } +// return hDC; + Frame[] frames = Frame.getFrames (); + Graphics2D g = null; + for (int i = 0; i < frames.length; i++) { + if (frames[i].isActive ()) { + g = (Graphics2D) frames[i].getGraphics (); + break; + } + } + if(g == null) { + for (int i = 0; i < frames.length; i++) { + if (frames[i].isShowing()) { + g = (Graphics2D) frames[i].getGraphics (); + } + } + } + for (int i = 0; i < frames.length && g == null; i++) { + g = (Graphics2D) frames[i].getGraphics (); + } + if(g == null) { + g = new NullGraphics2D(); + } + final Graphics2D g2D = g; + return new CGC.CGCGraphics2D() { + @Override + public Graphics2D getGraphics() { + return g2D; + } + @Override + public Dimension getDeviceSize() { + Rectangle bounds = getBounds(); + return new Dimension(bounds.width, bounds.height); + } + }; +} + +/** + * Initializes any internal resources needed by the + * device. + *

    + * This method is called after create. + *

    + * + * @see #create + */ +@Override +protected void init () { + super.init (); +} + +/** + * Invokes platform specific functionality to dispose a GC handle. + *

    + * IMPORTANT: This method is not part of the public + * API for Display. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param handle the platform specific GC handle + * @param data the platform specific GC data + */ +@Override +public void internal_dispose_GC (CGC handle, GCData data) { + handle.dispose(); +} + +boolean isValidThread () { + return thread == Thread.currentThread () || SwingUtilities.isEventDispatchThread(); +} + +/** + * Maps a point from one coordinate system to another. + * When the control is null, coordinates are mapped to + * the display. + *

    + * NOTE: On right-to-left platforms where the coordinate + * systems are mirrored, special care needs to be taken + * when mapping coordinates from one control to another + * to ensure the result is correctly mirrored. + * + * Mapping a point that is the origin of a rectangle and + * then adding the width and height is not equivalent to + * mapping the rectangle. When one control is mirrored + * and the other is not, adding the width and height to a + * point that was mapped causes the rectangle to extend + * in the wrong direction. Mapping the entire rectangle + * instead of just one point causes both the origin and + * the corner of the rectangle to be mapped. + *

    + * + * @param from the source Control or null + * @param to the destination Control or null + * @param point to be mapped + * @return point with mapped coordinates + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1.2 + */ +public Point map (Control from, Control to, Point point) { + checkDevice (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + return map (from, to, point.x, point.y); +} + +/** + * Maps a point from one coordinate system to another. + * When the control is null, coordinates are mapped to + * the display. + *

    + * NOTE: On right-to-left platforms where the coordinate + * systems are mirrored, special care needs to be taken + * when mapping coordinates from one control to another + * to ensure the result is correctly mirrored. + * + * Mapping a point that is the origin of a rectangle and + * then adding the width and height is not equivalent to + * mapping the rectangle. When one control is mirrored + * and the other is not, adding the width and height to a + * point that was mapped causes the rectangle to extend + * in the wrong direction. Mapping the entire rectangle + * instead of just one point causes both the origin and + * the corner of the rectangle to be mapped. + *

    + * + * @param from the source Control or null + * @param to the destination Control or null + * @param x coordinates to be mapped + * @param y coordinates to be mapped + * @return point with mapped coordinates + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1.2 + */ +public Point map (Control from, Control to, int x, int y) { + checkDevice (); + if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + Rectangle r = map(from, to, x, y, 0, 0); + return new Point(r.x, r.y); +} + +/** + * Maps a point from one coordinate system to another. + * When the control is null, coordinates are mapped to + * the display. + *

    + * NOTE: On right-to-left platforms where the coordinate + * systems are mirrored, special care needs to be taken + * when mapping coordinates from one control to another + * to ensure the result is correctly mirrored. + * + * Mapping a point that is the origin of a rectangle and + * then adding the width and height is not equivalent to + * mapping the rectangle. When one control is mirrored + * and the other is not, adding the width and height to a + * point that was mapped causes the rectangle to extend + * in the wrong direction. Mapping the entire rectangle + * instead of just one point causes both the origin and + * the corner of the rectangle to be mapped. + *

    + * + * @param from the source Control or null + * @param to the destination Control or null + * @param rectangle to be mapped + * @return rectangle with mapped coordinates + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the rectangle is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1.2 + */ +public Rectangle map (Control from, Control to, Rectangle rectangle) { + checkDevice (); + if (rectangle == null) error (SWT.ERROR_NULL_ARGUMENT); + return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height); +} + +/** + * Maps a point from one coordinate system to another. + * When the control is null, coordinates are mapped to + * the display. + *

    + * NOTE: On right-to-left platforms where the coordinate + * systems are mirrored, special care needs to be taken + * when mapping coordinates from one control to another + * to ensure the result is correctly mirrored. + * + * Mapping a point that is the origin of a rectangle and + * then adding the width and height is not equivalent to + * mapping the rectangle. When one control is mirrored + * and the other is not, adding the width and height to a + * point that was mapped causes the rectangle to extend + * in the wrong direction. Mapping the entire rectangle + * instead of just one point causes both the origin and + * the corner of the rectangle to be mapped. + *

    + * + * @param from the source Control or null + * @param to the destination Control or null + * @param x coordinates to be mapped + * @param y coordinates to be mapped + * @param width coordinates to be mapped + * @param height coordinates to be mapped + * @return rectangle with mapped coordinates + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1.2 + */ +public Rectangle map (Control from, Control to, int x, int y, int width, int height) { + checkDevice (); + java.awt.Point point = new java.awt.Point(x, y); + if(from == null) { + if(to == null) return new Rectangle(x, y, width, height); + Point offset = to.getInternalOffset(); + point.x += offset.x; + point.y += offset.y; + SwingUtilities.convertPointFromScreen(point, ((CControl)to.handle).getClientArea()); + } else { + Point offset = from.getInternalOffset(); + point.x -= offset.x; + point.y -= offset.y; + if(to == null) { + SwingUtilities.convertPointToScreen(point, ((CControl)from.handle).getClientArea()); + } else { + offset = to.getInternalOffset(); + point.x += offset.x; + point.y += offset.y; + point = SwingUtilities.convertPoint(((CControl)from.handle).getClientArea(), point, ((CControl)to.handle).getClientArea()); + } + } + // TODO: check what the "mirror" stuff mentioned in the comments is about. + return new Rectangle(point.x, point.y, width, height); +} + +static int getPreviousInputState() { + return convertModifiersEx(Utils.previousModifiersEx); +} + +static int getInputState() { + return convertModifiersEx(Utils.modifiersEx); +} + +static int convertModifiersEx(int modifiersEx) { + int state = 0; + if((modifiersEx & java.awt.event.KeyEvent.SHIFT_DOWN_MASK) != 0) { + state |= SWT.SHIFT; + } + if((modifiersEx & java.awt.event.KeyEvent.ALT_DOWN_MASK) != 0) { + state |= SWT.ALT; + } + if((modifiersEx & java.awt.event.KeyEvent.CTRL_DOWN_MASK) != 0) { + state |= SWT.CTRL; + } + if((modifiersEx & java.awt.event.KeyEvent.BUTTON1_DOWN_MASK) != 0) { + state |= SWT.BUTTON1; + } + if((modifiersEx & java.awt.event.KeyEvent.BUTTON2_DOWN_MASK) != 0) { + state |= SWT.BUTTON2; + } + if((modifiersEx & java.awt.event.KeyEvent.BUTTON3_DOWN_MASK) != 0) { + state |= SWT.BUTTON3; + } + return state; +} + +/** + * Generate a low level system event. + * + * post is used to generate low level keyboard + * and mouse events. The intent is to enable automated UI + * testing by simulating the input from the user. Most + * SWT applications should never need to call this method. + *

    + * Note that this operation can fail when the operating system + * fails to generate the event for any reason. For example, + * this can happen when there is no such key or mouse button + * or when the system event queue is full. + *

    + *

    + * Event Types: + *

    KeyDown, KeyUp + *

    The following fields in the Event apply: + *

      + *
    • (in) type KeyDown or KeyUp
    • + *

      Either one of: + *

    • (in) character a character that corresponds to a keyboard key
    • + *
    • (in) keyCode the key code of the key that was typed, + * as defined by the key code constants in class SWT
    • + *
    + *

    MouseDown, MouseUp

    + *

    The following fields in the Event apply: + *

      + *
    • (in) type MouseDown or MouseUp + *
    • (in) button the button that is pressed or released + *
    + *

    MouseMove

    + *

    The following fields in the Event apply: + *

      + *
    • (in) type MouseMove + *
    • (in) x the x coordinate to move the mouse pointer to in screen coordinates + *
    • (in) y the y coordinate to move the mouse pointer to in screen coordinates + *
    + * + * + * @param event the event to be generated + * + * @return true if the event was generated or false otherwise + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the event is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.0 + * + */ +public boolean post (Event event) { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + if (event == null) error (SWT.ERROR_NULL_ARGUMENT); + try { + int type = event.type; + switch (type) { + case SWT.KeyDown: { + int keyCode = event.keyCode == 0? untranslateChar(event.character): untranslateKey(event.keyCode); + if(keyCode == 0) { + return false; + } + new Robot().keyPress(keyCode); + return true; + } + case SWT.KeyUp: + int keyCode = event.keyCode == 0? untranslateChar(event.character): untranslateKey(event.keyCode); + if(keyCode == 0) { + return false; + } + new Robot().keyRelease(keyCode); + return true; + case SWT.MouseMove: + new Robot().mouseMove(event.x, event.y); + return true; + case SWT.MouseDown: + case SWT.MouseUp: { + int buttons; + switch (event.button) { + case 1: buttons = java.awt.event.InputEvent.BUTTON1_MASK; break; + case 2: buttons = java.awt.event.InputEvent.BUTTON2_MASK; break; + case 3: buttons = java.awt.event.InputEvent.BUTTON3_MASK; break; + default: return false; + } + if(type == SWT.MouseDown) { + new Robot().mousePress(buttons); + } else { + new Robot().mouseRelease(buttons); + } + return true; + } + } + } catch(Exception e) { + return false; + } + return false; +} + +void postEvent (final Event event) { + /* + * Place the event at the end of the event queue. + * This code is always called in the Display's + * thread so it must be re-enterant but does not + * need to be synchronized. + */ + if (eventQueue == null) eventQueue = new Event [4]; + int index = 0; + int length = eventQueue.length; + while (index < length) { + if (eventQueue [index] == null) break; + index++; + } + if (index == length) { + Event [] newQueue = new Event [length + 4]; + System.arraycopy (eventQueue, 0, newQueue, 0, length); + eventQueue = newQueue; + } + eventQueue [index] = event; +} + +AWTEvent event; + +/** + * Reads an event from the operating system's event queue, + * dispatches it appropriately, and returns true + * if there is potentially more work to do, or false + * if the caller can sleep until another event is placed on + * the event queue. + *

    + * In addition to checking the system event queue, this method also + * checks if any inter-thread messages (created by syncExec() + * or asyncExec()) are waiting to be processed, and if + * so handles them before returning. + *

    + * + * @return false if the caller can sleep upon return from this method + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message
    • + *
    + * + * @see #sleep + * @see #wake + */ +public boolean readAndDispatch () { + checkDevice (); + if(UIThreadUtils.isRealDispatch()) { + boolean result = UIThreadUtils.swingEventQueue.dispatchEvent(); + UIThreadUtils.throwStoredException(); + runDeferredEvents (); + return result || isDisposed(); + } + if(event != null) { + AWTEvent awtEvent = event; + event = null; + try { + Object source = awtEvent.getSource(); + if (awtEvent instanceof ActiveEvent) { + ((ActiveEvent)awtEvent).dispatch(); + } else if(source instanceof Component) { + ((Component)source).dispatchEvent(awtEvent); + } else if(source instanceof MenuComponent) { + ((MenuComponent)source).dispatchEvent(awtEvent); + } + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } + UIThreadUtils.throwStoredException(); + return true; + } + if(SwingUtilities.isEventDispatchThread()) { + return isDisposed(); + } + synchronized(UIThreadUtils.UI_LOCK) { + if(UIThreadUtils.exclusiveSectionCount == 0) { + return isDisposed(); + } + try { + UIThreadUtils.UI_LOCK.notify(); + UIThreadUtils.UI_LOCK.wait(); + } catch(Exception e) { + } + UIThreadUtils.throwStoredException(); + } + runDeferredEvents (); +// return true; +// } +// /*boolean result =*/ runAsyncMessages (false); +// System.err.println(synchronizer.getMessageCount()); + return true; +} + +static synchronized void register (Display display) { + for (int i=0; i + * Disposes all shells which are currently open on the display. + * After this method has been invoked, all related related shells + * will answer true when sent the message + * isDisposed(). + *

    + * When a device is destroyed, resources that were acquired + * on behalf of the programmer need to be returned to the + * operating system. For example, if the device allocated a + * font to be used as the system font, this font would be + * freed in release. Also,to assist the garbage + * collector and minimize the amount of memory that is not + * reclaimed when the programmer keeps a reference to a + * disposed device, all fields except the handle are zero'd. + * The handle is needed by destroy. + *

    + * This method is called before destroy. + * + * @see Device#dispose + * @see #destroy + */ +@Override +protected void release () { + sendEvent (SWT.Dispose, new Event ()); + Shell [] shells = getShells (); + for (int i=0; iSWT. + * + * @param eventType the type of event to listen for + * @param listener the listener which should no longer be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Listener + * @see SWT + * @see #addFilter + * @see #addListener + * + * @since 3.0 + */ +public void removeFilter (int eventType, Listener listener) { + checkDevice (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (filterTable == null) return; + filterTable.unhook (eventType, listener); + if (filterTable.size () == 0) filterTable = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notifed when an event of the given type occurs. The event type + * is one of the event constants defined in class SWT. + * + * @param eventType the type of event to listen for + * @param listener the listener which should no longer be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Listener + * @see SWT + * @see #addListener + * + * @since 2.0 + */ +public void removeListener (int eventType, Listener listener) { + checkDevice (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (eventType, listener); +} + +void removeBar (Menu menu) { + if (bars == null) return; + for (int i=0; iNote: It is typically considered bad practice for a + * program to move the on-screen pointer location. + * + * @param x the new x coordinate for the cursor + * @param y the new y coordinate for the cursor + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.1 + */ +public void setCursorLocation (int x, int y) { + checkDevice (); + try { + new Robot().mouseMove(x, y); + } catch(Exception e) {} +} + +/** + * Sets the location of the on-screen pointer relative to the top left corner + * of the screen. Note: It is typically considered bad practice for a + * program to move the on-screen pointer location. + * + * @param point new position + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_NULL_ARGUMENT - if the point is null + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 2.0 + */ +public void setCursorLocation (Point point) { + checkDevice (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + setCursorLocation (point.x, point.y); +} + +/** + * Sets the application defined property of the receiver + * with the specified name to the given argument. + *

    + * Applications may have associated arbitrary objects with the + * receiver in this fashion. If the objects stored in the + * properties need to be notified when the display is disposed + * of, it is the application's responsibility provide a + * disposeExec() handler which does so. + *

    + * + * @param key the name of the property + * @param value the new value for the property + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the key is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getData(String) + * @see #disposeExec(Runnable) + */ +public void setData (String key, Object value) { + checkDevice (); + if (key == null) error (SWT.ERROR_NULL_ARGUMENT); +// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) { +// Boolean data = (Boolean) value; +// runMessagesInIdle = data != null && data.booleanValue (); +// return; +// } + + /* Remove the key/value pair */ + if (value == null) { + if (keys == null) return; + int index = 0; + while (index < keys.length && !keys [index].equals (key)) index++; + if (index == keys.length) return; + if (keys.length == 1) { + keys = null; + values = null; + } else { + String [] newKeys = new String [keys.length - 1]; + Object [] newValues = new Object [values.length - 1]; + System.arraycopy (keys, 0, newKeys, 0, index); + System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index); + System.arraycopy (values, 0, newValues, 0, index); + System.arraycopy (values, index + 1, newValues, index, newValues.length - index); + keys = newKeys; + values = newValues; + } + return; + } + + /* Add the key/value pair */ + if (keys == null) { + keys = new String [] {key}; + values = new Object [] {value}; + return; + } + for (int i=0; idisplay specific data is a single, + * unnamed field that is stored with every display. + *

    + * Applications may put arbitrary objects in this field. If + * the object stored in the display specific data needs to + * be notified when the display is disposed of, it is the + * application's responsibility provide a + * disposeExec() handler which does so. + *

    + * + * @param data the new display specific data + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #getData() + * @see #disposeExec(Runnable) + */ +public void setData (Object data) { + checkDevice (); + this.data = data; +} + +/** + * On platforms which support it, sets the application name + * to be the argument. On Motif, for example, this can be used + * to set the name used for resource lookup. Specifying + * null for the name clears it. + * + * @param name the new app name or null + */ +public static void setAppName (String name) { + /* Do nothing */ +} + +/** + * Sets the synchronizer used by the display to be + * the argument, which can not be null. + * + * @param synchronizer the new synchronizer for the display (must not be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the synchronizer is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message
    • + *
    + */ +public void setSynchronizer (Synchronizer synchronizer) { + checkDevice (); + if (synchronizer == null) error (SWT.ERROR_NULL_ARGUMENT); + if (this.synchronizer != null) { + this.synchronizer.runAsyncMessages(true); + } + this.synchronizer = synchronizer; +} + +/** + * Causes the user-interface thread to sleep (that is, + * to be put in a state where it does not consume CPU cycles) + * until an event is received or it is otherwise awakened. + * + * @return true if an event requiring dispatching was placed on the queue. + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #wake + */ +public boolean sleep () { + checkDevice (); + if(UIThreadUtils.isRealDispatch()) { + return UIThreadUtils.swingEventQueue.sleep(); + } + if(SwingUtilities.isEventDispatchThread()) { + boolean result = true; + UIThreadUtils.fakeDispatchingEDT = Thread.currentThread(); + try { + event = Toolkit.getDefaultToolkit().getSystemEventQueue().getNextEvent(); + } catch(InterruptedException e) { + result = false; + } + UIThreadUtils.fakeDispatchingEDT = null; + return result; + } + synchronized(UIThreadUtils.UI_LOCK) { + if(UIThreadUtils.exclusiveSectionCount == 0) { + try { + UIThreadUtils.UI_LOCK.wait(); + } catch(Exception e) { + } + } + return UIThreadUtils.exclusiveSectionCount > 0; + } +} + +/** + * Causes the run() method of the runnable to + * be invoked by the user-interface thread at the next + * reasonable opportunity. The thread which calls this method + * is suspended until the runnable completes. Specifying null + * as the runnable simply wakes the user-interface thread. + *

    + * Note that at the time the runnable is invoked, widgets + * that have the receiver as their display may have been + * disposed. Therefore, it is necessary to check for this + * case inside the runnable before accessing the widget. + *

    + * + * @param runnable code to run on the user-interface thread or null + * + * @exception SWTException
      + *
    • ERROR_FAILED_EXEC - if an exception occured when executing the runnable
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #asyncExec + */ +public void syncExec (Runnable runnable) { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + synchronizer.syncExec (runnable); +} + +/** + * Causes the run() method of the runnable to + * be invoked by the user-interface thread after the specified + * number of milliseconds have elapsed. If milliseconds is less + * than zero, the runnable is not executed. + *

    + * Note that at the time the runnable is invoked, widgets + * that have the receiver as their display may have been + * disposed. Therefore, it is necessary to check for this + * case inside the runnable before accessing the widget. + *

    + * + * @param milliseconds the delay before running the runnable + * @param runnable code to run on the user-interface thread + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the runnable is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #asyncExec + */ +public void timerExec (final int milliseconds, final Runnable runnable) { + checkDevice (); + if (runnable == null) error (SWT.ERROR_NULL_ARGUMENT); + if (milliseconds < 0) { + timerList.remove(runnable); + return; + } + timerList.add(runnable); + new Thread("Display.timerExecThread") { + @Override + public void run() { + try { + sleep(milliseconds); + boolean isRemoved = timerList.remove(runnable); + if(isRemoved) { + SwingUtilities.invokeLater(runnable); + } + } catch(Exception e) {} + } + }.start(); +} + +static int translateKey (int key) { + for (int i=0; i= '0' && c <='9') { + return c; + } + char uc = Character.toUpperCase(c); + if(uc >= 'A' && uc <= 'Z') { + return uc; + } + switch(c) { + case '\n': return java.awt.event.KeyEvent.VK_ENTER; + case '\b': return java.awt.event.KeyEvent.VK_BACK_SPACE; + case '\t': return java.awt.event.KeyEvent.VK_TAB; + case ' ': return java.awt.event.KeyEvent.VK_SPACE; + case ',': return java.awt.event.KeyEvent.VK_COMMA; + case '-': return java.awt.event.KeyEvent.VK_MINUS; + case '.': return java.awt.event.KeyEvent.VK_PERIOD; + case ';': return java.awt.event.KeyEvent.VK_SEMICOLON; + case '=': return java.awt.event.KeyEvent.VK_EQUALS; + case '[': return java.awt.event.KeyEvent.VK_OPEN_BRACKET; + case '\\': return java.awt.event.KeyEvent.VK_BACK_SLASH; + case ']': return java.awt.event.KeyEvent.VK_CLOSE_BRACKET; + case '`': return java.awt.event.KeyEvent.VK_BACK_QUOTE; + case '\u00B4': return java.awt.event.KeyEvent.VK_QUOTE; + case '&': return java.awt.event.KeyEvent.VK_AMPERSAND; + case '*': return java.awt.event.KeyEvent.VK_ASTERISK; + case '"': return java.awt.event.KeyEvent.VK_QUOTEDBL; + case '<': return java.awt.event.KeyEvent.VK_LESS; + case '>': return java.awt.event.KeyEvent.VK_GREATER; + case '{': return java.awt.event.KeyEvent.VK_BRACELEFT; + case '}': return java.awt.event.KeyEvent.VK_BRACERIGHT; + case '@': return java.awt.event.KeyEvent.VK_AT; + case ':': return java.awt.event.KeyEvent.VK_COLON; + case '^': return java.awt.event.KeyEvent.VK_CIRCUMFLEX; + case '$': return java.awt.event.KeyEvent.VK_DOLLAR; + case '\u20AC': return java.awt.event.KeyEvent.VK_EURO_SIGN; + case '!': return java.awt.event.KeyEvent.VK_EXCLAMATION_MARK; + case '\u00A1': return java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK; + case '(': return java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS; + case '#': return java.awt.event.KeyEvent.VK_NUMBER_SIGN; + case '+': return java.awt.event.KeyEvent.VK_PLUS; + case ')': return java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS; + case '_': return java.awt.event.KeyEvent.VK_UNDERSCORE; + } + return 0; +} + +/** + * Forces all outstanding paint requests for the display + * to be processed before this method returns. + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see Control#update() + */ +public void update() { + checkDevice (); + Shell[] shells = getShells (); + for (int i=0; isleeping, + * causes it to be awakened and start running again. Note that this + * method may be called from any thread. + * + * @exception SWTException
      + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @see #sleep + */ +public void wake () { + if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED); + if (thread == Thread.currentThread ()) return; + UIThreadUtils.wakeUIThread(); +} + +void wakeThread () { + SwingUtilities.invokeLater(() -> { + UIThreadUtils.startExclusiveSection(Display.this); + try { + runAsyncMessages (true); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } + UIThreadUtils.stopExclusiveSection(); + UIThreadUtils.throwStoredException(); +}); +} + +/** + * Sets a callback that will be invoked whenever an exception is thrown by a listener or external + * callback function. The application may use this to set a global exception handling policy: + * the most common policies are either to log and discard the exception or to re-throw the + * exception. + *

    + * The default SWT error handling policy is to rethrow exceptions. + * + * @param runtimeExceptionHandler new exception handler to be registered. + * @since 3.106 + */ +public final void setRuntimeExceptionHandler (Consumer runtimeExceptionHandler) { + checkDevice(); + this.runtimeExceptionHandler = Objects.requireNonNull (runtimeExceptionHandler); +} + +/** + * Returns the current exception handler. It will receive all exceptions thrown by listeners + * and external callbacks in this display. If code wishes to temporarily replace the exception + * handler (for example, during a unit test), it is common practice to invoke this method prior + * to replacing the exception handler so that the old handler may be restored afterward. + * + * @return the current exception handler. Never null. + * @since 3.106 + */ +public final Consumer getRuntimeExceptionHandler () { + return runtimeExceptionHandler; +} + +/** + * Sets a callback that will be invoked whenever an error is thrown by a listener or external + * callback function. The application may use this to set a global exception handling policy: + * the most common policies are either to log and discard the exception or to re-throw the + * exception. + *

    + * The default SWT error handling policy is to rethrow exceptions. + * + * @param errorHandler new error handler to be registered. + * @since 3.106 + */ +public final void setErrorHandler (Consumer errorHandler) { + checkDevice(); + this.errorHandler = Objects.requireNonNull (errorHandler); +} + +/** + * Returns the current exception handler. It will receive all errors thrown by listeners + * and external callbacks in this display. If code wishes to temporarily replace the error + * handler (for example, during a unit test), it is common practice to invoke this method prior + * to replacing the error handler so that the old handler may be restored afterward. + * + * @return the current error handler. Never null. + * @since 3.106 + */ +public final Consumer getErrorHandler () { + return errorHandler; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java new file mode 100644 index 00000000000..056a344a74c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + +import java.awt.Component; +import java.awt.Container; +import java.util.ArrayList; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ExpandAdapter; +import org.eclipse.swt.events.ExpandEvent; +import org.eclipse.swt.events.ExpandListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.CExpandBar; +import org.eclipse.swt.internal.swing.CExpandItem; +import org.eclipse.swt.internal.swing.JExpandPane.JExpandPaneItem; + +/** + * Instances of this class support the layout of selectable + * expand bar items. + *

    + * The item children that may be added to instances of this class + * must be of type ExpandItem. + *

    + *

    + *
    Styles:
    + *
    V_SCROLL
    + *
    Events:
    + *
    Expand, Collapse
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see ExpandItem + * @see ExpandEvent + * @see ExpandListener + * @see ExpandAdapter + * + * @since 3.2 + */ +public class ExpandBar extends Composite { + + ArrayList itemList; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ExpandBar (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +Control [] _getChildren () { + Component[] children = ((CControl)handle).getClientArea().getComponents(); + if(children.length == 0) { + return new Control[0]; + } + ArrayList controlsList = new ArrayList(children.length); + for(int i=0; iExpandListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ExpandListener + * @see #removeExpandListener + */ +public void addExpandListener (ExpandListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Expand, typedListener); + addListener (SWT.Collapse, typedListener); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +static int checkStyle (int style) { + style &= ~SWT.H_SCROLL; + return style | SWT.NO_BACKGROUND; +} + +boolean autoAddChildren() { + return false; +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~CANVAS; +} + +protected Container createHandle () { + return (Container)CExpandBar.Factory.newInstance(this, style); +} + +void createItem (ExpandItem item, int style, int index) { + int count = getItemCount(); + if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE); + itemList.add(index, item); + ((CExpandBar)handle).insertExpandPaneItem(null, null, item.handle, index); + handle.invalidate(); + handle.validate(); +} + +void createWidget () { + super.createWidget (); + itemList = new ArrayList(); +} + +void destroyItem (ExpandItem item) { + int index = indexOf(item); + if(index != -1) { + ((CExpandBar)handle).removeExpandPaneItem(item.handle); + handle.invalidate(); + handle.validate(); + handle.repaint(); + } + itemList = null; +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ExpandItem getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return (ExpandItem)itemList.get(index); +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return itemList.size(); +} + +/** + * Returns an array of ExpandItems which are the items + * in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ExpandItem [] getItems () { + checkWidget (); + return (ExpandItem[])itemList.toArray(new ExpandItem [0]); +} + +/** + * Returns the receiver's spacing. + * + * @return the spacing + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSpacing () { + checkWidget (); + return ((CExpandBar)handle).getSpacing(); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (ExpandItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = getItemCount(); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ExpandListener + * @see #addExpandListener + */ +public void removeExpandListener (ExpandListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Expand, listener); + eventTable.unhook (SWT.Collapse, listener); +} + +/** + * Sets the receiver's spacing. Spacing specifies the number of pixels allocated around + * each item. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSpacing (int spacing) { + checkWidget (); + if (spacing < 0) return; + ((CExpandBar)handle).setSpacing(spacing); +} + +} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java new file mode 100644 index 00000000000..457a8cb0309 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.ImageIcon; +import javax.swing.JComponent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.CExpandBar; +import org.eclipse.swt.internal.swing.CExpandItem; +import org.eclipse.swt.internal.swing.Compatibility; + +/** + * Instances of this class represent a selectable user interface object + * that represents a expandable item in a expand bar. + *

    + *

    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see ExpandBar + * + * @since 3.2 + */ +public class ExpandItem extends Item { + ExpandBar parent; + Control control; + Container handle; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ExpandItem (ExpandBar parent, int style) { + this (parent, style, parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent, a + * style value describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ExpandItem (ExpandBar parent, int style, int index) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, style, index); +} + +Container createHandle () { + return (Container)CExpandItem.Factory.newInstance(this, style); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns the control that is shown when the item is expanded. + * If no control has been set, return null. + * + * @return the control + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Control getControl () { + checkWidget (); + return control; +} + +/** + * Returns true if the receiver is expanded, + * and false otherwise. + * + * @return the expanded state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getExpanded () { + checkWidget (); + return ((CExpandBar)parent.handle).isExpanded(handle); +} + +/** + * Returns the height of the receiver's header + * + * @return the height of the header + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getHeaderHeight () { + checkWidget (); + return ((CExpandBar)parent.handle).getTitleBarSize(handle).height; +} + +/** + * Gets the height of the receiver. + * + * @return the height + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getHeight () { + checkWidget (); + return ((CExpandBar)parent.handle).getSize().height; +} + +/** + * Returns the receiver's parent, which must be a ExpandBar. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ExpandBar getParent () { + checkWidget (); + return parent; +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseWidget () { + super.releaseWidget (); + control = null; +} + + +/** + * Sets the control that is shown when the item is expanded. + * + * @param control the new control (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setControl (Control control) { + checkWidget(); + if (control != null) { + if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT); + } + if (this.control != null && this.control.isDisposed ()) { + this.control = null; + } + handle.remove(control.handle); + this.control = control; + if(control != null) { + handle.add(control.handle, BorderLayout.CENTER); + } + handle.invalidate(); + handle.validate(); + handle.repaint(); +} + +/** + * Sets the expanded state of the receiver. + * + * @param expanded the new expanded state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setExpanded (boolean expanded) { + checkWidget (); + ((CExpandBar)parent.handle).setExpanded(handle, expanded); +} + +/** + * Sets the height of the receiver. This is height of the item when it is expanded, + * excluding the height of the header. + * + * @param height the new height + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setHeight (int height) { + checkWidget (); + if (height < 0) return; + if(Compatibility.IS_JAVA_5_OR_GREATER) { + handle.setPreferredSize(new Dimension(handle.getPreferredSize().width, height)); + } else if(handle instanceof JComponent) { + ((JComponent)handle).setPreferredSize(new Dimension(handle.getPreferredSize().width, height)); + } + ((JComponent)handle).revalidate(); + handle.repaint(); +} + +public void setImage (Image image) { + super.setImage (image); + ((CExpandBar)parent.handle).setIcon(handle, new ImageIcon(image.handle)); +} + +public void setText (String string) { + super.setText (string); + ((CExpandBar)parent.handle).setText(handle, text); +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java new file mode 100644 index 00000000000..37fa4884934 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java @@ -0,0 +1,314 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.swing.Compatibility; + +/** + * Instances of this class allow the user to navigate + * the file system and select or enter a file name. + *
    + *
    Styles:
    + *
    SAVE, OPEN, MULTI
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of the styles SAVE and OPEN may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class FileDialog extends Dialog { + String [] filterNames = new String [0]; + String [] filterExtensions = new String [0]; + String [] fileNames = new String [0]; + String filterPath = "", fileName = ""; + static final String FILTER = "*.*"; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a shell which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public FileDialog (Shell parent) { + this (parent, SWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a shell which will be the parent of the new instance + * @param style the style of dialog to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public FileDialog (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns the path of the first file that was + * selected in the dialog relative to the filter path, or an + * empty string if no such file has been selected. + * + * @return the relative path of the file + */ +public String getFileName () { + return fileName; +} + +/** + * Returns a (possibly empty) array with the paths of all files + * that were selected in the dialog relative to the filter path. + * + * @return the relative paths of the files + */ +public String [] getFileNames () { + return fileNames; +} + +/** + * Returns the file extensions which the dialog will + * use to filter the files it shows. + * + * @return the file extensions filter + */ +public String [] getFilterExtensions () { + return filterExtensions; +} + +/** + * Returns the names that describe the filter extensions + * which the dialog will use to filter the files it shows. + * + * @return the list of filter names + */ +public String [] getFilterNames () { + return filterNames; +} + +/** + * Returns the directory path that the dialog will use, or an empty + * string if this is not set. File names in this path will appear + * in the dialog, filtered according to the filter extensions. + * + * @return the directory path string + * + * @see #setFilterExtensions + */ +public String getFilterPath () { + return filterPath; +} + +protected static String currentDirectoryPath; + +/** + * Makes the dialog visible and brings it to the front + * of the display. + * + * @return a string describing the absolute path of the first selected file, + * or null if the dialog was cancelled or an error occurred + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the dialog has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
    • + *
    + */ +public String open () { + final JFileChooser fileChooser = new JFileChooser(currentDirectoryPath); + String title = getText(); + if(title != null && title.length() > 0) { + fileChooser.setDialogTitle(title); + } + if(filterPath != null && filterPath.length() > 0) { + fileChooser.setCurrentDirectory(new File(filterPath)); + } + if(fileName != null && fileName.length() > 0) { + fileChooser.setSelectedFile(new File(fileChooser.getCurrentDirectory().getAbsolutePath() + "/" + fileName)); + } + fileName = ""; + fileNames = null; + String fullPath = null; + fileChooser.setMultiSelectionEnabled((style & SWT.MULTI) != 0); + if(filterExtensions != null && filterExtensions.length > 0) { + fileChooser.setAcceptAllFileFilterUsed(false); + for(int i=0; i= filterNames.length)? filterExtension: filterNames[i]; + fileChooser.addChoosableFileFilter(new FileFilter() { + public boolean accept(File f) { + if(f.isDirectory()) { + return true; + } + for(int i=0; i 0) { + fullPath = selectedFiles[0].getParentFile().getAbsolutePath(); + } + } else { + File selectedFile = fileChooser.getSelectedFile(); + fileName = selectedFile.getName(); + fullPath = selectedFile.getAbsolutePath(); + } + filterPath = new String(fullPath); + } + return fullPath; +} + +/** + * Set the initial filename which the dialog will + * select by default when opened to the argument, + * which may be null. The name will be prefixed with + * the filter path when one is supplied. + * + * @param string the file name + */ +public void setFileName (String string) { + fileName = string; +} + +/** + * Set the file extensions which the dialog will + * use to filter the files it shows to the argument, + * which may be null. + *

    + * The strings are platform specific. For example, on + * Windows, an extension filter string is typically of + * the form "*.extension", where "*.*" matches all files. + *

    + * + * @param extensions the file extension filter + * + * @see #setFilterNames to specify the user-friendly + * names corresponding to the extensions + */ +public void setFilterExtensions (String [] extensions) { + filterExtensions = extensions; +} + +/** + * Sets the the names that describe the filter extensions + * which the dialog will use to filter the files it shows + * to the argument, which may be null. + *

    + * Each name is a user-friendly short description shown for + * its corresponding filter. The names array must + * be the same length as the extensions array. + *

    + * + * @param names the list of filter names, or null for no filter names + * + * @see #setFilterExtensions + */ +public void setFilterNames (String [] names) { + filterNames = names; +} + +/** + * Sets the directory path that the dialog will use + * to the argument, which may be null. File names in this + * path will appear in the dialog, filtered according + * to the filter extensions. If the string is null, + * then the operating system's default filter path + * will be used. + *

    + * Note that the path string is platform dependent. + * For convenience, either '/' or '\' can be used + * as a path separator. + *

    + * + * @param string the directory path + * + * @see #setFilterExtensions + */ +public void setFilterPath (String string) { + filterPath = string; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java new file mode 100644 index 00000000000..6285166bdb7 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java @@ -0,0 +1,235 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Window; +import java.awt.font.TextAttribute; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.internal.swing.JFontChooser; + +/** + * Instances of this class allow the user to select a font + * from all available fonts in the system. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class FontDialog extends Dialog { + FontData fontData; + RGB rgb; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a shell which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public FontDialog (Shell parent) { + this (parent, SWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a shell which will be the parent of the new instance + * @param style the style of dialog to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public FontDialog (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns a FontData object describing the font that was + * selected in the dialog, or null if none is available. + * + * @return the FontData for the selected font, or null + * @deprecated use #getFontList () + */ +public FontData getFontData () { + return fontData; +} + +/** + * Returns a FontData set describing the font that was + * selected in the dialog, or null if none is available. + * + * @return the FontData for the selected font, or null + * @since 2.1.1 + */ +public FontData [] getFontList () { + if (fontData == null) return null; + FontData [] result = new FontData [1]; + result [0] = fontData; + return result; +} + +/** + * Returns an RGB describing the color that was selected + * in the dialog, or null if none is available. + * + * @return the RGB value for the selected color, or null + * + * @see PaletteData#getRGBs + * + * @since 2.1 + */ +public RGB getRGB () { + return rgb; +} + +/** + * Makes the dialog visible and brings it to the front + * of the display. + * + * @return a FontData object describing the font that was selected, + * or null if the dialog was cancelled or an error occurred + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the dialog has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
    • + *
    + */ +public FontData open () { + Window window = (Window)getParent().handle; + JFontChooser fontChooser; + if(window instanceof Frame) { + fontChooser = new JFontChooser((Frame)window); + } else { + fontChooser = new JFontChooser((java.awt.Dialog)window); + } + if(rgb != null) { + fontChooser.setDefaultColor(new Color(rgb.red, rgb.green, rgb.blue)); + } + int dpi = getParent().getDisplay().getDPI().x; + if(fontData != null) { + int height = Math.round(fontData.getHeight() * dpi / 72.0f); + int style = fontData.getStyle(); + style = (((style & SWT.ITALIC) != 0? java.awt.Font.ITALIC: 0)) | (((style & SWT.BOLD) != 0? java.awt.Font.BOLD: 0)); + + java.awt.Font defaultFont; + if(fontData.data != null) { + Map attributeMap = new HashMap(fontData.data); + attributeMap.put(TextAttribute.FAMILY, fontData.getName()); + attributeMap.put(TextAttribute.POSTURE, (style & SWT.ITALIC) != 0? TextAttribute.POSTURE_OBLIQUE: TextAttribute.POSTURE_REGULAR); + attributeMap.put(TextAttribute.WEIGHT, (style & SWT.BOLD) != 0? TextAttribute.WEIGHT_BOLD: TextAttribute.WEIGHT_REGULAR); + defaultFont = new java.awt.Font(attributeMap); + } else { + defaultFont = new java.awt.Font(fontData.getName(), style, height); + } + fontChooser.setDefaultFont(defaultFont); + } + fontChooser.setModal(true); + fontChooser.setVisible(true); + java.awt.Font font = fontChooser.getNewFont(); + if(font == null) { + return null; + } + Color color = fontChooser.getNewColor(); + int height = Math.round(font.getSize() * 72.0f / dpi); + int style = font.getStyle(); + fontData = new FontData(font.getName(), height, 0 | (((style & java.awt.Font.ITALIC) != 0? SWT.ITALIC: 0)) | (((style & java.awt.Font.BOLD) != 0? SWT.BOLD: 0))); + fontData.data = font.getAttributes(); + rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue()); + return fontData; +} + +/** + * Sets a FontData object describing the font to be + * selected by default in the dialog, or null to let + * the platform choose one. + * + * @param fontData the FontData to use initially, or null + * @deprecated use #setFontList (FontData []) + */ +public void setFontData (FontData fontData) { + this.fontData = fontData; +} + +/** + * Sets the set of FontData objects describing the font to + * be selected by default in the dialog, or null to let + * the platform choose one. + * + * @param fontData the set of FontData objects to use initially, or null + * to let the platform select a default when open() is called + * + * @see Font#getFontData + * + * @since 2.1.1 + */ +public void setFontList (FontData [] fontData) { + if (fontData != null && fontData.length > 0) { + this.fontData = fontData [0]; + } else { + this.fontData = null; + } +} + +/** + * Sets the RGB describing the color to be selected by default + * in the dialog, or null to let the platform choose one. + * + * @param rgb the RGB value to use initially, or null to let + * the platform select a default when open() is called + * + * @see PaletteData#getRGBs + * + * @since 2.1 + */ +public void setRGB (RGB rgb) { + this.rgb = rgb; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java new file mode 100644 index 00000000000..9ccd58d57ff --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java @@ -0,0 +1,412 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.swing.CGroup; + +/** + * Instances of this class provide an etched border + * with an optional title. + *

    + * Shadow styles are hints and may not be honoured + * by the platform. To create a group with the + * default shadow style for the platform, do not + * specify a shadow style. + *

    + *
    Styles:
    + *
    SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of the above styles may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class Group extends Composite { + + String text; + +// static final int CLIENT_INSET = 3; +// static final int GroupProc; +// static final TCHAR GroupClass = new TCHAR (0, OS.IsWinCE ? "BUTTON" : "SWT_GROUP", true); +// static { +// /* +// * Feature in Windows. The group box window class +// * uses the CS_HREDRAW and CS_VREDRAW style bits to +// * force a full redraw of the control and all children +// * when resized. This causes flashing. The fix is to +// * register a new window class without these bits and +// * implement special code that damages only the exposed +// * area. +// * +// * Feature in WinCE. On certain devices, defining +// * a new window class which looks like BUTTON causes +// * CreateWindowEx() to crash. The workaround is to use +// * the class Button directly. +// */ +// WNDCLASS lpWndClass = new WNDCLASS (); +// if (OS.IsWinCE) { +// OS.GetClassInfo (0, GroupClass, lpWndClass); +// GroupProc = lpWndClass.lpfnWndProc; +// } else { +// TCHAR WC_BUTTON = new TCHAR (0, "BUTTON", true); +// OS.GetClassInfo (0, WC_BUTTON, lpWndClass); +// GroupProc = lpWndClass.lpfnWndProc; +// int hInstance = OS.GetModuleHandle (null); +// if (!OS.GetClassInfo (hInstance, GroupClass, lpWndClass)) { +// int hHeap = OS.GetProcessHeap (); +// lpWndClass.hInstance = hInstance; +// lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW); +// int byteCount = GroupClass.length () * TCHAR.sizeof; +// int lpszClassName = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory (lpszClassName, GroupClass, byteCount); +// lpWndClass.lpszClassName = lpszClassName; +// OS.RegisterClass (lpWndClass); +//// OS.HeapFree (hHeap, 0, lpszClassName); +// } +// } +// } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SHADOW_ETCHED_IN + * @see SWT#SHADOW_ETCHED_OUT + * @see SWT#SHADOW_IN + * @see SWT#SHADOW_OUT + * @see SWT#SHADOW_NONE + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Group (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// if (handle == 0) return 0; +// /* +// * Feature in Windows. When the user clicks on the group +// * box label, the group box takes focus. This is unwanted. +// * The fix is to avoid calling the group box window proc. +// */ +// switch (msg) { +// case OS.WM_LBUTTONDOWN: +// case OS.WM_LBUTTONDBLCLK: +// return OS.DefWindowProc (hwnd, msg, wParam, lParam); +// } +// return OS.CallWindowProc (GroupProc, hwnd, msg, wParam, lParam); +//} + +static int checkStyle (int style) { + style |= SWT.NO_FOCUS; + /* + * Even though it is legal to create this widget + * with scroll bars, they serve no useful purpose + * because they do not automatically scroll the + * widget's client area. The fix is to clear + * the SWT style. + */ + return style & ~(SWT.H_SCROLL | SWT.V_SCROLL); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// Point size = super.computeSize (wHint, hHint, changed); +// int length = OS.GetWindowTextLength (handle); +// if (length != 0) { +// /* +// * If the group has text, and the text is wider than the +// * client area, pad the width so the text is not clipped. +// */ +// TCHAR buffer1 = new TCHAR (getCodePage (), length + 1); +// OS.GetWindowText (handle, buffer1, length + 1); +// int newFont, oldFont = 0; +// int hDC = OS.GetDC (handle); +// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// RECT rect = new RECT (); +// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE; +// OS.DrawText (hDC, buffer1, length, rect, flags); +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6); +// } +// return size; +//} +// +//public Rectangle computeTrim (int x, int y, int width, int height) { +// checkWidget (); +// Rectangle trim = super.computeTrim (x, y, width, height); +// int newFont, oldFont = 0; +// int hDC = OS.GetDC (handle); +// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// trim.x -= CLIENT_INSET; +// trim.y -= tm.tmHeight; +// trim.width += CLIENT_INSET * 2; +// trim.height += tm.tmHeight + CLIENT_INSET; +// return trim; +//} + +void createHandleInit() { + super.createHandleInit(); + state |= DRAW_BACKGROUND; + state &= ~CANVAS; +} + +protected Container createHandle () { + return (Container)CGroup.Factory.newInstance(this, style); +// super.createHandle (); +} + +//public Rectangle getClientArea () { +// checkWidget (); +// forceResize (); +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// int newFont, oldFont = 0; +// int hDC = OS.GetDC (handle); +// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// int x = CLIENT_INSET, y = tm.tmHeight; +// int width = rect.right - CLIENT_INSET * 2; +// int height = rect.bottom - y - CLIENT_INSET; +// return new Rectangle (x, y, width, height); +//} + +String getNameText () { + return getText (); +} + +/** + * Returns the receiver's text, which is the string that the + * is used as the title. If the text has not previously + * been set, returns an empty string. + * + * @return the text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + return text == null? "": text; +} + +boolean mnemonicHit (char key) { + return setFocus (); +} + +boolean mnemonicMatch (char key) { + char mnemonic = findMnemonic (getText ()); + if (mnemonic == '\0') return false; + return Character.toUpperCase (key) == Character.toUpperCase (mnemonic); +} + +/** + * Sets the receiver's text, which is the string that will + * be displayed as the receiver's title, to the argument, + * which may not be null. The string may include the mnemonic character. + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, focus is assigned + * to the first child of the group. On most platforms, the + * mnemonic appears underlined but may be emphasised in a + * platform specific manner. The mnemonic indicator character + * '&' can be escaped by doubling it in the string, causing + * a single '&' to be displayed. + *

    + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + this.text = string; + int mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); + mnemonicIndex -= mnemonicIndex - 1 - s.length(); + mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + ((CGroup)handle).setText(string); +} + +//int widgetStyle () { +// /* +// * Bug in Windows. When GetDCEx () is called with DCX_INTERSECTUPDATE, +// * the HDC that is returned does not include the current update region. +// * This was confirmed under DEBUG Windows when GetDCEx () complained about +// * invalid flags. Therefore, it is not easily possible to get an HDC from +// * outside of WM_PAINT that includes the current damage and clips children. +// * Because the receiver has children and draws a frame and label, it is +// * necessary that the receiver always draw clipped, in the current damaged +// * area. The fix is to force the receiver to be fully clipped by including +// * WS_CLIPCHILDREN and WS_CLIPSIBLINGS in the default style bits. +// */ +// return super.widgetStyle () | OS.BS_GROUPBOX | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS; +//} +// +//TCHAR windowClass () { +// return GroupClass; +//} +// +//int windowProc () { +// return GroupProc; +//} +// +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// LRESULT result = super.WM_ERASEBKGND (wParam, lParam); +// if (result != null) return result; +// /* +// * Feaure in Windows. Group boxes do not erase +// * the background before drawing. The fix is to +// * fill the background. +// * +// * NOTE: This work around causes flashing on XP +// * and is not necessary when a parent has a theme. +// */ +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// if (findThemeControl () != null) return result; +// } +// drawBackground (wParam); +// return LRESULT.ONE; +//} +// +//LRESULT WM_NCHITTEST (int wParam, int lParam) { +// LRESULT result = super.WM_NCHITTEST (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. The window proc for the group box +// * returns HTTRANSPARENT indicating that mouse messages +// * should not be delivered to the receiver and any children. +// * Normally, group boxes in Windows do not have children and +// * this is the correct behavior for this case. Because we +// * allow children, answer HTCLIENT to allow mouse messages +// * to be delivered to the children. +// */ +// int code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); +// if (code == OS.HTTRANSPARENT) code = OS.HTCLIENT; +// return new LRESULT (code); +//} +// +//LRESULT WM_MOUSEMOVE (int wParam, int lParam) { +// LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. In version 6.00 of COMCTL32.DLL, +// * every time the mouse moves, the group title redraws. +// * This only happens when WM_NCHITTEST returns HTCLIENT. +// * The fix is to avoid calling the group window proc. +// */ +// return LRESULT.ZERO; +//} +// +//LRESULT WM_PRINTCLIENT (int wParam, int lParam) { +// LRESULT result = super.WM_PRINTCLIENT (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. In version 6.00 of COMCTL32.DLL, +// * when WM_PRINTCLIENT is sent from a child BS_GROUP +// * control to a parent BS_GROUP, the parent BS_GROUP +// * clears the font from the HDC. Normally, group boxes +// * in Windows do not have children so this behavior is +// * undefined. When the parent of a BS_GROUP is not a +// * BS_GROUP, there is no problem. The fix is to save +// * and restore the current font. +// */ +// if (OS.COMCTL32_MAJOR >= 6) { +// int nSavedDC = OS.SaveDC (wParam); +// int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); +// OS.RestoreDC (wParam, nSavedDC); +// return new LRESULT (code); +// } +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// LRESULT result = super.WM_SIZE (wParam, lParam); +// if (OS.IsWinCE) return result; +// OS.InvalidateRect (handle, null, true); +// return result; +//} +// +//LRESULT wmColorChild (int wParam, int lParam) { +// LRESULT result = super.wmColorChild (wParam, lParam); +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// Control control = findThemeControl (); +// if (control != null) { +// OS.SetBkMode (wParam, OS.TRANSPARENT); +// RECT rect = new RECT (); +// OS.GetClientRect (control.handle, rect); +// OS.MapWindowPoints (control.handle, handle, rect, 2); +// control.drawThemeBackground (wParam, rect); +// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH)); +// } +// } +// return result; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java new file mode 100644 index 00000000000..c6c86443f4f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java @@ -0,0 +1,564 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.ImageIcon; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CLabel; + +/** + * Instances of this class represent a non-selectable + * user interface object that displays a string or image. + * When SEPARATOR is specified, displays a single + * vertical or horizontal line. + *
    + *
    Styles:
    + *
    SEPARATOR, HORIZONTAL, VERTICAL
    + *
    SHADOW_IN, SHADOW_OUT, SHADOW_NONE
    + *
    CENTER, LEFT, RIGHT, WRAP
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified. + * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified. + * Only one of CENTER, LEFT and RIGHT may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class Label extends Control { +// String text = ""; + Image image; + String text; +// int font; +// static final int LabelProc; +// static final TCHAR LabelClass = new TCHAR (0, "STATIC", true); +// static { +// WNDCLASS lpWndClass = new WNDCLASS (); +// OS.GetClassInfo (0, LabelClass, lpWndClass); +// LabelProc = lpWndClass.lpfnWndProc; +// } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SEPARATOR + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see SWT#SHADOW_IN + * @see SWT#SHADOW_OUT + * @see SWT#SHADOW_NONE + * @see SWT#CENTER + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#WRAP + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Label (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// if (handle == 0) return 0; +// return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam); +//} + +static int checkStyle (int style) { + style |= SWT.NO_FOCUS; + if ((style & SWT.SEPARATOR) != 0) { + style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0); + return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0); + } + return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0); +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// int width = 0, height = 0; +// int border = getBorderWidth (); +// if ((style & SWT.SEPARATOR) != 0) { +// int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER); +// if ((style & SWT.HORIZONTAL) != 0) { +// width = DEFAULT_WIDTH; height = lineWidth * 2; +// } else { +// width = lineWidth * 2; height = DEFAULT_HEIGHT; +// } +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// width += border * 2; height += border * 2; +// return new Point (width, height); +// } +// /* +// * NOTE: SS_BITMAP and SS_ICON are not single bit +// * masks so it is necessary to test for all of the +// * bits in these masks. +// */ +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP; +// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON; +// if (isBitmap || isIcon) { +// if (image != null) { +// Rectangle rect = image.getBounds(); +// width = rect.width; +// height = rect.height; +// } +// } else { +// int hDC = OS.GetDC (handle); +// int newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// int oldFont = OS.SelectObject (hDC, newFont); +// RECT rect = new RECT (); +// int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS; +// if ((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) { +// flags |= OS.DT_WORDBREAK; +// rect.right = wHint; +// } +// int length = OS.GetWindowTextLength (handle); +// TCHAR buffer = new TCHAR (getCodePage (), length + 1); +// OS.GetWindowText (handle, buffer, length + 1); +// OS.DrawText (hDC, buffer, length, rect, flags); +// width = rect.right - rect.left; +// height = rect.bottom - rect.top; +// if (height == 0) { +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// height = tm.tmHeight; +// } +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// } +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// width += border * 2; height += border * 2; +// /* +// * Feature in WinCE PPC. Text labels have a trim +// * of one pixel wide on the right and left side. +// * The fix is to increase the size. +// */ +// if (OS.IsWinCE) { +// if (!isBitmap && !isIcon) width += 2; +// } +// return new Point (width, height); +//} + +/** + * Returns a value which describes the position of the + * text or image in the receiver. The value will be one of + * LEFT, RIGHT or CENTER + * unless the receiver is a SEPARATOR label, in + * which case, NONE is returned. + * + * @return the alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAlignment () { + checkWidget (); + if ((style & SWT.SEPARATOR) != 0) return 0; + if ((style & SWT.LEFT) != 0) return SWT.LEFT; + if ((style & SWT.CENTER) != 0) return SWT.CENTER; + if ((style & SWT.RIGHT) != 0) return SWT.RIGHT; + return SWT.LEFT; +} + +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget (); + if((style & SWT.WRAP) != 0) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + isAdjustingSize = true; + } + }); + Dimension size = handle.getSize(); + if(wHint == SWT.DEFAULT) { + handle.setSize(((CLabel)handle).getPreferredWidth(), 0); + } else { + handle.setSize(wHint, 0); + } + Point point = super.computeSize (wHint, hHint, changed); + handle.setSize(size); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + isAdjustingSize = false; + } + }); + return point; + } + return super.computeSize (wHint, hHint, changed); +} + +void createHandleInit() { + super.createHandleInit(); + state |= THEME_BACKGROUND; +} + +Container createHandle () { + return (Container)CLabel.Factory.newInstance(this, style); +} + +/** + * Returns the receiver's image if it has one, or null + * if it does not. + * + * @return the receiver's image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getImage () { + checkWidget (); + return image; +} + +String getNameText () { + return getText (); +} + +/** + * Returns the receiver's text, which will be an empty + * string if it has never been set or if the receiver is + * a SEPARATOR label. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + if ((style & SWT.SEPARATOR) != 0) return ""; + return text == null? "": text; +} + +//boolean mnemonicHit (char key) { +// Composite control = this.parent; +// while (control != null) { +// Control [] children = control._getChildren (); +// int index = 0; +// while (index < children.length) { +// if (children [index] == this) break; +// index++; +// } +// index++; +// if (index < children.length) { +// if (children [index].setFocus ()) return true; +// } +// control = control.parent; +// } +// return false; +//} +// +//boolean mnemonicMatch (char key) { +// char mnemonic = findMnemonic (getText ()); +// if (mnemonic == '\0') return false; +// return Character.toUpperCase (key) == Character.toUpperCase (mnemonic); +//} + +void releaseWidget () { + super.releaseWidget (); + image = null; +} + +/** + * Controls how text and images will be displayed in the receiver. + * The argument should be one of LEFT, RIGHT + * or CENTER. If the receiver is a SEPARATOR + * label, the argument is ignored and the alignment is not changed. + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAlignment (int alignment) { + checkWidget (); + if ((style & SWT.SEPARATOR) != 0) return; + if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return; + style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); + style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if((alignment & SWT.LEFT) != 0) { + ((CLabel)handle).setAlignment(SwingConstants.LEFT); + } else if((alignment & SWT.RIGHT) != 0) { + ((CLabel)handle).setAlignment(SwingConstants.RIGHT); + } else if((alignment & SWT.CENTER) != 0) { + ((CLabel)handle).setAlignment(SwingConstants.CENTER); + } +} + +/** + * Sets the receiver's image to the argument, which may be + * null indicating that no image should be displayed. + * + * @param image the image to display on the receiver (may be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget (); + if ((style & SWT.SEPARATOR) != 0) return; + if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + this.image = image; + ImageIcon icon = null; + if (image != null && image.handle != null) { + icon = new ImageIcon (image.handle); + } + ((CLabel) handle).setIcon (icon); +} + +/** + * Sets the receiver's text. + *

    + * This method sets the widget label. The label may include + * the mnemonic character and line delimiters. + *

    + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, focus is assigned + * to the control that follows the label. On most platforms, + * the mnemonic appears underlined but may be emphasised in a + * platform specific manner. The mnemonic indicator character + * '&' can be escaped by doubling it in the string, causing + * a single '&' to be displayed. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.SEPARATOR) != 0) return; + this.text = string; + int mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); + mnemonicIndex -= mnemonicIndex - 1 - s.length(); + mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + ((CLabel)handle).setText(string, mnemonicIndex); +} + +//int widgetExtStyle () { +// int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE; +// if ((style & SWT.BORDER) != 0) return bits | OS.WS_EX_STATICEDGE; +// return bits; +//} +// +//int widgetStyle () { +// int bits = super.widgetStyle () | OS.SS_NOTIFY; +// if ((style & SWT.SEPARATOR) != 0) return bits | OS.SS_OWNERDRAW; +// if ((style & SWT.CENTER) != 0) return bits | OS.SS_CENTER; +// if ((style & SWT.RIGHT) != 0) return bits | OS.SS_RIGHT; +// if ((style & SWT.WRAP) != 0) return bits | OS.SS_LEFT; +// return bits | OS.SS_LEFTNOWORDWRAP; +//} +// +//TCHAR windowClass () { +// return LabelClass; +//} +// +//int windowProc () { +// return LabelProc; +//} +// +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// LRESULT result = super.WM_ERASEBKGND (wParam, lParam); +// if (result != null) return result; +// if ((style & SWT.SEPARATOR) != 0) return LRESULT.ONE; +// /* +// * Bug in Windows. When a label has the SS_BITMAP +// * or SS_ICON style, the label does not draw the +// * background. The fix is to draw the background +// * when the label is showing a bitmap or icon. +// * +// * NOTE: SS_BITMAP and SS_ICON are not single bit +// * masks so it is necessary to test for all of the +// * bits in these masks. +// */ +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP; +// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON; +// if (isBitmap || isIcon) { +// drawBackground (wParam); +// return LRESULT.ONE; +// } +// return result; +//} +// +//LRESULT WM_GETFONT (int wParam, int lParam) { +// LRESULT result = super.WM_GETFONT (wParam, lParam); +// if (result != null) return result; +// /* +// * Bug in Windows. When the style of a label is SS_BITMAP +// * or SS_ICON, the label does not remember the font that is +// * set in WM_SETFONT. The fix is to remember the font and +// * return the font in WM_GETFONT. +// */ +// if (font == 0) font = defaultFont (); +// return new LRESULT (font); +//} +// +//LRESULT WM_SETFONT (int wParam, int lParam) { +// /* +// * Bug in Windows. When the style of a label is SS_BITMAP +// * or SS_ICON, the label does not remember the font that is +// * set in WM_SETFONT. The fix is to remember the font and +// * return the font in WM_GETFONT. +// */ +// return super.WM_SETFONT (font = wParam, lParam); +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// LRESULT result = super.WM_SIZE (wParam, lParam); +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the resize +// * event. If this happens, end the processing of the +// * Windows message by returning the result of the +// * WM_SIZE message. +// */ +// if (isDisposed ()) return result; +// if ((style & SWT.SEPARATOR) != 0) { +// OS.InvalidateRect (handle, null, true); +// return result; +// } +// +// /* +// * Bug in Windows. For some reason, a label with +// * SS_BITMAP or SS_ICON and SS_CENTER does not redraw +// * properly when resized. Only the new area is drawn +// * and the old area is not cleared. The fix is to +// * force the redraw. +// * +// * NOTE: SS_BITMAP and SS_ICON are not single bit +// * masks so it is necessary to test for all of the +// * bits in these masks. +// */ +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP; +// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON; +// if (isBitmap || isIcon) { +// OS.InvalidateRect (handle, null, true); +// return result; +// } +// +// /* +// * Bug in Windows. For some reason, a label with +// * style SS_LEFT, SS_CENTER or SS_RIGHT does not +// * redraw the text in the new position when resized. +// * Note that SS_LEFTNOWORDWRAP does not have the +// * problem. The fix is to force the redraw. +// */ +// if ((style & (SWT.WRAP | SWT.CENTER | SWT.RIGHT)) != 0) { +// OS.InvalidateRect (handle, null, true); +// return result; +// } +// +// return result; +//} +// +//LRESULT wmColorChild (int wParam, int lParam) { +// LRESULT result = super.wmColorChild (wParam, lParam); +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// Control control = findThemeControl (); +// if (control != null) { +// OS.SetBkMode (wParam, OS.TRANSPARENT); +// RECT rect = new RECT (); +// OS.GetClientRect (control.handle, rect); +// OS.MapWindowPoints (control.handle, handle, rect, 2); +// control.drawThemeBackground (wParam, rect); +// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH)); +// } +// } +// return result; +//} +// +//LRESULT wmDrawChild (int wParam, int lParam) { +// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof); +// drawBackground (struct.hDC); +// if ((style & SWT.SHADOW_NONE) != 0) return null; +// RECT rect = new RECT (); +// int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER); +// int flags = OS.EDGE_ETCHED; +// if ((style & SWT.SHADOW_IN) != 0) flags = OS.EDGE_SUNKEN; +// if ((style & SWT.HORIZONTAL) != 0) { +// int bottom = struct.top + Math.max (lineWidth * 2, (struct.bottom - struct.top) / 2); +// OS.SetRect (rect, struct.left, struct.top, struct.right, bottom); +// OS.DrawEdge (struct.hDC, rect, flags, OS.BF_BOTTOM); +// } else { +// int right = struct.left + Math.max (lineWidth * 2, (struct.right - struct.left) / 2); +// OS.SetRect (rect, struct.left, struct.top, right, struct.bottom); +// OS.DrawEdge (struct.hDC, rect, flags, OS.BF_RIGHT); +// } +// return null; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java new file mode 100644 index 00000000000..faa60cd0c9c --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + +import java.awt.Container; +import java.awt.Dimension; +import java.util.EventObject; + +import javax.swing.SwingUtilities; +import javax.swing.event.HyperlinkEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CLink; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class represent a selectable + * user interface object that displays a text with + * links. + *

    + *

    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @since 3.1 + */ +public class Link extends Control { + + String text; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Link (Composite parent, int style) { + super (parent, style); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the control is selected. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection, typedListener); + addListener (SWT.DefaultSelection, typedListener); +} + +void createHandleInit() { + super.createHandleInit(); + state |= THEME_BACKGROUND; +} + +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget (); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + isAdjustingSize = true; + } + }); + Dimension size = handle.getSize(); + if(wHint == SWT.DEFAULT) { + handle.setSize(((CLink)handle).getPreferredWidth(), 0); + } else { + handle.setSize(wHint, 0); + } + Point point = super.computeSize (wHint, hHint, changed); + handle.setSize(size); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + isAdjustingSize = false; + } + }); + return point; +} + +Container createHandle () { + return (Container)CLink.Factory.newInstance(this, style); +} + +String getNameText () { + return getText (); +} + +/** + * Returns the receiver's text, which will be an empty + * string if it has never been set. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + return text == null? "": text; +} + +boolean mnemonicHit (char key) { + Composite control = this.parent; + while (control != null) { + Control [] children = control._getChildren (); + int index = 0; + while (index < children.length) { + if (children [index] == this) break; + index++; + } + index++; + if (index < children.length) { + if (children [index].setFocus ()) return true; + } + control = control.parent; + } + return false; +} + +boolean mnemonicMatch (char key) { + char mnemonic = findMnemonic (getText ()); + if (mnemonic == '\0') return false; + return Character.toUpperCase (key) == Character.toUpperCase (mnemonic); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection, listener); +} + +/** + * Sets the receiver's text. + *

    + * The string can contain both regular text and hyperlinks. A hyperlink + * is delimited by an anchor tag, <A> and </A>. Within an + * anchor, a single HREF attribute is supported. When a hyperlink is + * selected, the text field of the selection event contains either the + * text of the hyperlink or the value of its HREF, if one was specified. + * In the rare case of identical hyperlinks within the same string, the + * HREF tag can be used to distinguish between them. The string may + * include the mnemonic character and line delimiters. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + checkWidget (); + this.text = string; + int mnemonicIndex = findMnemonicIndex(string); + if(mnemonicIndex > 0) { + String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&"); + string = s + string.substring(mnemonicIndex).replaceAll("&&", "&"); +// mnemonicIndex -= mnemonicIndex - 1 - s.length(); +// mnemonicIndex--; + } else { + string = string.replaceAll("&&", "&"); + } + ((CLink)handle).setLinkText(string); +} + +public void processEvent(EventObject e) { + if(e instanceof HyperlinkEvent) { + if(!hooks(SWT.Selection)) { super.processEvent(e); return; } + } else { + super.processEvent(e); + return; + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof HyperlinkEvent) { + Event event = new Event(); + event.text = ((HyperlinkEvent)e).getDescription(); + sendEvent(SWT.Selection, event); + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java new file mode 100644 index 00000000000..f19861321fe --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java @@ -0,0 +1,1031 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.util.EventObject; + +import javax.swing.event.ListSelectionEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.internal.swing.CList; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class represent a selectable user interface + * object that displays a list of strings and issues notificiation + * when a string selected. A list may be single or multi select. + *

    + *

    + *
    Styles:
    + *
    SINGLE, MULTI
    + *
    Events:
    + *
    Selection, DefaultSelection
    + *
    + *

    + * Note: Only one of SINGLE and MULTI may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class List extends Scrollable { + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SINGLE + * @see SWT#MULTI + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public List (Composite parent, int style) { + super (parent, checkStyle (style)); +} +/** + * Adds the argument to the end of the receiver's list. + * + * @param string the new item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String,int) + */ +public void add (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + ((CList)handle).addElement(string); +} +/** + * Adds the argument to the receiver's list at the given + * zero-relative index. + *

    + * Note: To add an item at the end of the list, use the + * result of calling getItemCount() as the + * index or use add(String). + *

    + * + * @param string the new item + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String) + */ +public void add (String string, int index) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if (index == -1) error (SWT.ERROR_INVALID_RANGE); + int count = getItemCount(); + if (index < 0 || count < index) error (SWT.ERROR_INVALID_RANGE); + ((CList)handle).addElement(string); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's selection changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the selection changes. + * widgetDefaultSelected is typically called when an item is double-clicked. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0); +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. Indices that are out + * of range and duplicate indices are ignored. + * + * @param indices the array of indices for the items to deselect + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the set of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselect (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + int length = indices.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void deselect (int index) { + checkWidget (); + ((CList)handle).removeSelectionInterval(index, index); +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. The range of the + * indices is inclusive. Indices that are out of range are ignored. + * + * @param start the start index of the items to deselect + * @param end the end index of the items to deselect + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselect (int start, int end) { + checkWidget (); + ((CList)handle).removeSelectionInterval(start, end); +} + +/** + * Deselects all selected items in the receiver. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselectAll () { + checkWidget (); + int count = getItemCount(); + if(count == 0) return; + ((CList)handle).removeSelectionInterval(0, count - 1); +} + +/** + * Returns the zero-relative index of the item which currently + * has the focus in the receiver, or -1 if no item has focus. + * + * @return the index of the selected item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getFocusIndex () { + checkWidget (); + return ((CList)handle).getFocusIndex(); +// int result = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); +// if (result == 0) { +// int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0); +// if (count == 0) return -1; +// } +// return result; +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getItem (int index) { + checkWidget (); + if(index < 0) { + error (SWT.ERROR_INVALID_RANGE); + } + int count = getItemCount(); + if (index < 0 || count <= index) error (SWT.ERROR_INVALID_RANGE); + return (String)((CList)handle).getElementAt(index); +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return ((CList)handle).getItemCount(); +} + +/** + * Returns the height of the area which would be used to + * display one of the items in the list. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemHeight () { + checkWidget (); + java.awt.Rectangle bounds = ((CList)handle).getCellBounds(0); + // TODO: find another way to get a default value. + if(bounds == null) return 16; + return bounds.height; +// int result = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0); +// if (result == OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT); +// return result; +} + +/** + * Returns a (possibly empty) array of Strings which + * are the items in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver's list + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String [] getItems () { + checkWidget (); + int count = getItemCount (); + String [] result = new String [count]; + for (int i=0; iStrings that are currently + * selected in the receiver. The order of the items is unspecified. + * An empty array indicates that no items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return an array representing the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String [] getSelection () { + checkWidget (); + int [] indices = getSelectionIndices (); + String [] result = new String [indices.length]; + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public int getSelectionCount () { + checkWidget (); + int min = ((CList)handle).getMinSelectionIndex(); + if(min == -1) { + return 0; + } + return ((CList)handle).getMaxSelectionIndex() - min + 1; +} + +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver, or -1 if no item is selected. + * + * @return the index of the selected item or -1 + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionIndex () { + checkWidget (); + return ((CList)handle).getMinSelectionIndex(); +} + +/** + * Returns the zero-relative indices of the items which are currently + * selected in the receiver. The order of the indices is unspecified. + * The array is empty if no items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return the array of indices of the selected items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int [] getSelectionIndices () { + checkWidget (); + return ((CList)handle).getSelectionIndices(); +} + +/** + * Returns the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items are + * scrolled or new items are added or removed. + * + * @return the index of the top item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopIndex () { + checkWidget (); + return ((CList)handle).getFirstVisibleIndex(); +} + +/** + * Gets the index of an item. + *

    + * The list is searched starting at 0 until an + * item is found that is equal to the search item. + * If no item is found, -1 is returned. Indexing + * is zero based. + * + * @param string the search item + * @return the index of the item + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (String string) { + return indexOf (string, 0); +} + +/** + * Searches the receiver's list starting at the given, + * zero-relative index until an item is found that is equal + * to the argument, and returns the index of that item. If + * no item is found or the starting index is out of range, + * returns -1. + * + * @param string the search item + * @param start the zero-relative index at which to start the search + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (String string, int start) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + return ((CList)handle).indexOf(string, start); +} + +/** + * Returns true if the item is selected, + * and false otherwise. Indices out of + * range are ignored. + * + * @param index the index of the item + * @return the visibility state of the item at the index + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean isSelected (int index) { + checkWidget (); + return ((CList)handle).isSelectedIndex(index); +} + +/** + * Removes the items from the receiver at the given + * zero-relative indices. + * + * @param indices the array of indices of the items + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    • ERROR_NULL_ARGUMENT - if the indices array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + if (indices.length == 0) return; + int [] newIndices = new int [indices.length]; + System.arraycopy (indices, 0, newIndices, 0, indices.length); + sort (newIndices); + int start = newIndices [newIndices.length - 1], end = newIndices [0]; + int count = getItemCount(); + if (start < 0 || start > end || end >= count) error (SWT.ERROR_INVALID_RANGE); + CList cList = (CList)handle; + for(int i=newIndices.length-1; i>=0; i--) { + cList.removeElementAt(newIndices[i]); + } +} + +/** + * Removes the item from the receiver at the given + * zero-relative index. + * + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int index) { + checkWidget (); + int count = getItemCount(); + if (index < 0 || count <= index) error (SWT.ERROR_INVALID_RANGE); + ((CList)handle).removeElementAt(index); +} + +/** + * Removes the items from the receiver which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int start, int end) { + checkWidget (); + if (start > end) return; + int count = getItemCount(); + if (start < 0 || start > end || end >= count) error (SWT.ERROR_INVALID_RANGE); + ((CList)handle).removeRange(start, end); +} + +/** + * Searches the receiver's list starting at the first item + * until an item is found that is equal to the argument, + * and removes that item from the list. + * + * @param string the item to remove + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the string is not found in the list
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + int index = indexOf (string, 0); + if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT); + remove (index); +} + +/** + * Removes all of the items from the receiver. + *

    + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void removeAll () { + checkWidget (); + ((CList)handle).removeAllElements(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's selection changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +boolean isAdjustingSelection; + +/** + * Selects the items at the given zero-relative indices in the receiver. + * The current selection is not cleared before the new items are selected. + *

    + * If the item at a given index is not selected, it is selected. + * If the item at a given index was already selected, it remains selected. + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + * + * @param indices the array of indices for the items to select + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see List#setSelection(int[]) + */ +public void select (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + int length = indices.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + isAdjustingSelection = true; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void select (int index) { + checkWidget (); + isAdjustingSelection = true; + ((CList)handle).addSelectionInterval(index, index); + isAdjustingSelection = false; +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is not cleared before the new items are selected. + *

    + * If an item in the given range is not selected, it is selected. + * If an item in the given range was already selected, it remains selected. + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + * + * @param start the start of the range + * @param end the end of the range + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see List#setSelection(int,int) + */ +public void select (int start, int end) { + checkWidget (); + if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return; + int count = getItemCount(); + if (count == 0 || start >= count) return; + isAdjustingSelection = true; + start = Math.max (0, start); + end = Math.min (end, count - 1); + ((CList)handle).addSelectionInterval(start, end); + isAdjustingSelection = false; +} + +/** + * Selects all of the items in the receiver. + *

    + * If the receiver is single-select, do nothing. + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void selectAll () { + checkWidget (); + if ((style & SWT.SINGLE) != 0) return; + int count = getItemCount(); + if(count == 0) return; + isAdjustingSelection = true; + ((CList)handle).setSelectionInterval(0, count - 1); + isAdjustingSelection = false; +} + +/** + * Sets the text of the item in the receiver's list at the given + * zero-relative index to the string argument. This is equivalent + * to remove'ing the old item at the index, and then + * add'ing the new item at that index. + * + * @param index the index for the item + * @param string the new text for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItem (int index, String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + ((CList)handle).setElementAt(string, index); +} + +/** + * Sets the receiver's items to be the given array of items. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the items array is null
    • + *
    • ERROR_INVALID_ARGUMENT - if an item in the items array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItems (String [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; i + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + * + * @param indices the indices of the items to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see List#deselectAll() + * @see List#select(int[]) + */ +public void setSelection(int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + deselectAll (); + int length = indices.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + isAdjustingSelection = true; + for(int i=0; i + * Items that are not in the receiver are ignored. + * If the receiver is single-select and multiple items are specified, + * then all items are ignored. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of items is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see List#deselectAll() + * @see List#select(int[]) + * @see List#setSelection(int[]) + */ +public void setSelection (String [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + isAdjustingSelection = true; + deselectAll (); + int length = items.length; + if (length != 0 && ((style & SWT.SINGLE) == 0 || length <= 1)) { + ((CList)handle).setSelectedElements(items); + } + isAdjustingSelection = false; +} + +/** + * Selects the item at the given zero-relative index in the receiver. + * If the item at the index was already selected, it remains selected. + * The current selection is first cleared, then the new item is selected. + * Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @see List#deselectAll() + * @see List#select(int) + */ +public void setSelection (int index) { + checkWidget (); + isAdjustingSelection = true; + ((CList)handle).setSelectionInterval(index, index); + isAdjustingSelection = false; +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is cleared before the new items are selected. + *

    + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + * + * @param start the start index of the items to select + * @param end the end index of the items to select + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see List#deselectAll() + * @see List#select(int,int) + */ +public void setSelection (int start, int end) { + checkWidget (); + deselectAll (); + if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return; + int count = getItemCount(); + if (count == 0 || start >= count) return; + isAdjustingSelection = true; + start = Math.max (0, start); + end = Math.min (end, count - 1); + ((CList)handle).setSelectionInterval(start, end); + isAdjustingSelection = false; +} + +/** + * Sets the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items + * are scrolled or new items are added and removed. + * + * @param index the index of the top item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTopIndex (int index) { + checkWidget (); + ((CList)handle).setFirstVisibleIndex(index); +} + +/** + * Shows the selection. If the selection is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the selection is visible. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void showSelection () { + checkWidget (); + ((CList)handle).showSelection(); +} + +public void processEvent(EventObject e) { + if(e instanceof ListSelectionEvent) { + if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof ListSelectionEvent) { + if(!((ListSelectionEvent)e).getValueIsAdjusting()) { + sendEvent(SWT.Selection); + } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case ActionEvent.ACTION_PERFORMED: + sendEvent(SWT.DefaultSelection); + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java new file mode 100644 index 00000000000..1764119a8ad --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java @@ -0,0 +1,1179 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Component; +import java.awt.MouseInfo; +import java.util.ArrayList; + +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.HelpListener; +import org.eclipse.swt.events.MenuListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class are user interface objects that contain + * menu items. + *
    + *
    Styles:
    + *
    BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP
    + *
    LEFT_TO_RIGHT, RIGHT_TO_LEFT
    + *
    Events:
    + *
    Help, Hide, Show
    + *
    + *

    + * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified. + * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class Menu extends Widget { + /** + * the handle to the OS resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public JComponent handle; + +// int x, y, hwndCB, id0, id1; + int x, y; + boolean hasLocation; + MenuItem cascade; + Decorations parent; +// ImageList imageList; + +// /* Resource ID for SHMENUBARINFO */ +// static final int ID_PPC = 100; +// +// /* SmartPhone SoftKeyBar resource ids */ +// static final int ID_SPMM = 102; +// static final int ID_SPBM = 103; +// static final int ID_SPMB = 104; +// static final int ID_SPBB = 105; +// static final int ID_SPSOFTKEY0 = 106; +// static final int ID_SPSOFTKEY1 = 107; + +/** + * Constructs a new instance of this class given its parent, + * and sets the style for the instance so that the instance + * will be a popup menu on the given parent's shell. + * + * @param parent a control which will be the parent of the new instance (cannot be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#POP_UP + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Menu (Control parent) { + this (checkNull (parent).menuShell (), SWT.POP_UP); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Decorations) and a style value + * describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a decorations control which will be the parent of the new instance (cannot be null) + * @param style the style of menu to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BAR + * @see SWT#DROP_DOWN + * @see SWT#POP_UP + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Menu (Decorations parent, int style) { + this (parent, checkStyle (style), null); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Menu) and sets the style + * for the instance so that the instance will be a drop-down + * menu on the given parent's parent. + * + * @param parentMenu a menu which will be the parent of the new instance (cannot be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Menu (Menu parentMenu) { + this (checkNull (parentMenu).parent, SWT.DROP_DOWN); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a MenuItem) and sets the style + * for the instance so that the instance will be a drop-down + * menu on the given parent's parent menu. + * + * @param parentItem a menu item which will be the parent of the new instance (cannot be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Menu (MenuItem parentItem) { + this (checkNull (parentItem).parent); +} + +Menu (Decorations parent, int style, JMenuBar handle) { + super (parent, checkStyle (style)); + this.parent = parent; + this.handle = handle; + createWidget (); +} + +//void _setVisible (boolean visible) { +// if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return; +// int hwndParent = parent.handle; +// if (visible) { +// int flags = OS.TPM_LEFTBUTTON; +// if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) flags |= OS.TPM_RIGHTBUTTON; +// if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.TPM_RIGHTALIGN; +// if ((parent.style & SWT.MIRRORED) != 0) { +// flags &= ~OS.TPM_RIGHTALIGN; +// if ((style & SWT.LEFT_TO_RIGHT) != 0) flags |= OS.TPM_RIGHTALIGN; +// } +// int nX = x, nY = y; +// if (!hasLocation) { +// int pos = OS.GetMessagePos (); +// nX = (short) (pos & 0xFFFF); +// nY = (short) (pos >> 16); +// } +// /* +// * Feature in Windows. It is legal use TrackPopupMenu() +// * to display an empty menu as long as menu items are added +// * inside of WM_INITPOPUPMENU. If no items are added, then +// * TrackPopupMenu() fails and does not send an indication +// * that the menu has been closed. This is not strictly a +// * bug but leads to unwanted behavior when application code +// * assumes that every WM_INITPOPUPMENU will eventually result +// * in a WM_MENUSELECT, wParam=0xFFFF0000, lParam=0 to indicate +// * that the menu has been closed. The fix is to detect the +// * case when TrackPopupMenu() fails and the number of items in +// * the menu is zero and issue a fake WM_MENUSELECT. +// */ +// boolean success = OS.TrackPopupMenu (handle, flags, nX, nY, 0, hwndParent, null); +// if (!success && GetMenuItemCount (handle) == 0) { +// OS.SendMessage (hwndParent, OS.WM_MENUSELECT, 0xFFFF0000, 0); +// } +// } else { +// OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0); +// } +//} + +/** + * Adds the listener to the collection of listeners who will + * be notified when help events are generated for the control, + * by sending it one of the messages defined in the + * HelpListener interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #removeHelpListener + */ +public void addHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Help, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when menus are hidden or shown, by sending it + * one of the messages defined in the MenuListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MenuListener + * @see #removeMenuListener + */ +public void addMenuListener (MenuListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Hide,typedListener); + addListener (SWT.Show,typedListener); +} + +static Control checkNull (Control control) { + if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return control; +} + +static Menu checkNull (Menu menu) { + if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return menu; +} + +static MenuItem checkNull (MenuItem item) { + if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return item; +} + +static int checkStyle (int style) { + return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0); +} + +void createHandle () { + if (handle != null) return; + if ((style & SWT.BAR) != 0) { + JMenuBar menuBar = new JMenuBar(); + handle = menuBar; + } else if((style & SWT.POP_UP) != 0) { + JPopupMenu popup = new JPopupMenu(); + // TODO: check if a component listener for visibility is needed + popup.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuCanceled(PopupMenuEvent e) { + } + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + if(!hooks(SWT.Hide)) return; + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + Event event = new Event(); + event.widget = Menu.this; + sendEvent(SWT.Hide, event); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + if(!hooks(SWT.Show)) return; + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + Event event = new Event(); + event.widget = Menu.this; + sendEvent(SWT.Show, event); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + }); + handle = popup; + } else if((style & SWT.DROP_DOWN) != 0) { + handle = new JMenu(); + } +} + +void createItem (MenuItem item, int index) { + int count = handle.getComponentCount(); + if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE); + display.addMenuItem (item); + handle.add(item.handle, index); +// handle.invalidate(); +// handle.validate(); +// handle.repaint(); + +// if (!success) { +// display.removeMenuItem (item); +// error (SWT.ERROR_ITEM_NOT_ADDED); +// } +// redraw (); +} + +void createWidget () { + checkOrientation (parent); + createHandle (); + parent.addMenu (this); +} + +///* +//* Currently not used. +//*/ +//int defaultBackground () { +// return OS.GetSysColor (OS.COLOR_MENU); +//} +// +///* +//* Currently not used. +//*/ +//int defaultForeground () { +// return OS.GetSysColor (OS.COLOR_MENUTEXT); +//} +// +//void destroyAccelerators () { +// parent.destroyAccelerators (); +//} + +void destroyItem (MenuItem item) { + java.awt.Component comp = item.handle.getParent(); + handle.remove(item.handle); + if(comp instanceof JPopupMenu) { + ((JPopupMenu)comp).pack(); + } +// redraw (); +} + +void destroyWidget () { +// int hMenu = handle, hCB = hwndCB; + releaseHandle (); +// if (OS.IsWinCE && hCB != 0) { +// OS.CommandBar_Destroy (hCB); +// } else { +// if (hMenu != 0) OS.DestroyMenu (hMenu); +// } +} + +void fixMenus (Decorations newParent) { + MenuItem [] items = getItems (); + for (int i=0; i + * Note that the bounds of a menu or menu item are undefined when + * the menu is not visible. This is because most platforms compute + * the bounds of a menu dynamically just before it is displayed. + *

    + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +/*public*/ Rectangle getBounds () { + checkWidget (); + java.awt.Rectangle bounds = handle.getBounds(); + return new Rectangle (bounds.x, bounds.y, bounds.width, bounds.height); +// if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0); +// if ((style & SWT.BAR) != 0) { +// if (parent.menuBar != this) { +// return new Rectangle (0, 0, 0, 0); +// } +// int hwndShell = parent.handle; +// MENUBARINFO info = new MENUBARINFO (); +// info.cbSize = MENUBARINFO.sizeof; +// if (OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 0, info)) { +// int width = info.right - info.left; +// int height = info.bottom - info.top; +// return new Rectangle (info.left, info.top, width, height); +// } +// } else { +// int count = GetMenuItemCount (handle); +// if (count != 0) { +// RECT rect1 = new RECT (); +// if (OS.GetMenuItemRect (0, handle, 0, rect1)) { +// RECT rect2 = new RECT (); +// if (OS.GetMenuItemRect (0, handle, count - 1, rect2)) { +// int x = rect1.left - 2, y = rect1.top - 2; +// int width = (rect2.right - rect2.left) + 4; +// int height = (rect2.bottom - rect1.top) + 4; +// return new Rectangle (x, y, width, height); +// } +// } +// } +// } +// return new Rectangle (0, 0, 0, 0); +} + +/** + * Returns the default menu item or null if none has + * been previously set. + * + * @return the default menu item. + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public MenuItem getDefaultItem () { + checkWidget (); + // TODO: implement that? +// if (OS.IsWinCE) return null; +// int id = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED); +// if (id == -1) return null; +// MENUITEMINFO info = new MENUITEMINFO (); +// info.cbSize = MENUITEMINFO.sizeof; +// info.fMask = OS.MIIM_ID; +// if (OS.GetMenuItemInfo (handle, id, false, info)) { +// return display.getMenuItem (info.wID); +// } + return null; +} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled menu is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public boolean getEnabled () { + checkWidget (); + return handle.isEnabled(); +// return (state & DISABLED) == 0; +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public MenuItem getItem (int index) { + checkWidget (); + if(index < 0) error (SWT.ERROR_INVALID_RANGE); + int result = 0; + int count = handle.getComponentCount(); + if(index > count) error (SWT.ERROR_INVALID_RANGE); + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public int getItemCount () { + checkWidget (); + int count = handle.getComponentCount(); + int result = 0; + for(int i=0; iMenuItems which + * are the items in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public MenuItem [] getItems () { + checkWidget (); + int count = handle.getComponentCount(); + java.util.List arrayList = new ArrayList(count); + for(int i=0; i 0) { + for (int i=0; iDecorations. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Decorations getParent () { + checkWidget (); + return parent; +} + +/** + * Returns the receiver's parent item, which must be a + * MenuItem or null when the receiver is a + * root. + * + * @return the receiver's parent item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public MenuItem getParentItem () { + checkWidget (); + return cascade; +} + +/** + * Returns the receiver's parent item, which must be a + * Menu or null when the receiver is a + * root. + * + * @return the receiver's parent item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getParentMenu () { + checkWidget (); + if (cascade != null) return cascade.parent; + return null; +} + +/** + * Returns the receiver's shell. For all controls other than + * shells, this simply returns the control's nearest ancestor + * shell. Shells return themselves, even if they are children + * of other shells. + * + * @return the receiver's shell + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getParent + */ +public Shell getShell () { + checkWidget (); + return parent.getShell (); +} + +/** + * Returns true if the receiver is visible, and + * false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget (); + if(!handle.isVisible()) { + return false; + } + if ((style & SWT.BAR) != 0) { + return this == parent.menuShell ().menuBar; + } + if ((style & SWT.POP_UP) != 0) { + Menu [] popups = display.popups; + if (popups == null) return false; + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the string is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (MenuItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + if (item.parent != this) return -1; + int componentCount = handle.getComponentCount(); + for(int i=0; itrue if the receiver is enabled and all + * of the receiver's ancestors are enabled, and false + * otherwise. A disabled menu is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public boolean isEnabled () { + checkWidget (); + Menu parentMenu = getParentMenu (); + if (parentMenu == null) return getEnabled (); + return getEnabled () && parentMenu.isEnabled (); +} + +/** + * Returns true if the receiver is visible and all + * of the receiver's ancestors are visible and false + * otherwise. + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + */ +public boolean isVisible () { + checkWidget (); + return getVisible (); +} + +//void redraw () { +// if (!isVisible ()) return; +// if ((style & SWT.BAR) != 0) { +// display.addBar (this); +// } else { +// update (); +// } +//} + +void releaseHandle () { + super.releaseHandle (); + handle = null; +} + +void releaseChildren (boolean destroy) { + MenuItem [] items = getItems (); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #addHelpListener + */ +public void removeHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Help, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the menu events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see MenuListener + * @see #addMenuListener + */ +public void removeMenuListener (MenuListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Hide, listener); + eventTable.unhook (SWT.Show, listener); +} + +/** + * Sets the default menu item to the argument or removes + * the default emphasis when the argument is null. + * + * @param item the default menu item or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the menu item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDefaultItem (MenuItem item) { + // TODO: implement that? +// checkWidget (); +// int newID = -1; +// if (item != null) { +// if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); +// if (item.parent != this) return; +// newID = item.id; +// } +// if (OS.IsWinCE) return; +// int oldID = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED); +// if (newID == oldID) return; +// OS.SetMenuDefaultItem (handle, newID, OS.MF_BYCOMMAND); +// redraw (); +} + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. A disabled menu is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (boolean enabled) { + checkWidget (); + handle.setEnabled(enabled); +} + +/** + * Sets the location of the receiver, which must be a popup, + * to the point specified by the arguments which are relative + * to the display. + *

    + * Note that this is different from most widgets where the + * location of the widget is relative to the parent. + *

    + * Note that the platform window manager ultimately has control + * over the location of popup menus. + *

    + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (int x, int y) { + checkWidget (); + if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return; + this.x = x; + this.y = y; + hasLocation = true; +} + +/** + * Sets the location of the receiver, which must be a popup, + * to the point specified by the argument which is relative + * to the display. + *

    + * Note that this is different from most widgets where the + * location of the widget is relative to the parent. + *

    + * Note that the platform window manager ultimately has control + * over the location of popup menus. + *

    + * + * @param location the new location for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public void setLocation (Point location) { + checkWidget (); + if (location == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + setLocation (location.x, location.y); +} + +/** + * Marks the receiver as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget (); + if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return; + JPopupMenu popup = (JPopupMenu)handle; + if (visible) { + display.addPopup (this); + java.awt.Point location; + if(hasLocation) { + location = new java.awt.Point(x, y); + } else { + if(Compatibility.IS_JAVA_5_OR_GREATER) { + location = MouseInfo.getPointerInfo().getLocation(); + } else { + location = new java.awt.Point(0, 0); + } + } + Shell shell = getShell(); + if(shell != null) { + Component shellHandle = shell.handle; + if(shellHandle.isShowing()) { + SwingUtilities.convertPointFromScreen(location, shellHandle); + popup.show(shellHandle, location.x, location.y); + return; + } + } + popup.show(null, location.x, location.y); + } else { + display.removePopup (this); + popup.setVisible(false); +// _setVisible (false); + } +} + +//void update () { +// if (OS.IsPPC || OS.IsSP) return; +// if (OS.IsHPC) { +// /* +// * Each time a menu has been modified, the command menu bar +// * must be redrawn or it won't update properly. For example, +// * a submenu will not drop down. +// */ +// Menu menuBar = parent.menuBar; +// if (menuBar != null) { +// Menu menu = this; +// while (menu != null && menu != menuBar) { +// menu = menu.getParentMenu (); +// } +// if (menu == menuBar) { +// OS.CommandBar_DrawMenuBar (menuBar.hwndCB, 0); +// OS.CommandBar_Show (menuBar.hwndCB, true); +// } +// } +// return; +// } +// if (OS.IsWinCE) return; +// if ((style & SWT.BAR) != 0) { +// if (this == parent.menuBar) OS.DrawMenuBar (parent.handle); +// return; +// } +// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) { +// return; +// } +// boolean hasCheck = false, hasImage = false; +// MenuItem [] items = getItems (); +// for (int i=0; i + *
    Styles:
    + *
    CHECK, CASCADE, PUSH, RADIO, SEPARATOR
    + *
    Events:
    + *
    Arm, Help, Selection
    + * + *

    + * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR + * may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class MenuItem extends Item { + Menu parent, menu; +// int id, accelerator; + int accelerator; + JComponent handle; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Menu) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a menu control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#CHECK + * @see SWT#CASCADE + * @see SWT#PUSH + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public MenuItem (Menu parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + createHandle(); + parent.createItem (this, parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Menu), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a menu control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#CHECK + * @see SWT#CASCADE + * @see SWT#PUSH + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public MenuItem (Menu parent, int style, int index) { + super (parent, checkStyle (style)); + this.parent = parent; + createHandle(); + parent.createItem (this, index); +} + +MenuItem (Menu parent, Menu menu, int style, int index) { + super (parent, checkStyle (style)); + this.parent = parent; + this.menu = menu; + if (menu != null) menu.cascade = this; + display.addMenuItem (this); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the arm events are generated for the control, by sending + * it one of the messages defined in the ArmListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ArmListener + * @see #removeArmListener + */ +public void addArmListener (ArmListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Arm, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the help events are generated for the control, by sending + * it one of the messages defined in the HelpListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #removeHelpListener + */ +public void addHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Help, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the menu item is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the stateMask field of the event object is valid. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.CASCADE, 0); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +//void fillAccel (ACCEL accel) { +// accel.fVirt = 0; +// accel.cmd = accel.key = 0; +// if (accelerator == 0 || !getEnabled ()) return; +// int fVirt = OS.FVIRTKEY; +// int key = accelerator & SWT.KEY_MASK; +// int vKey = Display.untranslateKey (key); +// if (vKey != 0) { +// key = vKey; +// } else { +// switch (key) { +// /* +// * Bug in Windows. For some reason, VkKeyScan +// * fails to map ESC to VK_ESCAPE and DEL to +// * VK_DELETE. The fix is to map these keys +// * as a special case. +// */ +// case 27: key = OS.VK_ESCAPE; break; +// case 127: key = OS.VK_DELETE; break; +// default: { +// key = Display.wcsToMbcs ((char) key); +// if (key == 0) return; +// if (OS.IsWinCE) { +// key = OS.CharUpper ((short) key); +// } else { +// vKey = OS.VkKeyScan ((short) key) & 0xFF; +// if (vKey == -1) { +// fVirt = 0; +// } else { +// key = vKey; +// } +// } +// } +// } +// } +// accel.key = (short) key; +// accel.cmd = (short) id; +// accel.fVirt = (byte) fVirt; +// if ((accelerator & SWT.ALT) != 0) accel.fVirt |= OS.FALT; +// if ((accelerator & SWT.SHIFT) != 0) accel.fVirt |= OS.FSHIFT; +// if ((accelerator & SWT.CONTROL) != 0) accel.fVirt |= OS.FCONTROL; +//} + +void fixMenus (Decorations newParent) { + if (menu != null) menu.fixMenus (newParent); +} + +/** + * Returns the widget accelerator. An accelerator is the bit-wise + * OR of zero or more modifier masks and a key. Examples: + * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2. + * The default value is zero, indicating that the menu item does + * not have an accelerator. + * + * @return the accelerator or 0 + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAccelerator () { + checkWidget (); + return accelerator; +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent (or its display if its parent is null). + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +/*public*/ Rectangle getBounds () { + checkWidget (); + java.awt.Rectangle bounds = handle.getBounds(); + return new Rectangle (bounds.x, bounds.y, bounds.width, bounds.height); +// if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0); +// int index = parent.indexOf (this); +// if (index == -1) return new Rectangle (0, 0, 0, 0); +// if ((parent.style & SWT.BAR) != 0) { +// Decorations shell = parent.parent; +// if (shell.menuBar != parent) { +// return new Rectangle (0, 0, 0, 0); +// } +// int hwndShell = shell.handle; +// MENUBARINFO info1 = new MENUBARINFO (); +// info1.cbSize = MENUBARINFO.sizeof; +// if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 1, info1)) { +// return new Rectangle (0, 0, 0, 0); +// } +// MENUBARINFO info2 = new MENUBARINFO (); +// info2.cbSize = MENUBARINFO.sizeof; +// if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, index + 1, info2)) { +// return new Rectangle (0, 0, 0, 0); +// } +// int x = info2.left - info1.left; +// int y = info2.top - info1.top; +// int width = info1.right - info1.left; +// int height = info1.bottom - info1.top; +// return new Rectangle (x, y, width, height); +// } else { +// int hMenu = parent.handle; +// RECT rect1 = new RECT (); +// if (!OS.GetMenuItemRect (0, hMenu, 0, rect1)) { +// return new Rectangle (0, 0, 0, 0); +// } +// RECT rect2 = new RECT (); +// if (!OS.GetMenuItemRect (0, hMenu, index, rect2)) { +// return new Rectangle (0, 0, 0, 0); +// } +// int x = rect2.left - rect1.left + 2; +// int y = rect2.top - rect1.top + 2; +// int width = rect2.right - rect2.left; +// int height = rect2.bottom - rect2.top; +// return new Rectangle (x, y, width, height); +// } +} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled menu item is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public boolean getEnabled () { + checkWidget (); + return handle.isEnabled(); +} + +/** + * Returns the receiver's cascade menu if it has one or null + * if it does not. Only CASCADE menu items can have + * a pull down menu. The sequence of key strokes, button presses + * and/or button releases that are used to request a pull down + * menu is platform specific. + * + * @return the receiver's menu + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getMenu () { + checkWidget (); + return menu; +} + +String getNameText () { + if ((style & SWT.SEPARATOR) != 0) return "|"; + return super.getNameText (); +} + +/** + * Returns the receiver's parent, which must be a Menu. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getParent () { + checkWidget (); + return parent; +} + +/** + * Returns true if the receiver is selected, + * and false otherwise. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. + * + * @return the selection state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getSelection () { + checkWidget (); + if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false; + return ((AbstractButton)handle).isSelected(); +} + +/** + * Returns true if the receiver is enabled and all + * of the receiver's ancestors are enabled, and false + * otherwise. A disabled menu item is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public boolean isEnabled () { + return getEnabled () && parent.isEnabled (); +} + +void releaseChildren (boolean destroy) { + if (menu != null) { + menu.release (false); + menu = null; + } + super.releaseChildren (destroy); +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseMenu () { + setMenu (null); + menu = null; +} + +void releaseParent () { + super.releaseParent (); + if (menu != null) menu.dispose (); + menu = null; +} + +void releaseWidget () { + super.releaseWidget (); +// if (accelerator != 0) { +// parent.destroyAccelerators (); +// } + accelerator = 0; + display.removeMenuItem (this); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the arm events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ArmListener + * @see #addArmListener + */ +public void removeArmListener (ArmListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Arm, listener); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the help events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #addHelpListener + */ +public void removeHelpListener (HelpListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Help, listener); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +void selectRadio () { + int index = 0; + MenuItem [] items = parent.getItems (); + while (index < items.length && items [index] != this) index++; + int i = index - 1; + while (i >= 0 && items [i].setRadioSelection (false)) --i; + int j = index + 1; + while (j < items.length && items [j].setRadioSelection (false)) j++; + setSelection (true); +} + +/** + * Sets the widget accelerator. An accelerator is the bit-wise + * OR of zero or more modifier masks and a key. Examples: + * SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2. + * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2. + * The default value is zero, indicating that the menu item does + * not have an accelerator. + * + * @param accelerator an integer that is the bit-wise OR of masks and a key + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAccelerator (int accelerator) { + checkWidget (); + if (this.accelerator == accelerator) return; + this.accelerator = accelerator; + int key = accelerator & SWT.KEY_MASK; + int vKey = Display.untranslateKey(key); + if(vKey != 0) { + key = vKey; + } + if(handle instanceof JMenu) { + ((JMenu)handle).setMnemonic(key); + } else { + int modifiers = 0; + if((accelerator & SWT.ALT) != 0) { + modifiers |= java.awt.event.KeyEvent.ALT_DOWN_MASK; + } + if((accelerator & SWT.SHIFT) != 0) { + modifiers |= java.awt.event.KeyEvent.SHIFT_DOWN_MASK; + } + if((accelerator & SWT.CONTROL) != 0) { + modifiers |= java.awt.event.KeyEvent.CTRL_DOWN_MASK; + } + ((JMenuItem)handle).setAccelerator(KeyStroke.getKeyStroke(key, modifiers)); + } +// parent.destroyAccelerators (); +} + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. A disabled menu item is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (boolean enabled) { + checkWidget (); + handle.setEnabled(enabled); +// parent.destroyAccelerators (); +// parent.redraw (); +} + +/** + * Sets the image the receiver will display to the argument. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept (for example, Windows NT). + *

    + * + * @param image the image to display + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget (); + if ((style & SWT.SEPARATOR) != 0) return; + super.setImage (image); + ImageIcon icon = null; + if (image != null && image.handle != null) { + icon = new ImageIcon (image.handle); + } + ((AbstractButton) handle).setIcon (icon); +// parent.redraw (); +} + +/** + * Sets the receiver's pull down menu to the argument. + * Only CASCADE menu items can have a + * pull down menu. The sequence of key strokes, button presses + * and/or button releases that are used to request a pull down + * menu is platform specific. + *

    + * Note: Disposing of a menu item that has a pull down menu + * will dispose of the menu. To avoid this behavior, set the + * menu to null before the menu item is disposed. + *

    + * + * @param menu the new pull down menu + * + * @exception IllegalArgumentException
      + *
    • ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu
    • + *
    • ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a CASCADE
    • + *
    • ERROR_INVALID_ARGUMENT - if the menu has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the menu is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMenu (Menu menu) { + checkWidget (); + /* Check to make sure the new menu is valid */ + if ((style & SWT.CASCADE) == 0) { + error (SWT.ERROR_MENUITEM_NOT_CASCADE); + } + if (menu != null) { + if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + if ((menu.style & SWT.DROP_DOWN) == 0) { + error (SWT.ERROR_MENU_NOT_DROP_DOWN); + } + if (menu.parent != parent.parent) { + error (SWT.ERROR_INVALID_PARENT); + } + } + if(!(handle instanceof JMenu)) { + JMenu popup = new JMenu() { + public void menuSelectionChanged(boolean isIncluded) { + super.menuSelectionChanged(isIncluded); + if(!isIncluded) return; + if(!hooks(SWT.Arm)) return; + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { +// Event event = new Event(); +// event.stateMask = Display.getInputState(); +// sendEvent(SWT.Arm, event); + sendEvent(SWT.Arm); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + }; + popup.getPopupMenu().addPopupMenuListener(new PopupMenuListener() { + public void popupMenuCanceled(PopupMenuEvent e) { + } + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + if(MenuItem.this.menu == null) return; + if(!MenuItem.this.menu.hooks(SWT.Hide)) return; + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + Event event = new Event(); + event.widget = MenuItem.this.menu; + MenuItem.this.menu.sendEvent(SWT.Hide, event); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + if(MenuItem.this.menu == null) return; + if(!MenuItem.this.menu.hooks(SWT.Show)) return; + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + Event event = new Event(); + event.widget = MenuItem.this.menu; + MenuItem.this.menu.sendEvent(SWT.Show, event); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + }); + Container p = handle.getParent(); + if(p != null) { + for(int i=p.getComponentCount()-1; i>=0; i--) { + if(p.getComponent(i) == handle) { + p.remove(handle); + p.add(popup, i); + if(p instanceof JComponent) { + ((JComponent)p).revalidate(); + } else { + p.invalidate(); + p.validate(); + } + p.repaint(); + break; + } + } + } + JMenuItem menuItem = (JMenuItem)handle; + popup.setText(menuItem.getText()); + popup.setMnemonic(menuItem.getMnemonic()); +// popup.setToolTipText(menuItem.getToolTipText()); + popup.setEnabled(menuItem.isEnabled()); + popup.setSelected(menuItem.isSelected()); + popup.setIcon(menuItem.getIcon()); + handle = popup; + } + JMenu menuHandle = (JMenu)handle; + JPopupMenu popupMenu = menuHandle.getPopupMenu(); + popupMenu.removeAll(); + /* Assign the new menu */ + Menu oldMenu = this.menu; + if (oldMenu == menu) return; + if (oldMenu != null) oldMenu.cascade = null; + this.menu = menu; + if (menu != null) { + menu.cascade = this; + Component[] components = ((JMenu)menu.handle).getPopupMenu().getComponents(); + for(int i=0; i + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. + * + * @param selected the new selection state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (boolean selected) { + checkWidget (); + if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return; + adjustSelection = true; + ((AbstractButton)handle).setSelected(selected); + adjustSelection = false; +// parent.redraw (); +} + +/** + * Sets the receiver's text. The string may include + * the mnemonic character and accelerator text. + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, a selection + * event occurs. On most platforms, the mnemonic appears + * underlined but may be emphasised in a platform specific + * manner. The mnemonic indicator character '&' can be + * escaped by doubling it in the string, causing a single + * '&' to be displayed. + *

    + *

    + * Accelerator text is indicated by the '\t' character. + * On platforms that support accelerator text, the text + * that follows the '\t' character is displayed to the user, + * typically indicating the key stroke that will cause + * the item to become selected. On most platforms, the + * accelerator text appears right aligned in the menu. + * Setting the accelerator text does not install the + * accelerator key sequence. The accelerator key sequence + * is installed using #setAccelerator. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setAccelerator + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.SEPARATOR) != 0) return; + if (text.equals (string)) return; + super.setText (string); + AbstractButton button = (AbstractButton)handle; + int index = findMnemonicIndex(string); + if(index != -1) { + button.setMnemonic(string.charAt(index)); + string = string.substring(0, index - 1) + string.substring(index); + } else { + button.setMnemonic('\0'); + } +// string = fixMnemonic (string); + // TODO: check what to do for cascade (CHECK, CASCADE, PUSH, RADIO and SEPARATOR) + index = string.lastIndexOf('\t'); + if(index != -1) { + string = string.substring(0, index); + } + button.setText(string); + java.awt.Component comp = button.getParent(); + if(comp instanceof javax.swing.JPopupMenu) { + ((javax.swing.JPopupMenu)comp).pack(); + } +// parent.redraw (); +} + +//int widgetStyle () { +// int bits = 0; +// Decorations shell = parent.parent; +// if ((shell.style & SWT.MIRRORED) != 0) { +// if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) { +// bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER; +// } +// } else { +// if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) { +// bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER; +// } +// } +// if ((style & SWT.SEPARATOR) != 0) return bits | OS.MFT_SEPARATOR; +// if ((style & SWT.RADIO) != 0) return bits | OS.MFT_RADIOCHECK; +// return bits | OS.MFT_STRING; +//} +// +//LRESULT wmCommandChild (int wParam, int lParam) { +// if ((style & SWT.CHECK) != 0) { +// setSelection (!getSelection ()); +// } else { +// if ((style & SWT.RADIO) != 0) { +// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) { +// setSelection (!getSelection ()); +// } else { +// selectRadio (); +// } +// } +// } +// Event event = new Event (); +// setInputState (event, SWT.Selection); +// postEvent (SWT.Selection, event); +// return null; +//} +// +//LRESULT wmDrawChild (int wParam, int lParam) { +// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof); +// if (image != null) { +// GCData data = new GCData(); +// data.device = display; +// GC gc = GC.win32_new (struct.hDC, data); +// /* +// * Bug in Windows. When a bitmap is included in the +// * menu bar, the HDC seems to already include the left +// * coordinate. The fix is to ignore this value when +// * the item is in a menu bar. +// */ +// int x = (parent.style & SWT.BAR) != 0 ? (OS.IsWin95 ? 4 : 2) : struct.left; +// gc.drawImage (image, x, struct.top + 2); +// gc.dispose (); +// } +// return null; +//} +// +//LRESULT wmMeasureChild (int wParam, int lParam) { +// MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT (); +// OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof); +// int width = 0, height = 0; +// if (image != null) { +// Rectangle rect = image.getBounds (); +// width = rect.width; +// height = rect.height; +// } else { +// /* +// * Bug in Windows. If a menu contains items that have +// * images and can be checked, Windows does not include +// * the width of the image and the width of the check when +// * computing the width of the menu. When the longest item +// * does not have an image, the label and the accelerator +// * text can overlap. The fix is to use SetMenuItemInfo() +// * to indicate that all items have a bitmap and then include +// * the width of the widest bitmap in WM_MEASURECHILD. +// */ +// MENUINFO lpcmi = new MENUINFO (); +// lpcmi.cbSize = MENUINFO.sizeof; +// lpcmi.fMask = OS.MIM_STYLE; +// int hMenu = parent.handle; +// OS.GetMenuInfo (hMenu, lpcmi); +// if ((lpcmi.dwStyle & OS.MNS_CHECKORBMP) == 0) { +// MenuItem [] items = parent.getItems (); +// for (int i=0; i + *
    Styles:
    + *
    ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING, ICON_WORKING
    + *
    OK, OK | CANCEL
    + *
    YES | NO, YES | NO | CANCEL
    + *
    RETRY | CANCEL
    + *
    ABORT | RETRY | IGNORE
    + *
    Events:
    + *
    (none)
    + * + *

    + * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, + * ICON_WARNING and ICON_WORKING may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class MessageBox extends Dialog { + String message = ""; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a shell which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public MessageBox (Shell parent) { + this (parent, SWT.OK | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + * + * @param parent a shell which will be the parent of the new instance + * @param style the style of dialog to construct + * + * @exception IllegalArgumentException

      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public MessageBox (Shell parent, int style) { + super (parent, checkStyle (style)); + checkSubclass (); +} + +static int checkStyle (int style) { + if ((style & (SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) == 0) style |= SWT.APPLICATION_MODAL; + int mask = (SWT.YES | SWT.NO | SWT.OK | SWT.CANCEL | SWT.ABORT | SWT.RETRY | SWT.IGNORE); + int bits = style & mask; + if (bits == SWT.OK || bits == SWT.CANCEL || bits == (SWT.OK | SWT.CANCEL)) return style; + if (bits == SWT.YES || bits == SWT.NO || bits == (SWT.YES | SWT.NO) || bits == (SWT.YES | SWT.NO | SWT.CANCEL)) return style; + if (bits == (SWT.RETRY | SWT.CANCEL) || bits == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) return style; + style = (style & ~mask) | SWT.OK; + return style; +} + +/** + * Returns the dialog's message, or an empty string if it does not have one. + * The message is a description of the purpose for which the dialog was opened. + * This message will be visible in the dialog while it is open. + * + * @return the message + */ +public String getMessage () { + return message; +} + +static final int MAX_WIDTH = 120; + +/** + * Makes the dialog visible and brings it to the front + * of the display. + * + * @return the ID of the button that was selected to dismiss the + * message box (e.g. SWT.OK, SWT.CANCEL, etc...) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the dialog has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
    • + *
    + */ +public int open () { + int messageType = JOptionPane.PLAIN_MESSAGE; + if ((style & SWT.ICON_ERROR) != 0) messageType = JOptionPane.ERROR_MESSAGE; + if ((style & SWT.ICON_INFORMATION) != 0) messageType = JOptionPane.INFORMATION_MESSAGE; + if ((style & SWT.ICON_QUESTION) != 0) messageType = JOptionPane.QUESTION_MESSAGE; + if ((style & SWT.ICON_WARNING) != 0) messageType = JOptionPane.WARNING_MESSAGE; + if ((style & SWT.ICON_WORKING) != 0) messageType = JOptionPane.INFORMATION_MESSAGE; + String[] messageTokens = this.message.split("\n"); + StringBuffer sb = new StringBuffer(this.message.length()); + for(int i=0; i 0) { + sb.append('\n'); + } + String token = messageTokens[i]; + if(token.length() > MAX_WIDTH) { + String[] subTokens = token.split(" "); + int count = 0; + for(int j=0; j 0 && count + subToken.length() > MAX_WIDTH) { + sb.append('\n'); + count = 0; + } + int splitCount = Math.max(0, (subToken.length() - 1)) / MAX_WIDTH + 1; + for(int k=0; k + *
  • ERROR_NULL_ARGUMENT - if the string is null
  • + * + */ +public void setMessage (String string) { + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + message = string; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java new file mode 100644 index 00000000000..62c517b47ee --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.swing.CProgressBar; + +/** + * Instances of the receiver represent is an unselectable + * user interface object that is used to display progress, + * typically in the form of a bar. + *
    + *
    Styles:
    + *
    SMOOTH, HORIZONTAL, VERTICAL, INDETERMINATE
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class ProgressBar extends Control { + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SMOOTH + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ProgressBar (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +static int checkStyle (int style) { + style |= SWT.NO_FOCUS; + return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); +} + +Container createHandle () { + return (Container)CProgressBar.Factory.newInstance(this, style); +} + +/** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMaximum () { + checkWidget (); + return ((CProgressBar)handle).getMaximum(); +} + +/** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMinimum () { + checkWidget (); + return ((CProgressBar)handle).getMinimum(); +} + +/** + * Returns the single 'selection' that is the receiver's position. + * + * @return the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelection () { + checkWidget (); + return ((CProgressBar)handle).getValue(); +} + +/** + * Sets the maximum value that the receiver will allow. This new + * value will be ignored if it is not greater than the receiver's current + * minimum value. If the new maximum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new maximum, which must be greater than the current minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMaximum (int value) { + checkWidget (); + int minimum = getMinimum(); + if (0 <= minimum && minimum < value) { + ((CProgressBar)handle).setMaximum(value); + } +} + +/** + * Sets the minimum value that the receiver will allow. This new + * value will be ignored if it is negative or is not less than the receiver's + * current maximum value. If the new minimum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new minimum, which must be nonnegative and less than the current maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMinimum (int value) { + checkWidget (); + int maximum = getMaximum(); + if (0 <= value && value < maximum) { + ((CProgressBar)handle).setMinimum(value); + } +} + +/** + * Sets the single 'selection' that is the receiver's + * position to the argument which must be greater than or equal + * to zero. + * + * @param value the new selection (must be zero or greater) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int value) { + checkWidget (); + ((CProgressBar)handle).setValue(value); + update(); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java new file mode 100644 index 00000000000..502d6b61e95 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Container; +import java.awt.Point; +import java.awt.event.MouseEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CSash; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of the receiver represent a selectable user interface object + * that allows the user to drag a rubber banded outline of the sash within + * the parent control. + *
    + *
    Styles:
    + *
    HORIZONTAL, VERTICAL, SMOOTH
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ +public class Sash extends Control { +// final static int INCREMENT = 1; +// final static int PAGE_INCREMENT = 9; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Sash (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the x, y, width, and height fields of the event object are valid. + * If the receiver is being dragged, the event object detail field contains the value SWT.DRAG. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); +} + +void createHandleInit() { + super.createHandleInit(); + state |= THEME_BACKGROUND; +} + +Container createHandle () { + return (Container)CSash.Factory.newInstance(this, style); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +Point origin; +Point targetPoint; + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case MouseEvent.MOUSE_PRESSED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + case MouseEvent.MOUSE_DRAGGED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + case MouseEvent.MOUSE_RELEASED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case MouseEvent.MOUSE_PRESSED: { + origin = ((MouseEvent)e).getPoint(); + Event event = new Event(); + Rectangle bounds = getBounds(); + event.x = bounds.x; + event.y = bounds.y; + event.width = bounds.width; + event.height = bounds.height; + targetPoint = new Point(bounds.x, bounds.y); + sendEvent(SWT.Selection, event); + break; + } + case MouseEvent.MOUSE_RELEASED: { + Event event = new Event(); + Rectangle bounds = getBounds(); + event.x = targetPoint.x; + event.y = targetPoint.y; + event.width = bounds.width; + event.height = bounds.height; +// if ((style & SWT.SMOOTH) != 0) { +// event.detail = SWT.DRAG; +// } + sendEvent(SWT.Selection, event); + origin = null; + targetPoint = null; + break; + } + case MouseEvent.MOUSE_DRAGGED: + Event event = new Event(); + MouseEvent me = (MouseEvent)e; + java.awt.Dimension size = handle.getParent().getSize(); + Rectangle bounds = getBounds(); + event.x = bounds.x; + event.y = bounds.y; + if((style & SWT.VERTICAL) != 0) { + event.x += me.getX() - origin.x; + if(event.x < 0) { + event.x = 0; + } else if(event.x >= size.width - bounds.width) { + event.x = size.width - bounds.width; + } + } else { + event.y += me.getY() - origin.y; + if(event.y < 0) { + event.y = 0; + } else if(event.y >= size.height - bounds.height) { + event.y = size.height - bounds.height; + } + } + event.width = bounds.width; + event.height = bounds.height; + if ((style & SWT.SMOOTH) == 0) { + event.detail = SWT.DRAG; + } + sendEvent(SWT.Selection, event); + if (event.doit) { + targetPoint.x = event.x; + targetPoint.y = event.y; + ((CSash)handle).setDragLocation((style & SWT.VERTICAL) != 0? targetPoint.x: targetPoint.y); +// if ((style & SWT.SMOOTH) != 0) { +// setLocation(targetPoint.x, targetPoint.y); +// } + } + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scale.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scale.java new file mode 100644 index 00000000000..53d08c4257f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scale.java @@ -0,0 +1,353 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; +import java.util.EventObject; + +import javax.swing.event.ChangeEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.internal.swing.CScale; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of the receiver represent a selectable user + * interface object that present a range of continuous + * numeric values. + *
    + *
    Styles:
    + *
    HORIZONTAL, VERTICAL
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public class Scale extends Control { + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Scale (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's value changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the control's value changes. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); +} + +void createHandleInit() { + super.createHandleInit(); + state |= THEME_BACKGROUND | DRAW_BACKGROUND; +} + +Container createHandle () { + return (Container)CScale.Factory.newInstance(this, style); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed. + * + * @return the increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getIncrement () { + checkWidget (); + return ((CScale)handle).getMinorTickSpacing(); +} + +/** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMaximum () { + checkWidget (); + return ((CScale)handle).getMaximum(); +} + +/** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMinimum () { + checkWidget (); + return ((CScale)handle).getMinimum(); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected. + * + * @return the page increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getPageIncrement () { + checkWidget (); + return ((CScale)handle).getMajorTickSpacing(); +} + +/** + * Returns the 'selection', which is the receiver's position. + * + * @return the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelection () { + checkWidget (); + return ((CScale)handle).getValue(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's value changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed to the argument, which must be at least + * one. + * + * @param increment the new increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setIncrement (int increment) { + checkWidget (); + if (increment < 1) return; + int minimum = getMinimum(); + int maximum = getMaximum(); + if (increment > maximum - minimum) return; + ((CScale)handle).setMinorTickSpacing(increment); +} + +/** + * Sets the maximum value that the receiver will allow. This new + * value will be ignored if it is not greater than the receiver's current + * minimum value. If the new maximum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new maximum, which must be greater than the current minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMaximum (int value) { + checkWidget (); + int minimum = getMinimum(); + if (0 <= minimum && minimum < value) { + ((CScale)handle).setMaximum(value); + } +} + +/** + * Sets the minimum value that the receiver will allow. This new + * value will be ignored if it is negative or is not less than the receiver's + * current maximum value. If the new minimum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new minimum, which must be nonnegative and less than the current maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMinimum (int value) { + checkWidget (); + int maximum = getMaximum(); + if (0 <= value && value < maximum) { + ((CScale)handle).setMinimum(value); + } +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected to the argument, which must be at least + * one. + * + * @param pageIncrement the page increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPageIncrement (int pageIncrement) { + checkWidget (); + if (pageIncrement < 1) return; + int minimum = getMinimum(); + int maximum = getMaximum(); + if (pageIncrement > maximum - minimum) return; + ((CScale)handle).setMajorTickSpacing(pageIncrement); +} + +/** + * Sets the 'selection', which is the receiver's value, + * to the argument which must be greater than or equal to zero. + * + * @param value the new selection (must be zero or greater) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int value) { + checkWidget (); + ((CScale)handle).setValue(value); +} + +public void processEvent(EventObject e) { + if(e instanceof ChangeEvent) { + if(!hooks(SWT.Selection)) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof ChangeEvent) { +// if(!((ChangeEvent)e).getValueIsAdjusting()) { + sendEvent(SWT.Selection); +// } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java new file mode 100644 index 00000000000..3ca8991dd66 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java @@ -0,0 +1,940 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; + +import org.eclipse.swt.internal.swing.CScrollable; +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.events.*; + +/** + * Instances of this class are selectable user interface + * objects that represent a range of positive, numeric values. + *

    + * At any given moment, a given scroll bar will have a + * single 'selection' that is considered to be its + * value, which is constrained to be within the range of + * values the scroll bar represents (that is, between its + * minimum and maximum values). + *

    + * Typically, scroll bars will be made up of five areas: + *

      + *
    1. an arrow button for decrementing the value
    2. + *
    3. a page decrement area for decrementing the value by a larger amount
    4. + *
    5. a thumb for modifying the value by mouse dragging
    6. + *
    7. a page increment area for incrementing the value by a larger amount
    8. + *
    9. an arrow button for incrementing the value
    10. + *
    + * Based on their style, scroll bars are either HORIZONTAL + * (which have a left facing button for decrementing the value and a + * right facing button for incrementing it) or VERTICAL + * (which have an upward facing button for decrementing the value + * and a downward facing buttons for incrementing it). + *

    + * On some platforms, the size of the scroll bar's thumb can be + * varied relative to the magnitude of the range of values it + * represents (that is, relative to the difference between its + * maximum and minimum values). Typically, this is used to + * indicate some proportional value such as the ratio of the + * visible area of a document to the total amount of space that + * it would take to display it. SWT supports setting the thumb + * size even if the underlying platform does not, but in this + * case the appearance of the scroll bar will not change. + *

    + * Scroll bars are created by specifying either H_SCROLL, + * V_SCROLL or both when creating a Scrollable. + * They are accessed from the Scrollable using + * getHorizontalBar and getVerticalBar. + *

    + * Note: Scroll bars are not Controls. On some platforms, scroll bars + * that appear as part of some standard controls such as a text or list + * have no operating system resources and are not children of the control. + * For this reason, scroll bars are treated specially. To create a control + * that looks like a scroll bar but has operating system resources, use + * Slider. + *

    + *
    + *
    Styles:
    + *
    HORIZONTAL, VERTICAL
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see Slider + * @see Scrollable + * @see Scrollable#getHorizontalBar + * @see Scrollable#getVerticalBar + */ + +public class ScrollBar extends Widget { + Scrollable parent; + JScrollBar handle; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +ScrollBar (Scrollable parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + createWidget (); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's value changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the event object detail field contains one of the following values: + * SWT.NONE - for the end of a drag. + * SWT.DRAG. + * SWT.HOME. + * SWT.END. + * SWT.ARROW_DOWN. + * SWT.ARROW_UP. + * SWT.PAGE_DOWN. + * SWT.PAGE_UP. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); +} + +void createWidget () { + handle = (style & SWT.HORIZONTAL) != 0? ((CScrollable)parent.handle).getHorizontalScrollBar(): ((CScrollable)parent.handle).getVerticalScrollBar(); + /* + * Do not set the intial values of the maximum + * or the thumb. These values normally default + * to 100 and 10 but may have been set already + * by the widget that owns the scroll bar. For + * example, a scroll bar that is created for a + * list widget, setting these defaults would + * override the initial values provided by the + * list widget. + */ + handle.addAdjustmentListener(new AdjustmentListener() { + public void adjustmentValueChanged(AdjustmentEvent e) { + if(blockListener || isDisposed()) return; + Event event = new Event (); + event.detail = SWT.DRAG; + switch(e.getAdjustmentType()) { + case AdjustmentEvent.BLOCK_DECREMENT: + event.detail = SWT.PAGE_DOWN; + break; + case AdjustmentEvent.BLOCK_INCREMENT: + event.detail = SWT.PAGE_UP; + break; + case AdjustmentEvent.UNIT_DECREMENT: + event.detail = SWT.ARROW_DOWN; + break; + case AdjustmentEvent.UNIT_INCREMENT: + event.detail = SWT.ARROW_UP; + break; + } + sendEvent (SWT.Selection, event); + } + }); +} + +void destroyWidget () { + if (isDisposed()) return; + if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); +// int hwnd = hwndScrollBar (), type = scrollBarType (); +// if (OS.IsWinCE) { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE; +// info.nPage = 101; +// info.nMax = 100; +// info.nMin = 0; +// OS.SetScrollInfo (hwnd, type, info, true); +// } else { +// OS.ShowScrollBar (hwnd, type, false); +// } + releaseHandle (); +} + +///* +//* Not currently used. +//*/ +//Rectangle getBounds () { +//// checkWidget (); +// parent.forceResize (); +// RECT rect = new RECT (); +// OS.GetClientRect (parent.scrolledHandle (), rect); +// int x = 0, y = 0, width, height; +// if ((style & SWT.HORIZONTAL) != 0) { +// y = rect.bottom - rect.top; +// width = rect.right - rect.left; +// height = OS.GetSystemMetrics (OS.SM_CYHSCROLL); +// } else { +// x = rect.right - rect.left; +// width = OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// height = rect.bottom - rect.top; +// } +// return new Rectangle (x, y, width, height); +//} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public boolean getEnabled () { + checkWidget(); + return handle.isEnabled(); +// return (state & DISABLED) == 0; +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed. + * + * @return the increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getIncrement () { + checkWidget(); + return handle.getUnitIncrement(); +} + +/** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMaximum () { + checkWidget(); + return handle.getMaximum(); +} + +/** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMinimum () { + checkWidget(); + return handle.getMinimum(); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected. + * + * @return the page increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getPageIncrement () { + checkWidget(); + return handle.getBlockIncrement(); +} + +/** + * Returns the receiver's parent, which must be a Scrollable. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Scrollable getParent () { + checkWidget(); + return parent; +} + +/** + * Returns the single 'selection' that is the receiver's value. + * + * @return the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelection () { + checkWidget(); + return handle.getValue(); +} + +/** + * Returns a point describing the receiver's size. The + * x coordinate of the result is the width of the receiver. + * The y coordinate of the result is the height of the + * receiver. + * + * @return the receiver's size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSize () { + checkWidget(); + java.awt.Dimension size; + if ((style & SWT.HORIZONTAL) != 0) { + size = ((CScrollable)parent.handle).getHorizontalScrollBar().getSize(); + } else { + size = ((CScrollable)parent.handle).getVerticalScrollBar().getSize(); + } + return new Point(size.width, size.height); +// parent.forceResize (); +// RECT rect = new RECT (); +// OS.GetClientRect (parent.scrolledHandle (), rect); +// int width, height; +// if ((style & SWT.HORIZONTAL) != 0) { +// width = rect.right - rect.left; +// height = OS.GetSystemMetrics (OS.SM_CYHSCROLL); +// } else { +// width = OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// height = rect.bottom - rect.top; +// } +// return new Point (width, height); +} + +/** + * Returns the size of the receiver's thumb relative to the + * difference between its maximum and minimum values. + * + * @return the thumb value + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ScrollBar + */ +public int getThumb () { + checkWidget(); + return handle.getVisibleAmount(); +} + +/** + * Returns true if the receiver is visible, and + * false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget(); + return handle.isVisible(); +// return (state & HIDDEN) == 0; +} + +//int hwndScrollBar () { +// return parent.scrolledHandle (); +//} + +/** + * Returns true if the receiver is enabled and all + * of the receiver's ancestors are enabled, and false + * otherwise. A disabled control is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public boolean isEnabled () { + checkWidget(); + return getEnabled () && parent.isEnabled (); +} + +/** + * Returns true if the receiver is visible and all + * of the receiver's ancestors are visible and false + * otherwise. + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + */ +public boolean isVisible () { + checkWidget(); + return getVisible () && parent.isVisible (); +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseParent () { + super.releaseParent (); + if (parent.horizontalBar == this) parent.horizontalBar = null; + if (parent.verticalBar == this) parent.verticalBar = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's value changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +//int scrollBarType () { +// if ((style & SWT.VERTICAL) != 0) return OS.SB_VERT; +// /* +// * This line is intentionally commented. There should +// * only ever be HORIZONTAL and VERTICAL scroll bars. +// * The commented code reminds us that this is the case +// * and that the default style is HORIZONTAL. +// */ +//// if ((style & SWT.HORIZONTAL) != 0) return OS.SB_HORZ; +// return OS.SB_HORZ; +//} + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (boolean enabled) { + checkWidget(); + handle.setEnabled(enabled); +// /* +// * This line is intentionally commented. Currently +// * always show scrollbar as being enabled and visible. +// */ +//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); +// if (!OS.IsWinCE) { +// int hwnd = hwndScrollBar (), type = scrollBarType (); +// int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH; +// OS.EnableScrollBar (hwnd, type, flags); +// if (enabled) { +// state &= ~DISABLED; +// } else { +// state |= DISABLED; +// } +// } +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed to the argument, which must be at least + * one. + * + * @param value the new increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setIncrement (int value) { + checkWidget(); + if (value < 1) return; + handle.setUnitIncrement(value); +} + +/** + * Sets the maximum. If this value is negative or less than or + * equal to the minimum, the value is ignored. If necessary, first + * the thumb and then the selection are adjusted to fit within the + * new range. + * + * @param value the new maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMaximum (int value) { + checkWidget(); + if (value < 0) return; + int minimum = handle.getMinimum(); + if (value <= minimum) return; + blockListener = true; + handle.setMaximum(value); + blockListener = false; +} + +/** + * Sets the minimum value. If this value is negative or greater + * than or equal to the maximum, the value is ignored. If necessary, + * first the thumb and then the selection are adjusted to fit within + * the new range. + * + * @param value the new minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMinimum (int value) { + checkWidget(); + if (value < 0) return; + int maximum = handle.getMaximum(); + if (value >= maximum) return; + blockListener = true; + handle.setMinimum(value); + blockListener = false; +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected to the argument, which must be at least + * one. + * + * @param value the page increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPageIncrement (int value) { + checkWidget(); + if (value < 1) return; + handle.setBlockIncrement(value); +} + +//boolean SetScrollInfo (int hwnd, int flags, SCROLLINFO info, boolean fRedraw) { +// /* +// * Bug in Windows. For some reason, when SetScrollInfo() +// * is used with SIF_POS and the scroll bar is hidden, +// * the opposite scroll bar is incorrectly made visible +// * so that the next time the parent is resized (or another +// * scroll bar operation is performed), the opposite scroll +// * bar draws. The fix is to hide both scroll bars. +// */ +// if ((state & (DISABLED | HIDDEN)) != 0) fRedraw = false; +// boolean result = OS.SetScrollInfo (hwnd, flags, info, fRedraw); +// +// /* +// * Bug in Windows. For some reason, when the widget +// * is a standard scroll bar, and SetScrollInfo() is +// * called with SIF_RANGE or SIF_PAGE, the widget is +// * incorrectly made visible so that the next time the +// * parent is resized (or another scroll bar operation +// * is performed), the scroll bar draws. The fix is +// * to hide the scroll bar (again) when already hidden. +// */ +// if ((state & HIDDEN) != 0) { +// /* +// * This line is intentionally commented. Currently +// * always show scrollbar as being enabled and visible. +// */ +//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); +// if (!OS.IsWinCE) { +// ScrollBar bar = null; +// switch (flags) { +// case OS.SB_HORZ: +// bar = parent.getVerticalBar (); +// break; +// case OS.SB_VERT: +// bar = parent.getHorizontalBar (); +// break; +// } +// boolean both = bar != null && !bar.getVisible (); +// OS.ShowScrollBar (hwnd, both ? OS.SB_BOTH : flags, false); +// } +// } +// +// /* +// * Feature in Windows. Using SIF_DISABLENOSCROLL, +// * SetScrollInfo () can change enabled and disabled +// * state of the scroll bar causing a scroll bar that +// * was disabled by the application to become enabled. +// * The fix is to disable the scroll bar (again) when +// * the application has disabled the scroll bar. +// */ +// if ((state & DISABLED) != 0) { +// /* +// * This line is intentionally commented. Currently +// * always show scrollbar as being enabled and visible. +// */ +//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); +// if (!OS.IsWinCE) { +// OS.EnableScrollBar (hwnd, flags, OS.ESB_DISABLE_BOTH); +// } +// } +// return result; +//} + +/** + * Sets the single selection that is the receiver's + * value to the argument which must be greater than or equal + * to zero. + * + * @param selection the new selection (must be zero or greater) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int selection) { + checkWidget(); + blockListener = true; + handle.setValue(selection); + blockListener = false; +} + +boolean blockListener; + +/** + * Sets the size of the receiver's thumb relative to the + * difference between its maximum and minimum values. This new + * value will be ignored if it is less than one, and will be + * clamped if it exceeds the receiver's current range. + * + * @param value the new thumb value, which must be at least one and not + * larger than the size of the current range + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setThumb (int value) { + checkWidget(); + if (value < 1) return; + int minimum = handle.getMinimum(); + int maximum = handle.getMaximum(); + int range = maximum - minimum; + if (value > range) { + value = range; + } + int maxSelection = maximum - value; + int selection = handle.getValue(); + if (selection > maxSelection) { + selection = maxSelection; + } + blockListener = true; + handle.setValues(selection, value, minimum, maximum); + blockListener = false; +} + +/** + * Sets the receiver's selection, minimum value, maximum + * value, thumb, increment and page increment all at once. + *

    + * Note: This is similar to setting the values individually + * using the appropriate methods, but may be implemented in a + * more efficient fashion on some platforms. + *

    + * + * @param selection the new selection value + * @param minimum the new minimum value + * @param maximum the new maximum value + * @param thumb the new thumb value + * @param increment the new increment value + * @param pageIncrement the new pageIncrement value + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) { + checkWidget(); + if (minimum < 0) return; + if (maximum < 0) return; + if (thumb < 1) return; + if (increment < 1) return; + if (pageIncrement < 1) return; + blockListener = true; + handle.setValues(selection, thumb, minimum, maximum); + blockListener = false; +} + +/** + * Marks the receiver as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget(); +// boolean isVisible = (state & HIDDEN) == 0; +// if (isVisible == visible) return; + if(handle.getParent() instanceof JScrollPane) { + JScrollPane scrollPane = ((JScrollPane)handle.getParent()); + if((style & SWT.HORIZONTAL) != 0) { + if(visible) { + scrollPane.setHorizontalScrollBarPolicy((parent.getStyle() & SWT.H_SCROLL) != 0? ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS: ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + } else { + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + } + } else { + if(visible) { + scrollPane.setVerticalScrollBarPolicy((parent.getStyle() & SWT.V_SCROLL) != 0? ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS: ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + } else { + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + } + } + } else { + handle.setVisible(visible); + } +// /* +// * On Windows CE, use SIF_DISABLENOSCROLL to show and +// * hide the scroll bar when the page size is equal to +// * the range. +// */ +// if (OS.IsWinCE) { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// int hwnd = hwndScrollBar (), type = scrollBarType (); +// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE; +// if (visible) info.fMask |= OS.SIF_DISABLENOSCROLL; +// OS.GetScrollInfo (hwnd, type, info); +// if (info.nPage == info.nMax - info.nMin + 1) { +// /* +// * Bug in Windows. When the only changed flag to +// * SetScrollInfo () is OS.SIF_DISABLENOSCROLL, +// * Windows does not update the scroll bar state. +// * The fix is to increase and then decrease the +// * maximum, causing Windows to honour the flag. +// */ +// int max = info.nMax; +// info.nMax++; +// OS.SetScrollInfo (hwnd, type, info, false); +// info.nMax = max; +// OS.SetScrollInfo (hwnd, type, info, true); +// } else { +// /* +// * This line is intentionally commented. Currently +// * always show scrollbar as being enabled and visible. +// */ +//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); +// } +// return; +// } +// +// /* +// * Set the state bits before calling ShowScrollBar () +// * because hiding and showing the scroll bar can cause +// * WM_SIZE messages when the client area is resized. +// * Setting the state before the call means that code +// * that runs during WM_SIZE that queries the visibility +// * of the scroll bar will get the correct value. +// */ +// state = visible ? state & ~HIDDEN : state | HIDDEN; +// int hwnd = hwndScrollBar (), type = scrollBarType (); +// if (OS.ShowScrollBar (hwnd, type, visible)) { +// /* +// * Bug in Windows. For some reason, when the widget +// * is a standard scroll bar, and SetScrollInfo () is +// * called with SIF_RANGE or SIF_PAGE while the widget +// * is not visible, the widget is incorrectly disabled +// * even though the values for SIF_RANGE and SIF_PAGE, +// * when set for a visible scroll bar would not disable +// * the scroll bar. The fix is to enable the scroll bar +// * when not disabled by the application and the current +// * scroll bar ranges would cause the scroll bar to be +// * enabled had they been set when the scroll bar was +// * visible. +// */ +// if ((state & DISABLED) == 0) { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE; +// OS.GetScrollInfo (hwnd, type, info); +// if (info.nMax - info.nMin - info.nPage >= 0) { +// OS.EnableScrollBar (hwnd, type, OS.ESB_ENABLE_BOTH); +// } +// } +// sendEvent (visible ? SWT.Show : SWT.Hide); +// // widget could be disposed at this point +// } +} + +//LRESULT wmScrollChild (int wParam, int lParam) { +// +// /* Do nothing when scrolling is ending */ +// int code = wParam & 0xFFFF; +// switch (code) { +// case OS.SB_THUMBPOSITION: +// case OS.SB_ENDSCROLL: +// return null; +// } +// +// /* +// * Send the event because WM_HSCROLL and +// * WM_VSCROLL are sent from a modal message +// * loop in Windows that is active when the +// * user is scrolling. +// */ +// Event event = new Event (); +// switch (code) { +// case OS.SB_THUMBTRACK: event.detail = SWT.DRAG; break; +// case OS.SB_TOP: event.detail = SWT.HOME; break; +// case OS.SB_BOTTOM: event.detail = SWT.END; break; +// case OS.SB_LINEDOWN: event.detail = SWT.ARROW_DOWN; break; +// case OS.SB_LINEUP: event.detail = SWT.ARROW_UP; break; +// case OS.SB_PAGEDOWN: event.detail = SWT.PAGE_DOWN; break; +// case OS.SB_PAGEUP: event.detail = SWT.PAGE_UP; break; +// } +// sendEvent (SWT.Selection, event); +// // the widget could be destroyed at this point +// return null; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java new file mode 100644 index 00000000000..7c54ec1a869 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java @@ -0,0 +1,422 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; +import java.awt.Insets; +import java.awt.Window; + +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CControl; + +/** + * This class is the abstract superclass of all classes which + * represent controls that have standard scroll bars. + *
    + *
    Styles:
    + *
    H_SCROLL, V_SCROLL
    + *
    Events: + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + */ + +public abstract class Scrollable extends Control { + ScrollBar horizontalBar, verticalBar; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Scrollable () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#H_SCROLL + * @see SWT#V_SCROLL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Scrollable (Composite parent, int style) { + super (parent, style); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// if (handle == 0) return 0; +// return OS.DefWindowProc (hwnd, msg, wParam, lParam); +//} + +/** + * Given a desired client area for the receiver + * (as described by the arguments), returns the bounding + * rectangle which would be required to produce that client + * area. + *

    + * In other words, it returns a rectangle such that, if the + * receiver's bounds were set to that rectangle, the area + * of the receiver which is capable of displaying data + * (that is, not covered by the "trimmings") would be the + * rectangle described by the arguments (relative to the + * receiver's parent). + *

    + * + * @param x the desired x coordinate of the client area + * @param y the desired y coordinate of the client area + * @param width the desired width of the client area + * @param height the desired height of the client area + * @return the required bounds to produce the given client area + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getClientArea + */ +public Rectangle computeTrim (int x, int y, int width, int height) { + checkWidget (); + java.awt.Dimension hSize = handle.getPreferredSize(); + java.awt.Container clientArea = ((CControl)handle).getClientArea(); + java.awt.Dimension cSize = clientArea.getPreferredSize(); + java.awt.Point location = new java.awt.Point(0, 0); + SwingUtilities.convertPoint(clientArea, location, handle); + int top = location.y; + int left = location.x; + int bottom = hSize.height - cSize.height - top; + int right = hSize.width - cSize.width - left; + return new Rectangle(x - left, y - top, left + width + right, top + height + bottom); +} + +ScrollBar createScrollBar (int type) { + ScrollBar bar = new ScrollBar (this, type); +// if ((state & CANVAS) != 0) { +// bar.setMaximum (100); +// bar.setThumb (10); +// } + return bar; +} + +void createWidget () { + super.createWidget (); + if ((style & SWT.H_SCROLL) != 0) horizontalBar = createScrollBar (SWT.H_SCROLL); + if ((style & SWT.V_SCROLL) != 0) verticalBar = createScrollBar (SWT.V_SCROLL); +} + +/** + * Returns a rectangle which describes the area of the + * receiver which is capable of displaying data (that is, + * not covered by the "trimmings"). + * + * @return the client area + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #computeTrim + */ +public Rectangle getClientArea () { + checkWidget (); + Container clientArea = ((CControl)handle).getClientArea(); + java.awt.Rectangle bounds = clientArea.getBounds(); + if(handle instanceof Window) { + return new Rectangle(0, 0, bounds.width, bounds.height); + } + Container parent = clientArea.getParent(); + bounds = SwingUtilities.convertRectangle(parent, bounds, handle); + Container handleParent = handle.getParent(); + while(parent != handleParent) { + Insets insets = parent.getInsets(); + bounds.x -= insets.left; + bounds.y -= insets.top; + parent = parent.getParent(); + } + Point internalOffset = getInternalOffset(); + return new Rectangle(bounds.x - internalOffset.x, bounds.y - internalOffset.y, bounds.width + internalOffset.x, bounds.height + internalOffset.y); +// forceResize (); +// RECT rect = new RECT (); +// int scrolledHandle = scrolledHandle (); +// OS.GetClientRect (scrolledHandle, rect); +// return new Rectangle (0, 0, rect.right, rect.bottom); +} + +/** + * Returns the receiver's horizontal scroll bar if it has + * one, and null if it does not. + * + * @return the horizontal scroll bar (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ScrollBar getHorizontalBar () { + checkWidget (); + return horizontalBar; +} + +/** + * Returns the receiver's vertical scroll bar if it has + * one, and null if it does not. + * + * @return the vertical scroll bar (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ScrollBar getVerticalBar () { + checkWidget (); + return verticalBar; +} + +void releaseChildren (boolean destroy) { + if (horizontalBar != null) { + horizontalBar.release (false); + horizontalBar = null; + } + if (verticalBar != null) { + verticalBar.release (false); + verticalBar = null; + } + super.releaseChildren (destroy); +} + +//int scrolledHandle () { +// return handle; +//} +// +//int widgetExtStyle () { +// return super.widgetExtStyle (); +// /* +// * This code is intentionally commented. In future, +// * we may wish to support different standard Windows +// * edge styles. The issue here is that not all of +// * these styles are available on the other platforms +// * this would need to be a hint. +// */ +//// if ((style & SWT.BORDER) != 0) return OS.WS_EX_CLIENTEDGE; +//// if ((style & SWT.SHADOW_IN) != 0) return OS.WS_EX_STATICEDGE; +//// return super.widgetExtStyle (); +//} +// +//int widgetStyle () { +// int bits = super.widgetStyle () | OS.WS_TABSTOP; +// if ((style & SWT.H_SCROLL) != 0) bits |= OS.WS_HSCROLL; +// if ((style & SWT.V_SCROLL) != 0) bits |= OS.WS_VSCROLL; +// return bits; +//} +// +//TCHAR windowClass () { +// return display.windowClass; +//} +// +//int windowProc () { +// return display.windowProc; +//} +// +//LRESULT WM_HSCROLL (int wParam, int lParam) { +// LRESULT result = super.WM_HSCROLL (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Bug on WinCE. lParam should be NULL when the message is not sent +// * by a scroll bar control, but it contains the handle to the window. +// * When the message is sent by a scroll bar control, it correctly +// * contains the handle to the scroll bar. The fix is to check for +// * both. +// */ +// if (horizontalBar != null && (lParam == 0 || lParam == handle)) { +// return wmScroll (horizontalBar, (state & CANVAS) != 0, handle, OS.WM_HSCROLL, wParam, lParam); +// } +// return result; +//} +// +//LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { +// LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL. +// */ +// if ((state & CANVAS) != 0) { +// if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) != 0) return result; +// boolean vertical = verticalBar != null && verticalBar.getEnabled (); +// boolean horizontal = horizontalBar != null && horizontalBar.getEnabled (); +// int msg = (vertical) ? OS.WM_VSCROLL : (horizontal) ? OS.WM_HSCROLL : 0; +// if (msg == 0) return result; +// int [] value = new int [1]; +// OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, value, 0); +// int delta = (short) (wParam >> 16); +// int code = 0, count = 0; +// if (value [0] == OS.WHEEL_PAGESCROLL) { +// code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP; +// count = Math.abs (delta / OS.WHEEL_DELTA); +// } else { +// code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP; +// delta = Math.abs (delta); +// if (delta < OS.WHEEL_DELTA) return result; +// if (msg == OS.WM_VSCROLL) { +// count = value [0] * delta / OS.WHEEL_DELTA; +// } else { +// count = delta / OS.WHEEL_DELTA; +// } +// } +// for (int i=0; iDisplay as the argument) are described + * as top level shells. Instances that do have + * a parent are described as secondary or + * dialog shells. + *

    + * Instances are always displayed in one of the maximized, + * minimized or normal states: + *

      + *
    • + * When an instance is marked as maximized, the + * window manager will typically resize it to fill the + * entire visible area of the display, and the instance + * is usually put in a state where it can not be resized + * (even if it has style RESIZE) until it is + * no longer maximized. + *
    • + * When an instance is in the normal state (neither + * maximized or minimized), its appearance is controlled by + * the style constants which were specified when it was created + * and the restrictions of the window manager (see below). + *
    • + * When an instance has been marked as minimized, + * its contents (client area) will usually not be visible, + * and depending on the window manager, it may be + * "iconified" (that is, replaced on the desktop by a small + * simplified representation of itself), relocated to a + * distinguished area of the screen, or hidden. Combinations + * of these changes are also possible. + *
    • + *
    + *

    + * The modality of an instance may be specified using + * style bits. The modality style bits are used to determine + * whether input is blocked for other shells on the display. + * The PRIMARY_MODAL style allows an instance to block + * input to its parent. The APPLICATION_MODAL style + * allows an instance to block input to every other shell in the + * display. The SYSTEM_MODAL style allows an instance + * to block input to all shells, including shells belonging to + * different applications. + *

    + * Note: The styles supported by this class are treated + * as HINTs, since the window manager for the + * desktop on which the instance is visible has ultimate + * control over the appearance and behavior of decorations + * and modality. For example, some window managers only + * support resizable windows and will always assume the + * RESIZE style, even if it is not set. In addition, if a + * modality style is not supported, it is "upgraded" to a + * more restrictive modality style that is supported. For + * example, if PRIMARY_MODAL is not supported, + * it would be upgraded to APPLICATION_MODAL. + * A modality style may also be "downgraded" to a less + * restrictive style. For example, most operating systems + * no longer support SYSTEM_MODAL because + * it can freeze up the desktop, so this is typically + * downgraded to APPLICATION_MODAL. + *

    + *
    Styles:
    + *
    BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL
    + *
    APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL
    + *
    Events:
    + *
    Activate, Close, Deactivate, Deiconify, Iconify
    + *
    + * Class SWT provides two "convenience constants" + * for the most commonly required style combinations: + *
    + *
    SHELL_TRIM
    + *
    + * the result of combining the constants which are required + * to produce a typical application top level shell: (that + * is, CLOSE | TITLE | MIN | MAX | RESIZE) + *
    + *
    DIALOG_TRIM
    + *
    + * the result of combining the constants which are required + * to produce a typical application dialog shell: (that + * is, TITLE | CLOSE | BORDER) + *
    + *
    + *

    + *

    + * Note: Only one of the styles APPLICATION_MODAL, MODELESS, + * PRIMARY_MODAL and SYSTEM_MODAL may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see Decorations + * @see SWT + */ +public class Shell extends Decorations { + Menu activeMenu; +// int hIMC, hwndMDIClient, toolTipHandle, lpstrTip; + int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT; +// int [] brushes; +// boolean showWithParent; + Control lastActive; +// SHACTIVATEINFO psai; + Region region; +// static final int DialogProc; +// static final TCHAR DialogClass = new TCHAR (0, OS.IsWinCE ? "Dialog" : "#32770", true); +// static { +// WNDCLASS lpWndClass = new WNDCLASS (); +// OS.GetClassInfo (0, DialogClass, lpWndClass); +// DialogProc = lpWndClass.lpfnWndProc; +// } + +/** + * Constructs a new instance of this class. This is equivalent + * to calling Shell((Display) null). + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public Shell () { + this ((Display) null); +} + +/** + * Constructs a new instance of this class given only the style + * value describing its behavior and appearance. This is equivalent + * to calling Shell((Display) null, style). + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param style the style of control to construct + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BORDER + * @see SWT#CLOSE + * @see SWT#MIN + * @see SWT#MAX + * @see SWT#RESIZE + * @see SWT#TITLE + * @see SWT#NO_TRIM + * @see SWT#SHELL_TRIM + * @see SWT#DIALOG_TRIM + * @see SWT#MODELESS + * @see SWT#PRIMARY_MODAL + * @see SWT#APPLICATION_MODAL + * @see SWT#SYSTEM_MODAL + */ +public Shell (int style) { + this ((Display) null, style); +} + +/** + * Constructs a new instance of this class given only the display + * to create it on. It is created with style SWT.SHELL_TRIM. + *

    + * Note: Currently, null can be passed in for the display argument. + * This has the effect of creating the shell on the currently active + * display if there is one. If there is no current display, the + * shell is created on a "default" display. Passing in null as + * the display argument is not considered to be good coding style, + * and may not be supported in a future release of SWT. + *

    + * + * @param display the display to create the shell on + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public Shell (Display display) { + this (display, SWT.SHELL_TRIM); +} + +/** + * Constructs a new instance of this class given the display + * to create it on and a style value describing its behavior + * and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * Note: Currently, null can be passed in for the display argument. + * This has the effect of creating the shell on the currently active + * display if there is one. If there is no current display, the + * shell is created on a "default" display. Passing in null as + * the display argument is not considered to be good coding style, + * and may not be supported in a future release of SWT. + *

    + * + * @param display the display to create the shell on + * @param style the style of control to construct + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BORDER + * @see SWT#CLOSE + * @see SWT#MIN + * @see SWT#MAX + * @see SWT#RESIZE + * @see SWT#TITLE + * @see SWT#NO_TRIM + * @see SWT#SHELL_TRIM + * @see SWT#DIALOG_TRIM + * @see SWT#MODELESS + * @see SWT#PRIMARY_MODAL + * @see SWT#APPLICATION_MODAL + * @see SWT#SYSTEM_MODAL + */ +public Shell (Display display, int style) { + this (display, null, style, null); +} + +Shell (Display display, Shell parent, int style, Container handle) { + super (); + checkSubclass (); + if (display == null) display = Display.getCurrent (); + if (display == null) display = Display.getDefault (); + if (!display.isValidThread ()) { + error (SWT.ERROR_THREAD_INVALID_ACCESS); + } + if (parent != null && parent.isDisposed ()) { + error (SWT.ERROR_INVALID_ARGUMENT); + } + this.style = checkStyle (style); + this.parent = parent; + this.display = display; + this.handle = handle; + createWidget (); +} + +/** + * Constructs a new instance of this class given only its + * parent. It is created with style SWT.DIALOG_TRIM. + *

    + * Note: Currently, null can be passed in for the parent. + * This has the effect of creating the shell on the currently active + * display if there is one. If there is no current display, the + * shell is created on a "default" display. Passing in null as + * the parent is not considered to be good coding style, + * and may not be supported in a future release of SWT. + *

    + * + * @param parent a shell which will be the parent of the new instance + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parent is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +public Shell (Shell parent) { + this (parent, SWT.DIALOG_TRIM); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * Note: Currently, null can be passed in for the parent. + * This has the effect of creating the shell on the currently active + * display if there is one. If there is no current display, the + * shell is created on a "default" display. Passing in null as + * the parent is not considered to be good coding style, + * and may not be supported in a future release of SWT. + *

    + * + * @param parent a shell which will be the parent of the new instance + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the parent is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#BORDER + * @see SWT#CLOSE + * @see SWT#MIN + * @see SWT#MAX + * @see SWT#RESIZE + * @see SWT#TITLE + * @see SWT#NO_TRIM + * @see SWT#SHELL_TRIM + * @see SWT#DIALOG_TRIM + * @see SWT#ON_TOP + * @see SWT#TOOL + * @see SWT#MODELESS + * @see SWT#PRIMARY_MODAL + * @see SWT#APPLICATION_MODAL + * @see SWT#SYSTEM_MODAL + */ +public Shell (Shell parent, int style) { + this (parent != null ? parent.display : null, parent, style, null); +} + +/** + * Invokes platform specific functionality to allocate a new shell. + *

    + * IMPORTANT: This method is not part of the public + * API for Shell. It is marked public only so that it + * can be shared within the packages provided by SWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param display the display for the shell + * @param handle the handle for the shell + * @return a new shell object containing the specified display and handle + */ +public static Shell swing_new (Display display, Container handle) { + return new Shell (display, null, SWT.NO_TRIM, handle); +} + +static int checkStyle (int style) { + style = Decorations.checkStyle (style); + int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL; + int bits = style & ~mask; + if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL; + if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL; + if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL; + return bits; +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when operations are performed on the receiver, + * by sending the listener one of the messages defined in the + * ShellListener interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ShellListener + * @see #removeShellListener + */ +public void addShellListener (ShellListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Close,typedListener); + addListener (SWT.Iconify,typedListener); + addListener (SWT.Deiconify,typedListener); + addListener (SWT.Activate, typedListener); + addListener (SWT.Deactivate, typedListener); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// if ((style & SWT.TOOL) != 0) { +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; +// if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam); +// } +// if (parent != null) { +// if (handle == 0) return 0; +// switch (msg) { +// case OS.WM_KILLFOCUS: +// case OS.WM_SETFOCUS: +// return OS.DefWindowProc (hwnd, msg, wParam, lParam); +// } +// return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam); +// } +// if (handle == 0) return 0; +// if (hwndMDIClient != 0) { +// return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam); +// } +// return OS.DefWindowProc (hwnd, msg, wParam, lParam); +//} + +/** + * Requests that the window manager close the receiver in + * the same way it would be closed when the user clicks on + * the "close box" or performs some other platform specific + * key or mouse combination that indicates the window + * should be removed. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#Close + * @see #dispose + */ +public void close () { + checkWidget (); + closeWidget (); +} + +protected Container createHandle () { + CShell parentShell = parent != null? (CShell)parent.handle: null; + return (Container)CShell.Factory.newInstance(this, parentShell, style); +// boolean embedded = handle != 0; +// +// /* +// * On Windows 98 and NT, setting a window to be the +// * top most window using HWND_TOPMOST can result in a +// * parent dialog shell being moved behind its parent +// * if the dialog has a sibling that is currently on top +// * This only occurs using SetWindowPos (), not when the +// * handle is created. +// */ +// /* +// * The following code is intentionally commented. +// */ +//// if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = true; +// super.createHandle (); +// +// /* +// * The following code is intentionally commented. +// */ +//// if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = false; +// +// if (!embedded) { +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION); +// if (!OS.IsWinCE) bits |= OS.WS_POPUP; +// if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION; +// if ((style & SWT.NO_TRIM) == 0) { +// if ((style & (SWT.BORDER | SWT.RESIZE)) == 0) bits |= OS.WS_BORDER; +// } +// /* +// * Bug in Windows. When the WS_CAPTION bits are cleared using +// * SetWindowLong(), Windows does not resize the client area of +// * the window to get rid of the caption until the first resize. +// * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force +// * the frame to be redrawn and resized. +// */ +// OS.SetWindowLong (handle, OS.GWL_STYLE, bits); +// int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE; +// SetWindowPos (handle, 0, 0, 0, 0, 0, flags); +// if (OS.IsWinCE) setMaximized (true); +// if (OS.IsPPC) { +// psai = new SHACTIVATEINFO (); +// psai.cbSize = SHACTIVATEINFO.sizeof; +// } +// } +// if (OS.IsDBLocale) { +// hIMC = OS.ImmCreateContext (); +// if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC); +// } +} + +public void dispose () { + /* + * This code is intentionally commented. On some + * platforms, the owner window is repainted right + * away when a dialog window exits. This behavior + * is currently unspecified. + */ +// /* +// * Note: It is valid to attempt to dispose a widget +// * more than once. If this happens, fail silently. +// */ +// if (!isValidWidget ()) return; +// if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); + Display oldDisplay = display; + super.dispose (); + if (oldDisplay != null) oldDisplay.wake(); + // widget is disposed at this point +// if (oldDisplay != null) oldDisplay.update (); +} + +//void enableWidget (boolean enabled) { +// if (enabled) { +// state &= ~DISABLED; +// } else { +// state |= DISABLED; +// } +// if (Display.TrimEnabled) { +// if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled); +// } else { +// OS.EnableWindow (handle, enabled); +// } +//} +// +//int findBrush (int pixel) { +// if (pixel == OS.GetSysColor (OS.COLOR_BTNFACE)) { +// return OS.GetSysColorBrush (OS.COLOR_BTNFACE); +// } +// if (pixel == OS.GetSysColor (OS.COLOR_WINDOW)) { +// return OS.GetSysColorBrush (OS.COLOR_WINDOW); +// } +// if (brushes == null) brushes = new int [4]; +// LOGBRUSH logBrush = new LOGBRUSH (); +// for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.0 + * @see Control#moveAbove + * @see Control#setFocus + * @see Control#setVisible + * @see Display#getActiveShell + * @see Decorations#setDefaultButton + * @see Shell#open + * @see Shell#setActive + */ +public void forceActive () { + checkWidget (); + if(!isVisible()) return; + ((CShell)handle).toFront(); +} + +//void forceResize () { +// /* Do nothing */ +//} +// +//public Rectangle getBounds () { +// checkWidget (); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) return super.getBounds (); +// } +// RECT rect = new RECT (); +// OS.GetWindowRect (handle, rect); +// int width = rect.right - rect.left; +// int height = rect.bottom - rect.top; +// return new Rectangle (rect.left, rect.top, width, height); +//} +// +//public boolean getEnabled () { +// checkWidget (); +// return (state & DISABLED) == 0; +//} + +/** + * Returns the receiver's input method editor mode. This + * will be the result of bitwise OR'ing together one or + * more of the following constants defined in class + * SWT: + * NONE, ROMAN, DBCS, + * PHONETIC, NATIVE, ALPHA. + * + * @return the IME mode + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + */ +public int getImeInputMode () { + checkWidget (); + // TODO: have a look at setImeInputMethod... + return SWT.NONE; +// if (!OS.IsDBLocale) return 0; +// int hIMC = OS.ImmGetContext (handle); +// int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1]; +// boolean open = OS.ImmGetOpenStatus (hIMC); +// if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence); +// OS.ImmReleaseContext (handle, hIMC); +// if (!open) return SWT.NONE; +// int result = 0; +// if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN; +// if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS; +// if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC; +// if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE; +// return result | SWT.ALPHA; +} + +//public Point getLocation () { +// checkWidget (); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) { +// return super.getLocation (); +// } +// } +// RECT rect = new RECT (); +// OS.GetWindowRect (handle, rect); +// return new Point (rect.left, rect.top); +//} + +/** + * Returns a point describing the minimum receiver's size. The + * x coordinate of the result is the minimum width of the receiver. + * The y coordinate of the result is the minimum height of the + * receiver. + * + * @return the receiver's size + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Point getMinimumSize () { + checkWidget (); + java.awt.Dimension size = handle.getMinimumSize(); + return new Point(size.width, size.height); +// int width = Math.max (0, minWidth); +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; +// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) { +// width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK)); +// } +// int height = Math.max (0, minHeight); +// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) { +// if ((style & SWT.RESIZE) != 0) { +// height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK)); +// } else { +// RECT rect = new RECT (); +// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); +// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); +// OS.AdjustWindowRectEx (rect, bits1, false, bits2); +// height = Math.max (height, rect.bottom - rect.top); +// } +// } +// return new Point (width, height); +} + +/** + * Returns the region that defines the shape of the shell, + * or null if the shell has the default shape. + * + * @return the region that defines the shape of the shell (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + * + */ +public Region getRegion () { + checkWidget (); + return region; +} + +public Shell getShell () { + checkWidget (); + return this; +} + +//public Point getSize () { +// checkWidget (); +// if (!OS.IsWinCE) { +// if (OS.IsIconic (handle)) return super.getSize (); +// } +// RECT rect = new RECT (); +// OS.GetWindowRect (handle, rect); +// int width = rect.right - rect.left; +// int height = rect.bottom - rect.top; +// return new Point (width, height); +//} + +/** + * Returns an array containing all shells which are + * descendents of the receiver. + *

    + * @return the dialog shells + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Shell [] getShells () { + checkWidget (); + int count = 0; + Shell [] shells = display.getShells (); + for (int i=0; i 0 ? this : null; +} + +protected boolean getTraversalKeyDefault(java.awt.event.KeyEvent ke) { + return false; +} + +public boolean isEnabled () { + checkWidget (); + return getEnabled (); +} + +public boolean isFocusControl () { + checkWidget (); + if(super.isFocusControl()) return true; + KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + return keyboardFocusManager.getFocusOwner() == null && keyboardFocusManager.getFocusedWindow() == handle; +} + +//public boolean isVisible () { +// checkWidget (); +// return getVisible (); +//} +// +//int hwndMDIClient () { +// if (hwndMDIClient == 0) { +// int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS; +// hwndMDIClient = OS.CreateWindowEx ( +// 0, +// new TCHAR (0, "MDICLIENT", true), +// null, +// widgetStyle, +// 0, 0, 0, 0, +// handle, +// 0, +// OS.GetModuleHandle (null), +// new CREATESTRUCT ()); +//// OS.ShowWindow (hwndMDIClient, OS.SW_SHOW); +// } +// return hwndMDIClient; +//} + +/** + * Moves the receiver to the top of the drawing order for + * the display on which it was created (so that all other + * shells on that display, which are not the receiver's + * children will be drawn behind it), marks it visible, + * sets the focus and asks the window manager to make the + * shell active. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Control#moveAbove + * @see Control#setFocus + * @see Control#setVisible + * @see Display#getActiveShell + * @see Decorations#setDefaultButton + * @see Shell#setActive + * @see Shell#forceActive + */ +public void open () { + checkWidget (); + bringToTop (); + if (isDisposed ()) return; + layout(); // Added because the default size is not taken into account be layout managers. cf snippet 109 +// /* +// * Feature on WinCE PPC. A new application becomes +// * the foreground application only if it has at least +// * one visible window before the event loop is started. +// * The workaround is to explicitely force the shell to +// * be the foreground window. +// */ +// if (OS.IsWinCE) OS.SetForegroundWindow (handle); +// OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); + setVisible (true); + // This is to ensure that splashscreens that do not dispatch the events from the queue have some display. +// handle.paint(handle.getGraphics()); + if (isDisposed ()) return; +// /* +// * Bug in Windows XP. Despite the fact that an icon has been +// * set for a window, the task bar displays the wrong icon the +// * first time the window is made visible with ShowWindow() after +// * a call to BringToTop(), when a long time elapses between the +// * ShowWindow() and the time the event queue is read. The icon +// * in the window trimming is correct but the one in the task +// * bar does not get updated. The fix is to call PeekMessage() +// * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond +// * to a cross thread WM_GETICON. +// * +// * NOTE: This allows other cross thread messages to be delivered, +// * most notably WM_ACTIVATE. +// */ +// MSG msg = new MSG (); +// int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE; +// OS.PeekMessage (msg, 0, 0, 0, flags); +// if (!restoreFocus () && !traverseGroup (true)) setFocus (); +} + +//void releaseHandle () { +// super.releaseHandle (); +// hwndMDIClient = 0; +//} + +void releaseChildren (boolean destroy) { + Shell [] shells = getShells (); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ShellListener + * @see #addShellListener + */ +public void removeShellListener (ShellListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Close, listener); + eventTable.unhook (SWT.Iconify,listener); + eventTable.unhook (SWT.Deiconify,listener); + eventTable.unhook (SWT.Activate, listener); + eventTable.unhook (SWT.Deactivate, listener); +} + +//LRESULT selectPalette (int hPalette) { +// int hDC = OS.GetDC (handle); +// int hOld = OS.SelectPalette (hDC, hPalette, false); +// int result = OS.RealizePalette (hDC); +// if (result > 0) { +// OS.InvalidateRect (handle, null, true); +// } else { +// OS.SelectPalette (hDC, hOld, true); +// OS.RealizePalette (hDC); +// } +// OS.ReleaseDC (handle, hDC); +// return (result > 0) ? LRESULT.ONE : LRESULT.ZERO; +//} + +/** + * If the receiver is visible, moves it to the top of the + * drawing order for the display on which it was created + * (so that all other shells on that display, which are not + * the receiver's children will be drawn behind it) and asks + * the window manager to make the shell active + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + * @see Control#moveAbove + * @see Control#setFocus + * @see Control#setVisible + * @see Display#getActiveShell + * @see Decorations#setDefaultButton + * @see Shell#open + * @see Shell#setActive + */ +public void setActive () { + checkWidget (); + if(!isVisible()) return; +// bringToTop (); + ((CShell)handle).forceActive(); + // widget could be disposed at this point +} + +Control getActiveControl() { + return lastActive; +} + +void setActiveControl (Control control) { + if (control != null && control.isDisposed ()) control = null; + if (lastActive != null && lastActive.isDisposed ()) lastActive = null; + if (lastActive == control) return; + + /* + * Compute the list of controls to be activated and + * deactivated by finding the first common parent + * control. + */ + Control [] activate = (control == null) ? new Control [0] : control.getPath (); + Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath (); + lastActive = control; + int index = 0, length = Math.min (activate.length, deactivate.length); + while (index < length) { + if (activate [index] != deactivate [index]) break; + index++; + } + + /* + * It is possible (but unlikely), that application + * code could have destroyed some of the widgets. If + * this happens, keep processing those widgets that + * are not disposed. + */ + for (int i=deactivate.length-1; i>=index; --i) { + if (!deactivate [i].isDisposed ()) { + deactivate [i].sendEvent (SWT.Deactivate); + } + } + for (int i=activate.length-1; i>=index; --i) { + if (!activate [i].isDisposed ()) { + activate [i].sendEvent (SWT.Activate); + } + } +} + +//void setBounds (int x, int y, int width, int height, int flags, boolean defer) { +// super.setBounds (x, y, width, height, flags, false); +//} +// +//public void setEnabled (boolean enabled) { +// checkWidget (); +// if (((state & DISABLED) == 0) == enabled) return; +// super.setEnabled (enabled); +// if (enabled && handle == OS.GetActiveWindow ()) { +// if (!restoreFocus ()) traverseGroup (true); +// } +//} + +/** + * Sets the input method editor mode to the argument which + * should be the result of bitwise OR'ing together one or more + * of the following constants defined in class SWT: + * NONE, ROMAN, DBCS, + * PHONETIC, NATIVE, ALPHA. + * + * @param mode the new IME mode + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + */ +public void setImeInputMode (int mode) { + checkWidget (); + // TODO: implement probably with something like the following... + InputContext ic = handle.getInputContext(); + boolean imeOn = mode != SWT.NONE && mode != SWT.ROMAN; +//handle.enableInputMethods(imeOn); + ic.setCompositionEnabled (imeOn); + if(imeOn) { + boolean phonetic = (mode & SWT.PHONETIC) != 0; + boolean nativecs = (mode & SWT.NATIVE) != 0; + // PHONETIC > NATIVE > ROMAN = ALPHA ; The former is stronger. + Character.Subset subset; + if ((mode & SWT.DBCS) != 0) { + // double byte characters + subset = InputSubset.FULLWIDTH_LATIN; + if (nativecs) { + subset = UnicodeBlock.HIRAGANA; + } + if (phonetic) { + subset = UnicodeBlock.KATAKANA; + } + } else { + // not double byte characters + subset = InputSubset.LATIN; + if (phonetic || nativecs) { + subset = InputSubset.HALFWIDTH_KATAKANA; + } + } + ic.setCharacterSubsets (new Character.Subset[] { subset }); + } +// if (!OS.IsDBLocale) return; +// boolean imeOn = mode != SWT.NONE && mode != SWT.ROMAN; +// int hIMC = OS.ImmGetContext (handle); +// OS.ImmSetOpenStatus (hIMC, imeOn); +// if (imeOn) { +// int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1]; +// if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) { +// int newBits = 0; +// int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA; +// if ((mode & SWT.PHONETIC) != 0) { +// newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE; +// oldBits = 0; +// } else { +// if ((mode & SWT.NATIVE) != 0) { +// newBits = OS.IME_CMODE_NATIVE; +// oldBits = OS.IME_CMODE_KATAKANA; +// } +// } +// if ((mode & SWT.DBCS) != 0) { +// newBits |= OS.IME_CMODE_FULLSHAPE; +// } else { +// oldBits |= OS.IME_CMODE_FULLSHAPE; +// } +// if ((mode & SWT.ROMAN) != 0) { +// newBits |= OS.IME_CMODE_ROMAN; +// } else { +// oldBits |= OS.IME_CMODE_ROMAN; +// } +// lpfdwConversion [0] |= newBits; lpfdwConversion [0] &= ~oldBits; +// OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]); +// } +// } +// OS.ImmReleaseContext (handle, hIMC); +} + +/** + * Sets the receiver's minimum size to the size specified by the arguments. + * If the new minimum size is larger than the current size of the receiver, + * the receiver is resized to the new minimum size. + * + * @param width the new minimum width for the receiver + * @param height the new minimum height for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setMinimumSize (int width, int height) { + checkWidget (); + if(Compatibility.IS_JAVA_5_OR_GREATER) { + handle.setMinimumSize(new java.awt.Dimension(width, height)); + } +// int widthLimit = 0, heightLimit = 0; +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; +// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) { +// widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK); +// if ((style & SWT.RESIZE) != 0) { +// heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK); +// } else { +// RECT rect = new RECT (); +// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); +// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); +// OS.AdjustWindowRectEx (rect, bits1, false, bits2); +// heightLimit = rect.bottom - rect.top; +// } +// } +// minWidth = Math.max (widthLimit, width); +// minHeight = Math.max (heightLimit, height); +// Point size = getSize (); +// int newWidth = Math.max (size.x, minWidth); +// int newHeight = Math.max (size.y, minHeight); +// if (minWidth <= widthLimit) minWidth = SWT.DEFAULT; +// if (minHeight <= heightLimit) minHeight = SWT.DEFAULT; +// if (newWidth != size.x || newHeight != size.y) setSize (newWidth, newHeight); +} + +/** + * Sets the receiver's minimum size to the size specified by the argument. + * If the new minimum size is larger than the current size of the receiver, + * the receiver is resized to the new minimum size. + * + * @param size the new minimum size for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setMinimumSize (Point size) { + checkWidget (); + if (size == null) error (SWT.ERROR_NULL_ARGUMENT); + setMinimumSize (size.x, size.y); +} + +//void setItemEnabled (int cmd, boolean enabled) { +// int hMenu = OS.GetSystemMenu (handle, false); +// if (hMenu == 0) return; +// int flags = OS.MF_ENABLED; +// if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED; +// OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags); +//} + +void setParent () { + /* Do nothing. Not necessary for Shells */ +} + +/** + * Sets the shape of the shell to the region specified + * by the argument. When the argument is null, the + * default shape of the shell is restored. The shell + * must be created with the style SWT.NO_TRIM in order + * to specify a region. + * + * @param region the region that defines the shape of the shell (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the region has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + * + */ +public void setRegion (Region region) { + checkWidget (); + if ((style & SWT.NO_TRIM) == 0) return; + if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + // TODO: how to implement that? +// int hRegion = 0; +// if (region != null) { +// hRegion = OS.CreateRectRgn (0, 0, 0, 0); +// OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR); +// } +// OS.SetWindowRgn (handle, hRegion, true); + this.region = region; +} + +//void setToolTipText (int hwnd, String text) { +// if (OS.IsWinCE) return; +// if (toolTipHandle == 0) { +// toolTipHandle = OS.CreateWindowEx ( +// 0, +// new TCHAR (0, OS.TOOLTIPS_CLASS, true), +// null, +// OS.TTS_ALWAYSTIP, +// OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, +// handle, +// 0, +// OS.GetModuleHandle (null), +// null); +// if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES); +// /* +// * Feature in Windows. Despite the fact that the +// * tool tip text contains \r\n, the tooltip will +// * not honour the new line unless TTM_SETMAXTIPWIDTH +// * is set. The fix is to set TTM_SETMAXTIPWIDTH to +// * a large value. +// */ +// OS.SendMessage (toolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); +// } +// TOOLINFO lpti = new TOOLINFO (); +// lpti.cbSize = TOOLINFO.sizeof; +// lpti.uId = hwnd; +// lpti.hwnd = handle; +// if (text == null) { +// OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti); +// } else { +// if (OS.SendMessage (toolTipHandle, OS.TTM_GETTOOLINFO, 0, lpti) != 0) { +// OS.SendMessage (toolTipHandle, OS.TTM_UPDATE, 0, 0); +// } else { +// lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS; +// lpti.lpszText = OS.LPSTR_TEXTCALLBACK; +// OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti); +// } +// } +//} +// +//void setToolTipText (NMTTDISPINFO lpnmtdi, byte [] buffer) { +// /* +// * Ensure that the current position of the mouse +// * is inside the client area of the shell. This +// * prevents tool tips from popping up over the +// * shell trimmings. +// */ +// if (!hasCursor ()) return; +// int hHeap = OS.GetProcessHeap (); +// if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip); +// int byteCount = buffer.length; +// lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory (lpstrTip, buffer, byteCount); +// lpnmtdi.lpszText = lpstrTip; +//} +// +//void setToolTipText (NMTTDISPINFO lpnmtdi, char [] buffer) { +// /* +// * Ensure that the current position of the mouse +// * is inside the client area of the shell. This +// * prevents tool tips from popping up over the +// * shell trimmings. +// */ +// if (!hasCursor ()) return; +// int hHeap = OS.GetProcessHeap (); +// if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip); +// int byteCount = buffer.length * 2; +// lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory (lpstrTip, buffer, byteCount); +// lpnmtdi.lpszText = lpstrTip; +//} + +Control initialFocusedControl; + +void setInitialFocusedControl(Control initialFocusedControl) { + this.initialFocusedControl = initialFocusedControl; +} + +public void setVisible (boolean visible) { + checkWidget (); + if(handle.isVisible() == visible) { + return; + } + boolean isFocusable = handle instanceof Window? ((Window)handle).getFocusableWindowState(): true; + handle.setVisible(visible); + if(visible) { + if(initialFocusedControl != null) { + initialFocusedControl.setFocus(); + initialFocusedControl = null; + } else { + if(isFocusable) { + if (!traverseGroup (true)) setFocus (); + } + } + layout(); + } +// if (drawCount != 0) { +// if (((state & HIDDEN) == 0) == visible) return; +// } else { +// if (visible == OS.IsWindowVisible (handle)) return; +// } +// +// /* +// * Feature in Windows. When ShowWindow() is called used to hide +// * a window, Windows attempts to give focus to the parent. If the +// * parent is disabled by EnableWindow(), focus is assigned to +// * another windows on the desktop. This means that if you hide +// * a modal window before the parent is enabled, the parent will +// * not come to the front. The fix is to change the modal state +// * before hiding or showing a window so that this does not occur. +// */ +// int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL; +// if ((style & mask) != 0) { +// if (visible) { +// display.setModalShell (this); +// Control control = display._getFocusControl (); +// if (control != null && !control.isActive ()) bringToTop (); +// int hwndShell = OS.GetActiveWindow (); +// if (hwndShell == 0) { +// if (parent != null) hwndShell = parent.handle; +// } +// if (hwndShell != 0) { +// OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0); +// } +// OS.ReleaseCapture (); +// } else { +// display.clearModal (this); +// } +// } else { +// updateModal (); +// } +// +// /* +// * Bug in Windows. Calling ShowOwnedPopups() to hide the +// * child windows of a hidden window causes the application +// * to be deactivated. The fix is to call ShowOwnedPopups() +// * to hide children before hiding the parent. +// */ +// if (showWithParent && !visible) { +// if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, false); +// } +// super.setVisible (visible); +// if (isDisposed ()) return; +// if (showWithParent == visible) return; +// showWithParent = visible; +// if (visible) { +// if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true); +// } +} + +//boolean translateAccelerator (MSG msg) { +// if (!isEnabled () || !isActive ()) return false; +// if (menuBar != null && !menuBar.isEnabled ()) return false; +// return translateMDIAccelerator (msg) || translateMenuAccelerator (msg); +//} + +boolean traverseEscape () { + if (parent == null) return false; + if (!isVisible () || !isEnabled ()) return false; + close (); + return true; +} + +//void updateModal () { +// if (Display.TrimEnabled) { +// setItemEnabled (OS.SC_CLOSE, isActive ()); +// } else { +// OS.EnableWindow (handle, isActive ()); +// } +//} +// +//CREATESTRUCT widgetCreateStruct () { +// return null; +//} +// +//int widgetParent () { +// if (handle != 0) return handle; +// return parent != null ? parent.handle : 0; +//} +// +//int widgetExtStyle () { +// int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD; +// if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW; +// +// /* +// * Feature in Windows. When a window that does not have a parent +// * is created, it is automatically added to the Windows Task Bar, +// * even when it has no title. The fix is to use WS_EX_TOOLWINDOW +// * which does not cause the window to appear in the Task Bar. +// */ +// if (!OS.IsWinCE) { +// if (parent == null) { +// if ((style & SWT.ON_TOP) != 0) { +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; +// if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) { +// bits |= OS.WS_EX_TOOLWINDOW; +// } +// } +// } +// } +// +// /* +// * Bug in Windows 98 and NT. Creating a window with the +// * WS_EX_TOPMOST extended style can result in a dialog shell +// * being moved behind its parent. The exact case where this +// * happens is a shell with two dialog shell children where +// * each dialog child has another hidden dialog child with +// * the WS_EX_TOPMOST extended style. Clicking on either of +// * the visible dialogs causes them to become active but move +// * to the back, behind the parent shell. The fix is to +// * disallow the WS_EX_TOPMOST extended style on Windows 98 +// * and NT. +// */ +// if (parent != null) { +// if (OS.IsWin95) return bits; +// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) { +// return bits; +// } +// } +// if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST; +// return bits; +//} +// +//TCHAR windowClass () { +// if (OS.IsSP) return DialogClass; +// if ((style & SWT.TOOL) != 0) { +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; +// if ((style & trim) == 0) return display.windowShadowClass; +// } +// return parent != null ? DialogClass : super.windowClass (); +//} +// +//int windowProc () { +// if (OS.IsSP) return DialogProc; +// if ((style & SWT.TOOL) != 0) { +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; +// if ((style & trim) == 0) super.windowProc (); +// } +// return parent != null ? DialogProc : super.windowProc (); +//} +// +//int widgetStyle () { +// int bits = super.widgetStyle (); +// if (handle != 0) return bits | OS.WS_CHILD; +// bits &= ~OS.WS_CHILD; +// /* +// * Feature in WinCE. Calling CreateWindowEx () with WS_OVERLAPPED +// * and a parent window causes the new window to become a WS_CHILD of +// * the parent instead of a dialog child. The fix is to use WS_POPUP +// * for a window with a parent. +// * +// * Feature in WinCE PPC. A window without a parent with WS_POPUP +// * always shows on top of the Pocket PC 'Today Screen'. The fix +// * is to not set WS_POPUP for a window without a parent on WinCE +// * devices. +// * +// * NOTE: WS_POPUP causes CreateWindowEx () to ignore CW_USEDEFAULT +// * and causes the default window location and size to be zero. +// */ +// if (OS.IsWinCE) { +// if (OS.IsSP) return bits | OS.WS_POPUP; +// return parent == null ? bits : bits | OS.WS_POPUP; +// } +// +// /* +// * Use WS_OVERLAPPED for all windows, either dialog or top level +// * so that CreateWindowEx () will respect CW_USEDEFAULT and set +// * the default window location and size. +// * +// * NOTE: When a WS_OVERLAPPED window is created, Windows gives +// * the new window WS_CAPTION style bits. These two constants are +// * as follows: +// * +// * WS_OVERLAPPED = 0 +// * WS_CAPTION = WS_BORDER | WS_DLGFRAME +// * +// */ +// return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION; +//} +// +//LRESULT WM_ACTIVATE (int wParam, int lParam) { +// if (OS.IsPPC) { +// /* +// * Note: this does not work when we get WM_ACTIVATE prior +// * to adding a listener. +// */ +// if (hooks (SWT.HardKeyDown) || hooks (SWT.HardKeyUp)) { +// int fActive = wParam & 0xFFFF; +// int hwnd = fActive != 0 ? handle : 0; +// for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) { +// OS.SHSetAppKeyWndAssoc ((byte) bVk, hwnd); +// } +// } +// /* Restore SIP state when window is activated */ +// if ((wParam & 0xFFFF) != 0) { +// OS.SHSipPreference (handle, psai.fSipUp == 0 ? OS.SIP_DOWN : OS.SIP_UP); +// } +// } +// +// /* +// * Bug in Windows XP. When a Shell is deactivated, the +// * IME composition window does not go away. This causes +// * repaint issues. The fix is to close the IME ourselves +// * when the Shell is deactivated. +// * +// * Note. When the Shell is reactivated, the text in the +// * composition window has been lost. +// */ +// if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) { +// if ((wParam & 0xFFFF) == 0 && OS.IsDBLocale && hIMC != 0) { +// OS.ImmSetOpenStatus (hIMC, false); +// } +// } +// +// LRESULT result = super.WM_ACTIVATE (wParam, lParam); +// if (parent != null) return LRESULT.ZERO; +// return result; +//} +// +//LRESULT WM_COMMAND (int wParam, int lParam) { +// if (OS.IsPPC) { +// /* +// * Note in WinCE PPC: Close the Shell when the "Done Button" has +// * been pressed. lParam is either 0 (PocketPC 2002) or the handle +// * to the Shell (PocketPC). +// */ +// int loWord = wParam & 0xFFFF; +// if (loWord == OS.IDOK && (lParam == 0 || lParam == handle)) { +// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); +// return LRESULT.ZERO; +// } +// } +// /* +// * Feature in Windows. On PPC, the menu is not actually an HMENU. +// * By observation, it is a tool bar that is configured to look like +// * a menu. Therefore, when the PPC menu sends WM_COMMAND messages, +// * lParam is not zero because the WM_COMMAND was not sent from a menu. +// * Sub menu item events originate from the menu bar. Top menu items +// * events originate from a tool bar. The fix is to detect the source +// * of the WM_COMMAND and set lParam to zero to pretend that the message +// * came from a real Windows menu, not a tool bar. +// */ +// if (OS.IsPPC || OS.IsSP) { +// if (menuBar != null) { +// int hwndCB = menuBar.hwndCB; +// if (lParam != 0 && hwndCB != 0) { +// if (lParam == hwndCB) { +// return super.WM_COMMAND (wParam, 0); +// } else { +// int hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD); +// if (lParam == hwndChild) return super.WM_COMMAND (wParam, 0); +// } +// } +// } +// } +// return super.WM_COMMAND (wParam, lParam); +//} +// +//LRESULT WM_DESTROY (int wParam, int lParam) { +// LRESULT result = super.WM_DESTROY (wParam, lParam); +// /* +// * When the shell is a WS_CHILD window of a non-SWT +// * window, the destroy code does not get called because +// * the non-SWT window does not call dispose (). Instead, +// * the destroy code is called here in WM_DESTROY. +// */ +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// if ((bits & OS.WS_CHILD) != 0) { +// releaseChild (); +// releaseResources (); +// } +// return result; +//} +// +//LRESULT WM_ENTERIDLE (int wParam, int lParam) { +// LRESULT result = super.WM_ENTERIDLE (wParam, lParam); +// if (result != null) return result; +// if (OS.IsWinCE) { +// if (display.runAsyncMessages (true)) display.wakeThread (); +// } +// return result; +//} +// +//LRESULT WM_GETMINMAXINFO (int wParam, int lParam) { +// LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam); +// if (result != null) return result; +// if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) { +// MINMAXINFO info = new MINMAXINFO (); +// OS.MoveMemory (info, lParam, MINMAXINFO.sizeof); +// if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth; +// if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight; +// OS.MoveMemory (lParam, info, MINMAXINFO.sizeof); +// return LRESULT.ZERO; +// } +// return result; +//} +// +//LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) { +// LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Check for WM_MOUSEACTIVATE when an MDI shell is active +// * and stop the normal shell activation but allow the mouse +// * down to be delivered. +// */ +// int hittest = (short) (lParam & 0xFFFF); +// switch (hittest) { +// case OS.HTERROR: +// case OS.HTTRANSPARENT: +// case OS.HTNOWHERE: +// break; +// default: { +// Control control = display._getFocusControl (); +// if (control != null) { +// Decorations decorations = control.menuShell (); +// if (decorations.getShell () == this && decorations != this) { +// display.ignoreRestoreFocus = true; +// display.lastHittest = hittest; +// display.lastHittestControl = null; +// if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) { +// display.lastHittestControl = control; +// return null; +// } +// if (OS.IsWin95 && hittest == OS.HTCAPTION) { +// display.lastHittestControl = control; +// } +// return new LRESULT (OS.MA_NOACTIVATE); +// } +// } +// } +// } +// if (hittest == OS.HTMENU) return null; +// +// /* +// * Get the current location of the cursor, +// * not the location of the cursor when the +// * WM_MOUSEACTIVATE was generated. This is +// * strictly incorrect but is necessary in +// * order to support Activate and Deactivate +// * events for embedded widgets that have +// * their own event loop. In that case, the +// * cursor location reported by GetMessagePos +// * is the one for our event loop, not the +// * embedded widget's event loop. +// */ +// POINT pt = new POINT (); +// if (!OS.GetCursorPos (pt)) { +// int pos = OS.GetMessagePos (); +// pt.x = (short) (pos & 0xFFFF); +// pt.y = (short) (pos >> 16); +// } +// int hwnd = OS.WindowFromPoint (pt); +// if (hwnd == 0) return null; +// Control control = display.findControl (hwnd); +// setActiveControl (control); +// +// /* +// * This code is intentionally commented. On some platforms, +// * shells that are created with SWT.NO_TRIM won't take focus +// * when the user clicks in the client area or on the border. +// * This behavior is usedful when emulating tool tip shells +// * Until this behavior is specified, this code will remain +// * commented. +// */ +//// if ((style & SWT.NO_TRIM) != 0) { +//// if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) { +//// return new LRESULT (OS.MA_NOACTIVATE); +//// } +//// } +// return null; +//} +// +//LRESULT WM_NCHITTEST (int wParam, int lParam) { +// if (!OS.IsWindowEnabled (handle)) return null; +// if (!isEnabled () || !isActive ()) { +// if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE); +// int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); +// if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER; +// return new LRESULT (hittest); +// } +// if (menuBar != null && !menuBar.getEnabled ()) { +// int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); +// if (hittest == OS.HTMENU) hittest = OS.HTBORDER; +// return new LRESULT (hittest); +// } +// return null; +//} +// +//LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) { +// LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam); +// if (result != null) return result; +// /* +// * When the normal activation was interruped in WM_MOUSEACTIVATE +// * because the active shell was an MDI shell, set the active window +// * to the top level shell but lock the active window and stop focus +// * changes. This allows the user to interact the top level shell +// * in the normal manner. +// */ +// if (!display.ignoreRestoreFocus) return result; +// Display display = this.display; +// int hwndActive = 0; +// boolean fixActive = OS.IsWin95 && display.lastHittest == OS.HTCAPTION; +// if (fixActive) hwndActive = OS.SetActiveWindow (handle); +// display.lockActiveWindow = true; +// int code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam); +// display.lockActiveWindow = false; +// if (fixActive) OS.SetActiveWindow (hwndActive); +// Control focusControl = display.lastHittestControl; +// if (focusControl != null && !focusControl.isDisposed ()) { +// focusControl.setFocus (); +// } +// display.lastHittestControl = null; +// display.ignoreRestoreFocus = false; +// return new LRESULT (code); +//} +// +//LRESULT WM_PALETTECHANGED (int wParam, int lParam) { +// if (wParam != handle) { +// int hPalette = display.hPalette; +// if (hPalette != 0) return selectPalette (hPalette); +// } +// return super.WM_PALETTECHANGED (wParam, lParam); +//} +// +//LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) { +// int hPalette = display.hPalette; +// if (hPalette != 0) return selectPalette (hPalette); +// return super.WM_QUERYNEWPALETTE (wParam, lParam); +//} +// +//LRESULT WM_SETCURSOR (int wParam, int lParam) { +// /* +// * Feature in Windows. When the shell is disabled +// * by a Windows standard dialog (like a MessageBox +// * or FileDialog), clicking in the shell does not +// * bring the shell or the dialog to the front. The +// * fix is to detect this case and bring the shell +// * forward. +// */ +// int msg = (short) (lParam >> 16); +// if (msg == OS.WM_LBUTTONDOWN) { +// if (!Display.TrimEnabled) { +// Shell modalShell = display.getModalShell (); +// if (modalShell != null && !isActive ()) { +// int hwndModal = modalShell.handle; +// if (OS.IsWindowEnabled (hwndModal)) { +// OS.SetActiveWindow (hwndModal); +// } +// } +// } +// if (!OS.IsWindowEnabled (handle)) { +// if (!OS.IsWinCE) { +// int hwndPopup = OS.GetLastActivePopup (handle); +// if (hwndPopup != 0 && hwndPopup != handle) { +// if (display.getControl (hwndPopup) == null) { +// if (OS.IsWindowEnabled (hwndPopup)) { +// OS.SetActiveWindow (hwndPopup); +// } +// } +// } +// } +// } +// } +// /* +// * When the shell that contains a cursor is disabled, +// * WM_SETCURSOR is called with HTERROR. Normally, +// * when a control is disabled, the parent will get +// * mouse and cursor events. In the case of a disabled +// * shell, there is no enabled parent. In order to +// * show the cursor when a shell is disabled, it is +// * necessary to override WM_SETCURSOR when called +// * with HTERROR to set the cursor but only when the +// * mouse is in the client area of the shell. +// */ +// int hitTest = (short) (lParam & 0xFFFF); +// if (hitTest == OS.HTERROR) { +// if (!getEnabled ()) { +// Control control = display.getControl (wParam); +// if (control == this && cursor != null) { +// POINT pt = new POINT (); +// if (OS.GetCursorPos (pt)) { +// OS.ScreenToClient (handle, pt); +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// if (OS.PtInRect (rect, pt)) { +// OS.SetCursor (cursor.handle); +// switch (msg) { +// case OS.WM_LBUTTONDOWN: +// case OS.WM_RBUTTONDOWN: +// case OS.WM_MBUTTONDOWN: +// case OS.WM_XBUTTONDOWN: +// OS.MessageBeep (OS.MB_OK); +// } +// return LRESULT.ONE; +// } +// } +// } +// } +// } +// return super.WM_SETCURSOR (wParam, lParam); +//} +// +//LRESULT WM_SETTINGCHANGE (int wParam, int lParam) { +// LRESULT result = super.WM_SETTINGCHANGE (wParam, lParam); +// if (result != null) return result; +// if (OS.IsPPC) { +// if (wParam == OS.SPI_SETSIPINFO) { +// /* +// * The SIP is in a new state. Cache its new value. +// * Resize the Shell if it has the style SWT.RESIZE. +// * Note that SHHandleWMSettingChange resizes the +// * Shell and also updates the cached state. +// */ +// if ((style & SWT.RESIZE) != 0) { +// OS.SHHandleWMSettingChange (handle, wParam, lParam, psai); +// return LRESULT.ZERO; +// } else { +// SIPINFO pSipInfo = new SIPINFO (); +// pSipInfo.cbSize = SIPINFO.sizeof; +// OS.SipGetInfo (pSipInfo); +// psai.fSipUp = pSipInfo.fdwFlags & OS.SIPF_ON; +// } +// } +// } +// return result; +//} +// +//LRESULT WM_SHOWWINDOW (int wParam, int lParam) { +// LRESULT result = super.WM_SHOWWINDOW (wParam, lParam); +// if (result != null) return result; +// /* +// * Bug in Windows. If the shell is hidden while the parent +// * is iconic, Windows shows the shell when the parent is +// * deiconified. This does not happen if the shell is hidden +// * while the parent is not an icon. The fix is to track +// * visible state for the shell and refuse to show the shell +// * when the parent is shown. +// */ +// if (lParam == OS.SW_PARENTOPENING) { +// Control control = this; +// while (control != null) { +// Shell shell = control.getShell (); +// if (!shell.showWithParent) return LRESULT.ZERO; +// control = control.parent; +// } +// } +// return result; +//} +// +//LRESULT WM_SYSCOMMAND (int wParam, int lParam) { +// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam); +// //This code is intentionally commented +//// if (result != null) return result; +//// /* +//// * Feature in Windows. When a window is minimized, the memory +//// * for the working set of the process. For applications that +//// * use a lot of memory, when the window is restored, it can take +//// * a long time (sometimes minutes) before the application becomes +//// * responsive. The fix is to intercept WM_SYSCOMMAND looking +//// * for SC_MINIMIZE and use ShowWindow() with SW_SHOWMINIMIZED to +//// * minimize the window rather than allowing the default window +//// * proc to do it when more that 64Meg of memory is being used. +//// * +//// * NOTE: The default window proc activates the next top-level +//// * window in the Z order while ShowWindow () with SW_SHOWMINIMIZED +//// * does not. There is no fix for this at this time. +//// */ +//// int cmd = wParam & 0xFFF0; +//// switch (cmd) { +//// case OS.SC_MINIMIZE: +//// long memory = Runtime.getRuntime ().totalMemory (); +//// if (memory > 64000000) { +//// OS.ShowWindow (handle, OS.SW_SHOWMINIMIZED); +//// return LRESULT.ZERO; +//// } +//// } +// return result; +//} +// +//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { +// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam); +// if (result != null) return result; +// WINDOWPOS lpwp = new WINDOWPOS (); +// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof); +// if ((lpwp.flags & OS.SWP_NOSIZE) == 0) { +// lpwp.cx = Math.max (lpwp.cx, minWidth); +// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; +// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) { +// lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK)); +// } +// lpwp.cy = Math.max (lpwp.cy, minHeight); +// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) { +// if ((style & SWT.RESIZE) != 0) { +// lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK)); +// } else { +// RECT rect = new RECT (); +// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); +// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); +// OS.AdjustWindowRectEx (rect, bits1, false, bits2); +// lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top); +// } +// } +// OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof); +// } +// return result; +//} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Traverse)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_ACTIVATED: if(!hooks(SWT.Activate)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_DEACTIVATED: if(!hooks(SWT.Deactivate)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_CLOSED: if(!hooks(SWT.Close)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_ICONIFIED: if(!hooks(SWT.Iconify)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_DEICONIFIED: if(!hooks(SWT.Deiconify)) { super.processEvent(e); return; } break; + case WindowEvent.WINDOW_CLOSING: if(!isEnabled()) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case WindowEvent.WINDOW_ACTIVATED: sendEvent(SWT.Activate); break; + case WindowEvent.WINDOW_DEACTIVATED: sendEvent(SWT.Deactivate); break; + case WindowEvent.WINDOW_CLOSED: sendEvent(SWT.Close); break; + case WindowEvent.WINDOW_ICONIFIED: sendEvent(SWT.Iconify); break; + case WindowEvent.WINDOW_DEICONIFIED: sendEvent(SWT.Deiconify); break; + case WindowEvent.WINDOW_CLOSING: + if(isEnabled()) { + closeWidget(); + } + break; + case ActionEvent.ACTION_PERFORMED: + Event event = new Event(); + event.detail = SWT.TRAVERSE_ESCAPE; + sendEvent(SWT.Traverse, event); + if(event.doit) { + close(); + } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java new file mode 100644 index 00000000000..c488a80a4e5 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java @@ -0,0 +1,470 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Container; +import java.awt.event.AdjustmentEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.internal.swing.CSlider; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class are selectable user interface + * objects that represent a range of positive, numeric values. + *

    + * At any given moment, a given slider will have a + * single 'selection' that is considered to be its + * value, which is constrained to be within the range of + * values the slider represents (that is, between its + * minimum and maximum values). + *

    + * Typically, sliders will be made up of five areas: + *

      + *
    1. an arrow button for decrementing the value
    2. + *
    3. a page decrement area for decrementing the value by a larger amount
    4. + *
    5. a thumb for modifying the value by mouse dragging
    6. + *
    7. a page increment area for incrementing the value by a larger amount
    8. + *
    9. an arrow button for incrementing the value
    10. + *
    + * Based on their style, sliders are either HORIZONTAL + * (which have a left facing button for decrementing the value and a + * right facing button for incrementing it) or VERTICAL + * (which have an upward facing button for decrementing the value + * and a downward facing buttons for incrementing it). + *

    + * On some platforms, the size of the slider's thumb can be + * varied relative to the magnitude of the range of values it + * represents (that is, relative to the difference between its + * maximum and minimum values). Typically, this is used to + * indicate some proportional value such as the ratio of the + * visible area of a document to the total amount of space that + * it would take to display it. SWT supports setting the thumb + * size even if the underlying platform does not, but in this + * case the appearance of the slider will not change. + *

    + *
    + *
    Styles:
    + *
    HORIZONTAL, VERTICAL
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @see ScrollBar + */ +public class Slider extends Control { + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Slider (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's value changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the event object detail field contains one of the following values: + * 0 - for the end of a drag. + * SWT.NONE - for the end of a drag. + * SWT.DRAG. + * SWT.HOME. + * SWT.END. + * SWT.ARROW_DOWN. + * SWT.ARROW_UP. + * SWT.PAGE_DOWN. + * SWT.PAGE_UP. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); +} + +Container createHandle () { + return (Container)CSlider.Factory.newInstance(this, style); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed. + * + * @return the increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getIncrement () { + checkWidget (); + return ((CSlider)handle).getUnitIncrement(); +} + +/** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMaximum () { + checkWidget (); + return ((CSlider)handle).getMaximum(); +} + +/** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMinimum () { + checkWidget (); + return ((CSlider)handle).getMinimum(); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected. + * + * @return the page increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getPageIncrement () { + checkWidget (); + return ((CSlider)handle).getBlockIncrement(); +} + +/** + * Returns the 'selection', which is the receiver's value. + * + * @return the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelection () { + checkWidget (); + return ((CSlider)handle).getValue(); +} + +/** + * Returns the size of the receiver's thumb relative to the + * difference between its maximum and minimum values. + * + * @return the thumb value + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getThumb () { + checkWidget (); + return ((CSlider)handle).getVisibleAmount(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's value changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the up/down (or right/left) arrows + * are pressed to the argument, which must be at least + * one. + * + * @param value the new increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setIncrement (int value) { + checkWidget (); + if (value < 1) return; + ((CSlider)handle).setUnitIncrement(value); +} + +/** + * Sets the maximum. If this value is negative or less than or + * equal to the minimum, the value is ignored. If necessary, first + * the thumb and then the selection are adjusted to fit within the + * new range. + * + * @param value the new maximum, which must be greater than the current minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMaximum (int value) { + checkWidget (); + if (value < 0) return; + ((CSlider)handle).setMaximum(value); +} + +/** + * Sets the minimum value. If this value is negative or greater + * than or equal to the maximum, the value is ignored. If necessary, + * first the thumb and then the selection are adjusted to fit within + * the new range. + * + * @param value the new minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMinimum (int value) { + checkWidget (); + if (value < 0) return; + ((CSlider)handle).setMinimum(value); +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the page increment/decrement areas + * are selected to the argument, which must be at least + * one. + * + * @param value the page increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPageIncrement (int value) { + checkWidget (); + if (value < 1) return; + ((CSlider)handle).setBlockIncrement(value); +} + +/** + * Sets the 'selection', which is the receiver's + * value, to the argument which must be greater than or equal + * to zero. + * + * @param value the new selection (must be zero or greater) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int value) { + checkWidget (); + ((CSlider)handle).setValue(value); +} + +/** + * Sets the size of the receiver's thumb relative to the + * difference between its maximum and minimum values. This new + * value will be ignored if it is less than one, and will be + * clamped if it exceeds the receiver's current range. + * + * @param value the new thumb value, which must be at least one and not + * larger than the size of the current range + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setThumb (int value) { + checkWidget (); + if (value < 1) return; + ((CSlider)handle).setVisibleAmount(value); +} + +/** + * Sets the receiver's selection, minimum value, maximum + * value, thumb, increment and page increment all at once. + *

    + * Note: This is similar to setting the values individually + * using the appropriate methods, but may be implemented in a + * more efficient fashion on some platforms. + *

    + * + * @param selection the new selection value + * @param minimum the new minimum value + * @param maximum the new maximum value + * @param thumb the new thumb value + * @param increment the new increment value + * @param pageIncrement the new pageIncrement value + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) { + checkWidget (); + if (minimum < 0) return; + if (maximum < 0) return; + if (thumb < 1) return; + if (increment < 1) return; + if (pageIncrement < 1) return; + CSlider cSlider = (CSlider)handle; + cSlider.setValues(selection, thumb, minimum, maximum); + cSlider.setUnitIncrement(increment); + cSlider.setBlockIncrement(increment); +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: + Event event = new Event (); + event.detail = SWT.DRAG; + switch(((AdjustmentEvent)e).getAdjustmentType()) { + case AdjustmentEvent.BLOCK_DECREMENT: + event.detail = SWT.PAGE_DOWN; + break; + case AdjustmentEvent.BLOCK_INCREMENT: + event.detail = SWT.PAGE_UP; + break; + case AdjustmentEvent.UNIT_DECREMENT: + event.detail = SWT.ARROW_DOWN; + break; + case AdjustmentEvent.UNIT_INCREMENT: + event.detail = SWT.ARROW_UP; + break; + } + sendEvent (SWT.Selection, event); + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java new file mode 100644 index 00000000000..7f79f2d1c4f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java @@ -0,0 +1,1051 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Container; +import java.util.EventObject; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.DocumentEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CSpinner; +import org.eclipse.swt.internal.swing.TextFilterEvent; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class are selectable user interface + * objects that allow the user to enter and modify numeric + * values. + *

    + *

    + *
    Styles:
    + *
    READ_ONLY, WRAP
    + *
    Events:
    + *
    Selection, Modify
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @since 3.1 + */ +public class Spinner extends Composite { +// boolean ignoreModify; + int pageIncrement; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#READ_ONLY + * @see SWT#WRAP + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Spinner (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +static int checkStyle (int style) { + /* + * Even though it is legal to create this widget + * with scroll bars, they serve no useful purpose + * because they do not automatically scroll the + * widget's client area. The fix is to clear + * the SWT style. + */ + return style & ~(SWT.H_SCROLL | SWT.V_SCROLL); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CSpinner.Factory.newInstance(this, style); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is modified, by sending + * it one of the messages defined in the ModifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #removeModifyListener + */ +public void addModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Modify, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is not called for texts. + * widgetDefaultSelected is typically called when ENTER is pressed in a single-line text. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is verified, by sending + * it one of the messages defined in the VerifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #removeVerifyListener + */ +void addVerifyListener (VerifyListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Verify, typedListener); +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// int width = 0, height = 0; +// if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { +// int newFont, oldFont = 0; +// int hDC = OS.GetDC (hwndText); +// newFont = OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// height = tm.tmHeight; +// RECT rect = new RECT (); +// int [] max = new int [1]; +// OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max); +// TCHAR buffer = new TCHAR (getCodePage (), String.valueOf (max [0]), false); +// int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX; +// OS.DrawText (hDC, buffer, buffer.length (), rect, flags); +// width = rect.right - rect.left; +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (hwndText, hDC); +// } +// if (width == 0) width = DEFAULT_WIDTH; +// if (height == 0) height = DEFAULT_HEIGHT; +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// Rectangle trim = computeTrim (0, 0, width, height); +// if (hHint == SWT.DEFAULT) { +// trim.height = Math.max (trim.height, OS.GetSystemMetrics (OS.SM_CYVSCROLL)); +// } +// return new Point (trim.width, trim.height); +//} +// +//public Rectangle computeTrim (int x, int y, int width, int height) { +// checkWidget (); +// +// /* Get the trim of the text control */ +// RECT rect = new RECT (); +// OS.SetRect (rect, x, y, x + width, y + height); +// int bits0 = OS.GetWindowLong (hwndText, OS.GWL_STYLE); +// int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE); +// OS.AdjustWindowRectEx (rect, bits0, false, bits1); +// width = rect.right - rect.left; +// height = rect.bottom - rect.top; +// +// /* +// * The preferred height of a single-line text widget +// * has been hand-crafted to be the same height as +// * the single-line text widget in an editable combo +// * box. +// */ +// int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0); +// x -= margins & 0xFFFF; +// width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); +// if ((style & SWT.BORDER) != 0) { +// x -= 1; +// y -= 1; +// width += 2; +// height += 2; +// } +// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// return new Rectangle (x, y, width, height); +//} + +public Point computeSize (int wHint, int hHint, boolean changed) { + Point p = super.computeSize(wHint, hHint, changed); + return new Point(p.x, handle.getPreferredSize().height); +} + +/** + * Copies the selected text. + *

    + * The current selection is copied to the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void copy () { + checkWidget (); + ((CSpinner)handle).copy(); +} + +/** + * Cuts the selected text. + *

    + * The current selection is first copied to the + * clipboard and then deleted from the widget. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void cut () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CSpinner)handle).cut(); +} + +/** + * Returns the number of decimal places used by the receiver. + * + * @return the digits + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getDigits () { + checkWidget (); + return ((CSpinner)handle).getDigitCount(); +} + +/** + * Returns the amount that the receiver's value will be + * modified by when the up/down arrows are pressed. + * + * @return the increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getIncrement () { + checkWidget (); + return ((CSpinner)handle).getStepSize(); +} + +/** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMaximum () { + checkWidget (); + return ((CSpinner)handle).getMaximum(); +} + +/** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getMinimum () { + checkWidget (); + return ((CSpinner)handle).getMinimum(); +} + +/** + * Returns the amount that the receiver's position will be + * modified by when the page up/down keys are pressed. + * + * @return the page increment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getPageIncrement () { + checkWidget (); + return pageIncrement; +} + +/** + * Returns the selection, which is the receiver's position. + * + * @return the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelection () { + checkWidget (); + return ((CSpinner)handle).getSelectedValue(); +} + +/** + * Pastes text from clipboard. + *

    + * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void paste () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CSpinner)handle).paste(); +} + +//void releaseHandle () { +// super.releaseHandle (); +// hwndText = hwndUpDown = 0; +//} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #addModifyListener + */ +public void removeModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Modify, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is verified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #addVerifyListener + */ +void removeVerifyListener (VerifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Verify, listener); +} + +//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) { +// if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) { +// return false; +// } +// if ((style & SWT.READ_ONLY) != 0) return true; +// if (type != SWT.KeyDown) return true; +// if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) { +// return true; +// } +// if (event.character == 0) return true; +//// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true; +// char key = event.character; +// int stateMask = event.stateMask; +// +// /* +// * Disable all magic keys that could modify the text +// * and don't send events when Alt, Shift or Ctrl is +// * pressed. +// */ +// switch (msg) { +// case OS.WM_CHAR: +// if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break; +// // FALL THROUGH +// case OS.WM_KEYDOWN: +// if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false; +// break; +// } +// +// /* +// * If the left button is down, the text widget refuses the character. +// */ +// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) { +// return true; +// } +// +// /* Verify the character */ +// String oldText = ""; +// int [] start = new int [1], end = new int [1]; +// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end); +// switch (key) { +// case 0x08: /* Bs */ +// if (start [0] == end [0]) { +// if (start [0] == 0) return true; +// start [0] = start [0] - 1; +// if (OS.IsDBLocale) { +// int [] newStart = new int [1], newEnd = new int [1]; +// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]); +// OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd); +// if (start [0] != newStart [0]) start [0] = start [0] - 1; +// } +// start [0] = Math.max (start [0], 0); +// } +// break; +// case 0x7F: /* Del */ +// if (start [0] == end [0]) { +// int length = OS.GetWindowTextLength (hwndText); +// if (start [0] == length) return true; +// end [0] = end [0] + 1; +// if (OS.IsDBLocale) { +// int [] newStart = new int [1], newEnd = new int [1]; +// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]); +// OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd); +// if (end [0] != newEnd [0]) end [0] = end [0] + 1; +// } +// end [0] = Math.min (end [0], length); +// } +// break; +// case '\r': /* Return */ +// return true; +// default: /* Tab and other characters */ +// if (key != '\t' && key < 0x20) return true; +// oldText = new String (new char [] {key}); +// break; +// } +// String newText = verifyText (oldText, start [0], end [0], event); +// if (newText == null) return false; +// if (newText == oldText) return true; +// TCHAR buffer = new TCHAR (getCodePage (), newText, true); +// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]); +// OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer); +// return false; +//} + + +/** + * Sets the number of decimal places used by the receiver. + *

    + * The digit setting is used to allow for floating point values in the receiver. + * For example, to set the selection to a floating point value of 1.37 call setDigits() with + * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value + * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all + * numeric APIs. + *

    + * + * @param value the new digits (must be greater than or equal to zero) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the value is less than zero
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDigits (int value) { + checkWidget (); + if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT); + ((CSpinner)handle).setDigitCount(value); +} + +/** + * Sets the amount that the receiver's value will be + * modified by when the up/down arrows are pressed to + * the argument, which must be at least one. + * + * @param value the new increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setIncrement (int value) { + checkWidget (); + if (value < 1) return; + ((CSpinner)handle).setStepSize(value); +} + +/** + * Sets the maximum value that the receiver will allow. This new + * value will be ignored if it is not greater than the receiver's current + * minimum value. If the new maximum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new maximum, which must be greater than the current minimum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMaximum (int value) { + checkWidget (); + if (value < 0) return; + ((CSpinner)handle).setMaximum(value); +} + +/** + * Sets the minimum value that the receiver will allow. This new + * value will be ignored if it is negative or is not less than the receiver's + * current maximum value. If the new minimum is applied then the receiver's + * selection value will be adjusted if necessary to fall within its new range. + * + * @param value the new minimum, which must be nonnegative and less than the current maximum + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMinimum (int value) { + checkWidget (); + if (value < 0) return; + ((CSpinner)handle).setMinimum(value); +} + +/** + * Sets the amount that the receiver's position will be + * modified by when the page up/down keys are pressed + * to the argument, which must be at least one. + * + * @param value the page increment (must be greater than zero) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setPageIncrement (int value) { + checkWidget (); + if (value < 1) return; + pageIncrement = value; +} + +/** + * Sets the selection, which is the receiver's + * position, to the argument. If the argument is not within + * the range specified by minimum and maximum, it will be + * adjusted to fall within this range. + * + * @param value the new selection (must be zero or greater) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int value) { + checkWidget (); + ((CSpinner)handle).setSelectedValue(value); +} + +/** + * Sets the receiver's selection, minimum value, maximum + * value, digits, increment and page increment all at once. + *

    + * Note: This is similar to setting the values individually + * using the appropriate methods, but may be implemented in a + * more efficient fashion on some platforms. + *

    + * + * @param selection the new selection value + * @param minimum the new minimum value + * @param maximum the new maximum value + * @param digits the new digits value + * @param increment the new increment value + * @param pageIncrement the new pageIncrement value + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) { + checkWidget (); + if (minimum < 0) return; + if (maximum <= minimum) return; + if (digits < 0) return; + if (increment < 1) return; + if (pageIncrement < 1) return; + selection = Math.min (Math.max (minimum, selection), maximum); + setIncrement (increment); + setPageIncrement(pageIncrement); + setDigits(digits); + setSelection (selection); +} + +//String verifyText (String string, int start, int end, Event keyEvent) { +// Event event = new Event (); +// event.text = string; +// event.start = start; +// event.end = end; +// if (keyEvent != null) { +// event.character = keyEvent.character; +// event.keyCode = keyEvent.keyCode; +// event.stateMask = keyEvent.stateMask; +// } +// int index = 0; +// while (index < string.length ()) { +// if (!Character.isDigit (string.charAt (index))) break; +// index++; +// } +// event.doit = index == string.length (); +// if (OS.IsDBLocale) { +// event.start = mbcsToWcsPos (start); +// event.end = mbcsToWcsPos (end); +// } +// sendEvent (SWT.Verify, event); +// if (!event.doit || isDisposed ()) return null; +// return event.text; +//} + +//int windowProc (int hwnd, int msg, int wParam, int lParam) { +// if (hwnd == hwndText || hwnd == hwndUpDown) { +// LRESULT result = null; +// switch (msg) { +// /* Keyboard messages */ +// case OS.WM_CHAR: result = wmChar (hwnd, wParam, lParam); break; +// case OS.WM_IME_CHAR: result = wmIMEChar (hwnd, wParam, lParam); break; +// case OS.WM_KEYDOWN: result = wmKeyDown (hwnd, wParam, lParam); break; +// case OS.WM_KEYUP: result = wmKeyUp (hwnd, wParam, lParam); break; +// case OS.WM_SYSCHAR: result = wmSysChar (hwnd, wParam, lParam); break; +// case OS.WM_SYSKEYDOWN: result = wmSysKeyDown (hwnd, wParam, lParam); break; +// case OS.WM_SYSKEYUP: result = wmSysKeyUp (hwnd, wParam, lParam); break; +// +// /* Mouse Messages */ +// case OS.WM_LBUTTONDBLCLK: result = wmLButtonDblClk (hwnd, wParam, lParam); break; +// case OS.WM_LBUTTONDOWN: result = wmLButtonDown (hwnd, wParam, lParam); break; +// case OS.WM_LBUTTONUP: result = wmLButtonUp (hwnd, wParam, lParam); break; +// case OS.WM_MBUTTONDBLCLK: result = wmMButtonDblClk (hwnd, wParam, lParam); break; +// case OS.WM_MBUTTONDOWN: result = wmMButtonDown (hwnd, wParam, lParam); break; +// case OS.WM_MBUTTONUP: result = wmMButtonUp (hwnd, wParam, lParam); break; +// case OS.WM_MOUSEHOVER: result = wmMouseHover (hwnd, wParam, lParam); break; +// case OS.WM_MOUSELEAVE: result = wmMouseLeave (hwnd, wParam, lParam); break; +// case OS.WM_MOUSEMOVE: result = wmMouseMove (hwnd, wParam, lParam); break; +//// case OS.WM_MOUSEWHEEL: result = wmMouseWheel (hwnd, wParam, lParam); break; +// case OS.WM_RBUTTONDBLCLK: result = wmRButtonDblClk (hwnd, wParam, lParam); break; +// case OS.WM_RBUTTONDOWN: result = wmRButtonDown (hwnd, wParam, lParam); break; +// case OS.WM_RBUTTONUP: result = wmRButtonUp (hwnd, wParam, lParam); break; +// case OS.WM_XBUTTONDBLCLK: result = wmXButtonDblClk (hwnd, wParam, lParam); break; +// case OS.WM_XBUTTONDOWN: result = wmXButtonDown (hwnd, wParam, lParam); break; +// case OS.WM_XBUTTONUP: result = wmXButtonUp (hwnd, wParam, lParam); break; +// +// /* Focus Messages */ +// case OS.WM_SETFOCUS: result = wmSetFocus (hwnd, wParam, lParam); break; +// case OS.WM_KILLFOCUS: result = wmKillFocus (hwnd, wParam, lParam); break; +// +// /* Paint messages */ +// case OS.WM_PAINT: result = wmPaint (hwnd, wParam, lParam); break; +// +// /* Menu messages */ +// case OS.WM_CONTEXTMENU: result = wmContextMenu (hwnd, wParam, lParam); +// +// /* Clipboard messages */ +// case OS.WM_CLEAR: +// case OS.WM_CUT: +// case OS.WM_PASTE: +// case OS.WM_UNDO: +// case OS.EM_UNDO: +// if (hwnd == hwndText) { +// result = wmClipboard (hwnd, msg, wParam, lParam); +// } +// break; +// } +// if (result != null) return result.value; +// return callWindowProc (hwnd, msg, wParam, lParam); +// } +// return super.windowProc (hwnd, msg, wParam, lParam); +//} + +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// LRESULT result = super.WM_ERASEBKGND (wParam, lParam); +// if (result != null) return result; +// drawBackground (wParam); +// return LRESULT.ONE; +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// return null; +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// OS.SetFocus (hwndText); +// return null; +//} +// +//LRESULT WM_SETFONT (int wParam, int lParam) { +// LRESULT result = super.WM_SETFONT (wParam, lParam); +// if (result != null) return result; +// OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam); +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// LRESULT result = super.WM_SIZE (wParam, lParam); +// if (isDisposed ()) return result; +// int width = lParam & 0xFFFF, height = lParam >> 16; +// int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// int textWidth = width - upDownWidth; +// int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE; +// SetWindowPos (hwndText, 0, 0, 0, textWidth, height, flags); +// SetWindowPos (hwndUpDown, 0, textWidth, 0, upDownWidth, height, flags); +// return result; +//} +// +//LRESULT wmChar (int hwnd, int wParam, int lParam) { +// LRESULT result = super.wmChar (hwnd, wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. For some reason, when the +// * widget is a single line text widget, when the +// * user presses tab, return or escape, Windows beeps. +// * The fix is to look for these keys and not call +// * the window proc. +// */ +// switch (wParam) { +// case SWT.CR: +// int value = getSelectionText (); +// setSelection (value, true); +// postEvent (SWT.DefaultSelection); +// // FALL THROUGH +// case SWT.TAB: +// case SWT.ESC: return LRESULT.ZERO; +// } +// return result; +//} +// +//LRESULT wmClipboard (int hwndText, int msg, int wParam, int lParam) { +// if ((style & SWT.READ_ONLY) != 0) return null; +//// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null; +// boolean call = false; +// int [] start = new int [1], end = new int [1]; +// String oldText = null, newText = null; +// switch (msg) { +// case OS.WM_CLEAR: +// case OS.WM_CUT: +// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end); +// if (start [0] != end [0]) { +// newText = ""; +// call = true; +// } +// break; +// case OS.WM_PASTE: +// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end); +// newText = getClipboardText (); +// break; +// case OS.EM_UNDO: +// case OS.WM_UNDO: +// if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) != 0) { +// ignoreModify = true; +// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end); +// if (OS.IsDBLocale) { +// start [0] = mbcsToWcsPos (start [0]); +// end [0] = mbcsToWcsPos (end [0]); +// } +// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam); +// int length = OS.GetWindowTextLength (hwndText); +// if (length != 0 && start [0] != end [0]) { +// TCHAR buffer = new TCHAR (getCodePage (), length + 1); +// OS.GetWindowText (hwndText, buffer, length + 1); +// newText = buffer.toString (start [0], end [0] - start [0]); +// } else { +// newText = ""; +// } +// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam); +// ignoreModify = false; +// } +// break; +// } +// if (newText != null && !newText.equals (oldText)) { +// oldText = newText; +// newText = verifyText (newText, start [0], end [0], null); +// if (newText == null) return LRESULT.ZERO; +// if (!newText.equals (oldText)) { +// if (call) { +// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam); +// } +// TCHAR buffer = new TCHAR (getCodePage (), newText, true); +// if (msg == OS.WM_SETTEXT) { +// int hHeap = OS.GetProcessHeap (); +// int byteCount = buffer.length () * TCHAR.sizeof; +// int pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); +// OS.MoveMemory (pszText, buffer, byteCount); +// int code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText); +// OS.HeapFree (hHeap, 0, pszText); +// return new LRESULT (code); +// } else { +// OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer); +// return LRESULT.ZERO; +// } +// } +// } +// return null; +//} +// +//LRESULT wmCommandChild (int wParam, int lParam) { +// int code = wParam >> 16; +// switch (code) { +// case OS.EN_CHANGE: +// if (ignoreModify) break; +// sendEvent (SWT.Modify); +// if (isDisposed ()) return LRESULT.ZERO; +// break; +// } +// return super.wmCommandChild (wParam, lParam); +//} +// +//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) { +// LRESULT result = super.wmKeyDown (hwnd, wParam, lParam); +// if (result != null) return result; +// +// /* Increment the value */ +// UDACCEL udaccel = new UDACCEL (); +// OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel); +// int delta = 0; +// switch (wParam) { +// case OS.VK_UP: delta = udaccel.nInc; break; +// case OS.VK_DOWN: delta = -udaccel.nInc; break; +// case OS.VK_PRIOR: delta = pageIncrement; break; +// case OS.VK_NEXT: delta = -pageIncrement; break; +// } +// if (delta != 0) { +// int value = getSelectionText (); +// int newValue = value + delta; +// int [] max = new int [1], min = new int [1]; +// OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max); +// if ((style & SWT.WRAP) != 0) { +// if (newValue < min [0]) newValue = max [0]; +// if (newValue > max [0]) newValue = min [0]; +// } +// newValue = Math.min (Math.max (min [0], newValue), max [0]); +// if (value != newValue) setSelection (newValue, true); +// } +// +// /* Stop the edit control from moving the caret */ +// switch (wParam) { +// case OS.VK_UP: +// case OS.VK_DOWN: +// return LRESULT.ZERO; +// } +// return result; +//} +// +//LRESULT wmKillFocus (int hwnd, int wParam, int lParam) { +// int value = getSelectionText (); +// setSelection (value, true); +// return super.wmKillFocus (hwnd, wParam, lParam); +//} +// +//LRESULT wmScrollChild (int wParam, int lParam) { +// int code = wParam & 0xFFFF; +// switch (code) { +// case OS.SB_THUMBPOSITION: +// postEvent (SWT.Selection); +// break; +// } +// return super.wmScrollChild (wParam, lParam); +//} + +String verifyText (String string, int start, int end, Event keyEvent) { + Event event = new Event (); + event.text = string; + event.start = start; + event.end = end; + if (keyEvent != null) { + event.character = keyEvent.character; + event.keyCode = keyEvent.keyCode; + event.stateMask = keyEvent.stateMask; + } + sendEvent (SWT.Verify, event); + if (!event.doit || isDisposed ()) return null; + return event.text; +} + +public void processEvent(EventObject e) { + if(e instanceof ChangeEvent) { + if(!hooks(SWT.Selection)) { super.processEvent(e); return; } + } else if(e instanceof TextFilterEvent) { + if(!hooks(SWT.Verify)) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof ChangeEvent) { + sendEvent (SWT.Selection); + } else if(e instanceof TextFilterEvent) { + TextFilterEvent filterEvent = (TextFilterEvent)e; + filterEvent.setText(verifyText(filterEvent.getText(), filterEvent.getStart(), filterEvent.getStart() + filterEvent.getEnd(), createKeyEvent(filterEvent.getKeyEvent()))); + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(DocumentEvent e) { + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + sendEvent(SWT.Modify, new Event()); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java new file mode 100644 index 00000000000..d185119b84b --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java @@ -0,0 +1,504 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Component; +import java.awt.Container; +import java.util.ArrayList; +import java.util.EventObject; + +import javax.swing.event.ChangeEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.CTabFolder; +import org.eclipse.swt.internal.swing.CTabItem; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class implement the notebook user interface + * metaphor. It allows the user to select a notebook page from + * set of pages. + *

    + * The item children that may be added to instances of this class + * must be of type TabItem. + * Control children are created and then set into a + * tab item using TabItem#setControl. + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to set a layout on it. + *

    + *

    + *
    Styles:
    + *
    TOP, BOTTOM
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * Note: Only one of the styles TOP and BOTTOM may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class TabFolder extends Composite { + + ArrayList itemList; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TabFolder (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +Control [] _getChildren () { + Component[] children = ((CControl)handle).getClientArea().getComponents(); + if(children.length == 0) { + return new Control[0]; + } + ArrayList controlsList = new ArrayList(children.length); + for(int i=0; iSelectionListener + * interface. + *

    + * When widgetSelected is called, the item field of the event object is valid. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener(SWT.Selection,typedListener); + addListener(SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + style = checkBits (style, SWT.TOP, SWT.BOTTOM, 0, 0, 0, 0); + return style & ~(SWT.H_SCROLL | SWT.V_SCROLL); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +boolean autoAddChildren() { + return false; +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CTabFolder.Factory.newInstance(this, style); +} + +void createItem (TabItem item, int index) { + int count = getItemCount(); + if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE); + itemList.add(index, item); + handle.add(item.handle, index); + handle.invalidate(); + handle.validate(); + /* + * Send a selection event when the item that is added becomes + * the new selection. This only happens when the first item + * is added. + */ +// if (getItemCount() == 1) { +// Event event = new Event (); +// event.item = item; +// sendEvent (SWT.Selection, event); +// // the widget could be destroyed at this point +// } +} + +void createWidget () { + super.createWidget (); + itemList = new ArrayList(); +} + +void destroyItem (TabItem item) { + int index = indexOf(item); + if(index != -1) { + handle.remove(item.handle); + handle.invalidate(); + handle.validate(); + handle.repaint(); + } + itemList = null; +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TabItem getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return (TabItem)itemList.get(index); +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return itemList.size(); +} + +/** + * Returns an array of TabItems which are the items + * in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TabItem [] getItems () { + checkWidget (); + return (TabItem[])itemList.toArray(new TabItem [0]); +} + +/** + * Returns an array of TabItems that are currently + * selected in the receiver. An empty array indicates that no + * items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return an array representing the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TabItem [] getSelection () { + checkWidget (); + int index = ((CTabFolder)handle).getSelectedIndex(); + if (index == -1) return new TabItem [0]; + return new TabItem [] {(TabItem)itemList.get(index)}; +} + +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver, or -1 if no item is selected. + * + * @return the index of the selected item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionIndex () { + checkWidget (); + return ((CTabFolder)handle).getSelectedIndex(); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (TabItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = getItemCount(); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Sets the receiver's selection to the given item. + * The current selected is first cleared, then the new item is + * selected. + * + * @param item the item to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSelection (TabItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + setSelection (new TabItem [] {item}); +} + +/** + * Sets the receiver's selection to be the given array of items. + * The current selected is first cleared, then the new items are + * selected. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the items array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (TabItem [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + if (items.length == 0) { + ((CTabFolder)handle).setSelectedIndex(-1); + } else { + ((CTabFolder)handle).setSelectedIndex(indexOf (items [items.length-1])); + } +} + +/** + * Selects the item at the given zero-relative index in the receiver. + * If the item at the index was already selected, it remains selected. + * The current selection is first cleared, then the new items are + * selected. Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) return; + ((CTabFolder)handle).setSelectedIndex(index); +} + +Point minimumSize (int wHint, int hHint, boolean changed) { + java.awt.Dimension size = handle.getPreferredSize(); + return new Point(size.width, size.height); +} + +public void processEvent(EventObject e) { + if(e instanceof ChangeEvent) { + if(!hooks(SWT.Selection)) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof ChangeEvent) { +// ChangeEvent ce = (ChangeEvent)e; + int index = ((CTabFolder)handle).getSelectedIndex(); + Event event = new Event(); + if(index >= 0) { + event.item = (Widget)itemList.get(index); + } + sendEvent(SWT.Selection, event); + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java new file mode 100644 index 00000000000..af5326388dd --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.BorderLayout; +import java.awt.Container; + +import javax.swing.ImageIcon; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.CTabFolder; +import org.eclipse.swt.internal.swing.CTabItem; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class represent a selectable user interface object + * corresponding to a tab for a page in a tab folder. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class TabItem extends Item { + TabFolder parent; + Control control; + String toolTipText; + Container handle; + +/** + * Constructs a new instance of this class given its parent + * (which must be a TabFolder) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TabItem (TabFolder parent, int style) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a TabFolder), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TabItem (TabFolder parent, int style, int index) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, index); +} + +Container createHandle () { + return (Container)CTabItem.Factory.newInstance(this, style); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns the control that is used to fill the client area of + * the tab folder when the user selects the tab item. If no + * control has been set, return null. + *

    + * @return the control + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Control getControl () { + checkWidget(); + return control; +} + +/** + * Returns the receiver's parent, which must be a TabFolder. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TabFolder getParent () { + checkWidget(); + return parent; +} + +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getToolTipText () { + checkWidget(); + return toolTipText; +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseParent () { + super.releaseParent (); + int index = parent.indexOf (this); + if (index == parent.getSelectionIndex ()) { + if (control != null) control.setVisible (false); + } +} + +void releaseWidget () { + super.releaseWidget (); + control = null; +} + +/** + * Sets the control that is used to fill the client area of + * the tab folder when the user selects the tab item. + *

    + * @param control the new control (or null) + * + * @exception IllegalArgumentException

      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setControl (Control control) { + checkWidget(); + if (control != null) { + if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT); + } + if (this.control != null && this.control.isDisposed ()) { + this.control = null; + handle.remove(this.control.handle); + } + this.control = control; + if(control != null) { + handle.add(control.handle, BorderLayout.CENTER); + } + handle.invalidate(); + handle.validate(); + handle.repaint(); +} + +public void setImage (Image image) { + checkWidget(); + int index = parent.indexOf (this); + if (index == -1) return; + super.setImage (image); + ((CTabFolder)parent.handle).setIconAt(index, new ImageIcon(image.handle)); +} + +/** + * Sets the receiver's text. The string may include + * the mnemonic character. + *

    + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, a selection + * event occurs. On most platforms, the mnemonic appears + * underlined but may be emphasised in a platform specific + * manner. The mnemonic indicator character '&' can be + * escaped by doubling it in the string, causing a single + * '&' to be displayed. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + */ +public void setText (String string) { + checkWidget(); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if (string.equals (text)) return; + int index = parent.indexOf (this); + if (index == -1) return; + super.setText (string); + int mnemonicIndex = findMnemonicIndex(string); + char mnemonic; + CTabFolder cTabFolder = (CTabFolder)parent.handle; + if(mnemonicIndex < 0) { + mnemonic = '\0'; + cTabFolder.setTitleAt(index, string); + } else { + mnemonic = string.charAt(mnemonicIndex); + cTabFolder.setTitleAt(index, string.substring(0, mnemonicIndex - 1) + string.substring(mnemonicIndex)); + } + cTabFolder.setMnemonicAt(index, mnemonic); +} + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setToolTipText (String string) { + checkWidget(); + toolTipText = string; + ((CTabFolder)parent.handle).setToolTipTextAt(parent.indexOf(this), Utils.convertStringToHTML(toolTipText)); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java new file mode 100644 index 00000000000..14fb2cb76c4 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java @@ -0,0 +1,3479 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Container; +import java.awt.event.ItemEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.EventObject; + +import javax.swing.DefaultListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumnModel; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CTable; +import org.eclipse.swt.internal.swing.CTableItem; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.CTable.CellPaintEvent; + +/** + * Instances of this class implement a selectable user interface + * object that displays a list of images and strings and issues + * notification when selected. + *

    + * The item children that may be added to instances of this class + * must be of type TableItem. + *

    + * Style VIRTUAL is used to create a Table whose + * TableItems are to be populated by the client on an on-demand basis + * instead of up-front. This can provide significant performance improvements for + * tables that are very large or for which TableItem population is + * expensive (for example, retrieving values from an external source). + *

    + * Here is an example of using a Table with style VIRTUAL: + *

    + *  final Table table = new Table (parent, SWT.VIRTUAL | SWT.BORDER);
    + *  table.setItemCount (1000000);
    + *  table.addListener (SWT.SetData, new Listener () {
    + *      public void handleEvent (Event event) {
    + *          TableItem item = (TableItem) event.item;
    + *          int index = table.indexOf (item);
    + *          item.setText ("Item " + index);
    + *          System.out.println (item.getText ());
    + *      }
    + *  }); 
    + * 
    + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to add Control children to it, + * or set a layout on it. + *

    + *

    + *
    Styles:
    + *
    SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL
    + *
    Events:
    + *
    Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem
    + *
    + *

    + * Note: Only one of the styles SINGLE, and MULTI may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class Table extends Composite { + ArrayList itemList; + ArrayList columnList; +// ImageList imageList; + TableItem currentItem; + int lastIndexOf; +// int lastWidth; +// boolean customDraw, dragStarted, fixScrollWidth, mouseDown, tipRequested; +// boolean ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize; + static final int INSET = 4; + static final int GRID_WIDTH = 1; + static final int HEADER_MARGIN = 10; + + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SINGLE + * @see SWT#MULTI + * @see SWT#CHECK + * @see SWT#FULL_SELECTION + * @see SWT#HIDE_SELECTION + * @see SWT#VIRTUAL + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Table (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +void adjustColumnWidth() { + // Could be more efficient. Should post, with coalescing? + if(getColumnCount() == 0) { + CTable cTable = (CTable)handle; + cTable.getColumnModel().getColumn(0).setPreferredWidth(cTable.getPreferredColumnWidth(0)); + } +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's selection changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the item field of the event object is valid. + * If the receiver has SWT.CHECK style set and the check selection changes, + * the event object detail field contains the value SWT.CHECK. + * widgetDefaultSelected is typically called when an item is double-clicked. + * The item field of the event object is valid for default selection, but the detail field is not used. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +boolean checkData (TableItem item, boolean redraw) { + if ((style & SWT.VIRTUAL) == 0) return true; + return checkData (item, indexOf (item), redraw); +} + +boolean checkData (TableItem item, int index, boolean redraw) { + if ((style & SWT.VIRTUAL) == 0) return true; + if (!item.cached) { + item.cached = true; + Event event = new Event (); + event.item = item; + event.index = index; + currentItem = item; + sendEvent (SWT.SetData, event); + //widget could be disposed at this point + currentItem = null; + if (isDisposed () || item.isDisposed ()) return false; +// if (redraw) { +// if (!setScrollWidth (item, false)) { +// item.redraw (); +// } +// } + } + return true; +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +/** + * Clears the item at the given zero-relative index in the receiver. + * The text, icon and other attributes of the item are set to the default + * value. If the table was created with the SWT.VIRTUAL style, + * these attributes are requested again as needed. + * + * @param index the index of the item to clear + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.0 + */ +public void clear (int index) { + checkWidget (); + TableItem item = (TableItem)itemList.get(index); + if(item != null) { + item.clear(); + } + handle.repaint(); +// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); +// TableItem item = items [index]; +// if (item != null) { +// if (item != currentItem) item.clear (); +// /* +// * Bug in Windows. Despite the fact that every item in the +// * table always has LPSTR_TEXTCALLBACK, Windows caches the +// * bounds for the selected items. This means that +// * when you change the string to be something else, Windows +// * correctly asks you for the new string but when the item +// * is selected, the selection draws using the bounds of the +// * previous item. The fix is to reset LPSTR_TEXTCALLBACK +// * even though it has not changed, causing Windows to flush +// * cached bounds. +// */ +// if ((style & SWT.VIRTUAL) == 0 && item.cached) { +// LVITEM lvItem = new LVITEM (); +// lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT; +// lvItem.pszText = OS.LPSTR_TEXTCALLBACK; +// lvItem.iItem = index; +// OS.SendMessage (handle, OS.LVM_SETITEM, 0, lvItem); +// item.cached = false; +// } +// if (currentItem == null && drawCount == 0 && OS.IsWindowVisible (handle)) { +// OS.SendMessage (handle, OS.LVM_REDRAWITEMS, index, index); +// } +// setScrollWidth (item, false); +// } +} + +/** + * Removes the items from the receiver which are between the given + * zero-relative start and end indices (inclusive). The text, icon + * and other attributes of the items are set to their default values. + * If the table was created with the SWT.VIRTUAL style, + * these attributes are requested again as needed. + * + * @param start the start index of the item to clear + * @param end the end index of the item to clear + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.0 + */ +public void clear (int start, int end) { + checkWidget (); + if (start > end) return; + for(int i=start; i<=end; i++) { + TableItem item = (TableItem)itemList.get(i); + if(item != null) { + item.clear(); + } + } + handle.repaint(); +// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// if (!(0 <= start && start <= end && end < count)) { +// error (SWT.ERROR_INVALID_RANGE); +// } +// if (start == 0 && end == count - 1) { +// clearAll (); +// } else { +// LVITEM lvItem = null; +// boolean cleared = false; +// for (int i=start; i<=end; i++) { +// TableItem item = items [i]; +// if (item != null) { +// if (item != currentItem) { +// cleared = true; +// item.clear (); +// } +// /* +// * Bug in Windows. Despite the fact that every item in the +// * table always has LPSTR_TEXTCALLBACK, Windows caches the +// * bounds for the selected items. This means that +// * when you change the string to be something else, Windows +// * correctly asks you for the new string but when the item +// * is selected, the selection draws using the bounds of the +// * previous item. The fix is to reset LPSTR_TEXTCALLBACK +// * even though it has not changed, causing Windows to flush +// * cached bounds. +// */ +// if ((style & SWT.VIRTUAL) == 0 && item.cached) { +// if (lvItem == null) { +// lvItem = new LVITEM (); +// lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT; +// lvItem.pszText = OS.LPSTR_TEXTCALLBACK; +// } +// lvItem.iItem = i; +// OS.SendMessage (handle, OS.LVM_SETITEM, 0, lvItem); +// item.cached = false; +// } +// } +// } +// if (cleared) { +// if (currentItem == null && drawCount == 0 && OS.IsWindowVisible (handle)) { +// OS.SendMessage (handle, OS.LVM_REDRAWITEMS, start, end); +// } +// TableItem item = start == end ? items [start] : null; +// setScrollWidth (item, false); +// } +// } +} + +/** + * Clears the items at the given zero-relative indices in the receiver. + * The text, icon and other attributes of the items are set to their default + * values. If the table was created with the SWT.VIRTUAL style, + * these attributes are requested again as needed. + * + * @param indices the array of indices of the items + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    • ERROR_NULL_ARGUMENT - if the indices array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.0 + */ +public void clear (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + if (indices.length == 0) return; + for(int i=0; iSWT.VIRTUAL style, these + * attributes are requested again as needed. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.0 + */ +public void clearAll () { + checkWidget (); + for (int i=itemList.size()-1; i>=0; i--) { + TableItem item = (TableItem)itemList.get(i); + if(item != null) { + item.clear(); + } + } + handle.repaint(); +// LVITEM lvItem = null; +// boolean cleared = false; +// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// for (int i=0; i> 16; +// +// /* +// * Feature in Windows. The height returned by LVM_APPROXIMATEVIEWRECT +// * includes the trim plus the height of the items plus one extra row. +// * The fix is to subtract the height of one row from the result height. +// */ +// int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); +// int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); +// height -= (oneItem >> 16) - (empty >> 16); +// +// if (width == 0) width = DEFAULT_WIDTH; +// if (height == 0) height = DEFAULT_HEIGHT; +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// int border = getBorderWidth (); +// width += border * 2; height += border * 2; +// if ((style & SWT.V_SCROLL) != 0) { +// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL); +// } +// if ((style & SWT.H_SCROLL) != 0) { +// height += OS.GetSystemMetrics (OS.SM_CYHSCROLL); +// } +// return new Point (width, height); +//} + +public Rectangle computeTrim(int x, int y, int width, int height) { + CTable cTable = (CTable)handle; + width += cTable.getVerticalScrollBar().getPreferredSize().width; + height += cTable.getHorizontalScrollBar().getPreferredSize().height; + return super.computeTrim(x, y, width, height); +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CTable.Factory.newInstance(this, style); +} + +void createItem (TableColumn column, int index) { + for (int i=0; i=0; i--) { + javax.swing.table.TableColumn tColumn = columnModel.getColumn(i); + int modelIndex = tColumn.getModelIndex(); + if(modelIndex >= index) { + tColumn.setModelIndex(modelIndex + 1); + } + } + columnModel.addColumn(tableColumn); + tableColumn.setModelIndex(index); + ((CTable)handle).moveColumn(getColumnCount()-1, index); + // TODO: check it is enough + handle.repaint(); +} + +void createItem (TableItem item, int index) { + int count = getItemCount(); + if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE); + itemList.add(index, item); + ((CTable)handle).addItem(index); +} + +void createWidget () { + itemList = new ArrayList(); + columnList = new ArrayList(); + super.createWidget (); +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. Indices that are out + * of range and duplicate indices are ignored. + * + * @param indices the array of indices for the items to deselect + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the set of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselect (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + if (indices.length == 0) return; + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + isAdjustingSelection = true; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void deselect (int index) { + checkWidget (); + if (index < 0) return; + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().removeSelectionInterval(index, index); + isAdjustingSelection = false; +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. The range of the + * indices is inclusive. Indices that are out of range are ignored. + * + * @param start the start index of the items to deselect + * @param end the end index of the items to deselect + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselect (int start, int end) { + checkWidget (); + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().removeSelectionInterval(start, end); + isAdjustingSelection = false; +} + +/** + * Deselects all selected items in the receiver. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void deselectAll () { + checkWidget (); + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().clearSelection(); + isAdjustingSelection = false; +} + +void destroyItem (TableColumn column) { + int index = columnList.indexOf(column); + for (int i=0; iTableColumns were created by the programmer, + * this method will throw ERROR_INVALID_RANGE despite + * the fact that a single column of data may be visible in the table. + * This occurs when the programmer uses the table like a list, adding + * items but never creating a column. + * + * @param index the index of the column to return + * @return the column at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#getColumnOrder() + * @see Table#setColumnOrder(int[]) + * @see TableColumn#getMoveable() + * @see TableColumn#setMoveable(boolean) + * @see SWT#Move + */ +public TableColumn getColumn (int index) { + checkWidget (); + if (columnList == null) error (SWT.ERROR_INVALID_RANGE); + int count = getColumnCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return (TableColumn)columnList.get(index); +} + +/** + * Returns the number of columns contained in the receiver. + * If no TableColumns were created by the programmer, + * this value is zero, despite the fact that visually, one column + * of items may be visible. This occurs when the programmer uses + * the table like a list, adding items but never creating a column. + * + * @return the number of columns + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getColumnCount () { + checkWidget (); + return columnList == null? 0: columnList.size(); +} + +/** + * Returns an array of zero-relative integers that map + * the creation order of the receiver's items to the + * order in which they are currently being displayed. + *

    + * Specifically, the indices of the returned array represent + * the current visual order of the items, and the contents + * of the array represent the creation order of the items. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the current visual order of the receiver's items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#setColumnOrder(int[]) + * @see TableColumn#getMoveable() + * @see TableColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.1 + */ +public int[] getColumnOrder () { + checkWidget (); + return ((CTable)handle).getColumnOrder(); +} + +/** + * Returns an array of TableColumns which are the + * columns in the receiver. Columns are returned in the order + * that they were created. If no TableColumns were + * created by the programmer, the array is empty, despite the fact + * that visually, one column of items may be visible. This occurs + * when the programmer uses the table like a list, adding items but + * never creating a column. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#getColumnOrder() + * @see Table#setColumnOrder(int[]) + * @see TableColumn#getMoveable() + * @see TableColumn#setMoveable(boolean) + * @see SWT#Move + */ +public TableColumn [] getColumns () { + checkWidget (); + if (columnList == null) return new TableColumn [0]; + return (TableColumn[])columnList.toArray(new TableColumn[0]); +} + +///* +//* Not currently used. +//*/ +//int getFocusIndex () { +//// checkWidget (); +// return OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED); +//} + +/** + * Returns the width in pixels of a grid line. + * + * @return the width of a grid line in pixels + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getGridLineWidth () { + checkWidget (); + return GRID_WIDTH; +} + +/** + * Returns the height of the receiver's header + * + * @return the height of the header or zero if the header is not visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public int getHeaderHeight () { + checkWidget (); + JTableHeader tableHeader = ((CTable)handle).getTableHeader(); + return tableHeader.isVisible()? tableHeader.getHeight(): 0; +} + +/** + * Returns true if the receiver's header is visible, + * and false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's header's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getHeaderVisible () { + checkWidget (); + return ((CTable)handle).getTableHeader().isVisible(); +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return _getItem(index); +} + +/** + * Returns the item at the given point in the receiver + * or null if no such item exists. The point is in the + * coordinate system of the receiver. + *

    + * The item that is returned represents an item that could be selected by the user. + * For example, if selection only occurs in items in the first column, then null is + * returned if the point is outside of the item. + * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy, + * determines the extent of the selection. + *

    + * + * @param point the point used to locate the item + * @return the item at the given point, or null if the point is not in a selectable item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem getItem (Point point) { + checkWidget (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + int row = ((CTable)handle).rowAtPoint(new java.awt.Point(point.x, point.y)); + if(row < 0) return null; + return _getItem(row); +} + +TableItem _getItem (int index) { + TableItem tableItem = (TableItem)itemList.get(index); + if ((style & SWT.VIRTUAL) == 0) return tableItem; + if (tableItem != null) return tableItem; + tableItem = new TableItem (this, SWT.NONE, -1, false); + itemList.set(index, tableItem); + return tableItem; +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return itemList == null? 0: itemList.size(); +} + +/** + * Returns the height of the area which would be used to + * display one of the items in the receiver's. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemHeight () { + checkWidget (); + return ((CTable)handle).getRowHeight(); +} + +/** + * Returns a (possibly empty) array of TableItems which + * are the items in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem [] getItems () { + checkWidget (); + if ((style & SWT.VIRTUAL) != 0) { + TableItem[] items = new TableItem[getItemCount()]; + for(int i=0; itrue if the receiver's lines are visible, + * and false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the visibility state of the lines + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getLinesVisible () { + checkWidget (); + return ((CTable)handle).isGridVisible(); +} + +/** + * Returns an array of TableItems that are currently + * selected in the receiver. The order of the items is unspecified. + * An empty array indicates that no items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return an array representing the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem [] getSelection () { + checkWidget (); + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + int minSelectionIndex = selectionModel.getMinSelectionIndex(); + int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); + if(minSelectionIndex == -1 || maxSelectionIndex == -1) { + return new TableItem[0]; + } + TableItem[] selectedIndices_ = new TableItem[1 + maxSelectionIndex - minSelectionIndex]; + int count = 0; + for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) { + if(selectionModel.isSelectedIndex(i)) { + selectedIndices_[count++] = _getItem(i); + } + } + TableItem[] selectedIndices = new TableItem[count]; + System.arraycopy(selectedIndices_, 0, selectedIndices, 0, count); + return selectedIndices; +} + +/** + * Returns the number of selected items contained in the receiver. + * + * @return the number of selected items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionCount () { + checkWidget (); + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + int minSelectionIndex = selectionModel.getMinSelectionIndex(); + int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); + int count = 0; + for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) { + if(selectionModel.isSelectedIndex(i)) { + count++; + } + } + return count; +} + +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver, or -1 if no item is selected. + * + * @return the index of the selected item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionIndex () { + checkWidget (); + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + return selectionModel.getMinSelectionIndex(); +} + +/** + * Returns the zero-relative indices of the items which are currently + * selected in the receiver. The order of the indices is unspecified. + * The array is empty if no items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return the array of indices of the selected items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int [] getSelectionIndices () { + checkWidget (); + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + int minSelectionIndex = selectionModel.getMinSelectionIndex(); + int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); + if(minSelectionIndex == -1 || maxSelectionIndex == -1) { + return new int[0]; + } + int[] selectedIndices_ = new int[1 + maxSelectionIndex - minSelectionIndex]; + int count = 0; + for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) { + if(selectionModel.isSelectedIndex(i)) { + selectedIndices_[count++] = i; + } + } + int[] selectedIndices = new int[count]; + System.arraycopy(selectedIndices_, 0, selectedIndices, 0, count); + return selectedIndices; +} + +TableColumn sortColumn; +int sortDirection; + +/** + * Returns the column which shows the sort indicator for + * the receiver. The value may be null if no column shows + * the sort indicator. + * + * @return the sort indicator + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setSortColumn(TableColumn) + * + * @since 3.2 + */ +public TableColumn getSortColumn () { + checkWidget (); + return sortColumn; +} + +/** + * Returns the direction of the sort indicator for the receiver. + * The value will be one of UP, DOWN + * or NONE. + * + * @return the sort direction + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setSortDirection(int) + * + * @since 3.2 + */ +public int getSortDirection () { + checkWidget (); + return sortDirection; +} + +/** + * Returns the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items are + * scrolled or new items are added or removed. + * + * @return the index of the top item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopIndex () { + checkWidget (); + // Should we return -1 or 0 when there are no items? + return Math.max(0, ((CTable)handle).getTopIndex()); +} + +//int imageIndex (Image image) { +// if (image == null) return OS.I_IMAGENONE; +// if (imageList == null) { +// Rectangle bounds = image.getBounds (); +// imageList = display.getImageList (new Point (bounds.width, bounds.height)); +// int index = imageList.indexOf (image); +// if (index == -1) index = imageList.add (image); +// int hImageList = imageList.getHandle (); +// /* +// * Bug in Windows. Making any change to an item that +// * changes the item height of a table while the table +// * is scrolled can cause the lines to draw incorrectly. +// * This happens even when the lines are not currently +// * visible and are shown afterwards. The fix is to +// * save the top index, scroll to the top of the table +// * and then restore the original top index. +// */ +// int topIndex = getTopIndex (); +// setRedraw (false); +// setTopIndex (0); +// OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList); +// setTopIndex (topIndex); +// fixCheckboxImageList (); +// setRedraw (true); +// return index; +// } +// int index = imageList.indexOf (image); +// if (index != -1) return index; +// return imageList.add (image); +//} + +/** + * Searches the receiver's list starting at the first column + * (index 0) until a column is found that is equal to the + * argument, and returns the index of that column. If no column + * is found, returns -1. + * + * @param column the search column + * @return the index of the column + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (TableColumn column) { + checkWidget (); + if (column == null) error (SWT.ERROR_NULL_ARGUMENT); + if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + return columnList.indexOf(column); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (TableItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = getItemCount(); + if (1 <= lastIndexOf && lastIndexOf < count - 1) { + if (itemList.get(lastIndexOf) == item) return lastIndexOf; + if (itemList.get(lastIndexOf + 1) == item) return ++lastIndexOf; + if (itemList.get(lastIndexOf - 1) == item) return --lastIndexOf; + } + if (lastIndexOf < count / 2) { + for (int i=0; i=0; --i) { + if (itemList.get(i) == item) return lastIndexOf = i; + } + } + return -1; +} + +/** + * Returns true if the item is selected, + * and false otherwise. Indices out of + * range are ignored. + * + * @param index the index of the item + * @return the visibility state of the item at the index + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean isSelected (int index) { + checkWidget (); + return ((CTable)handle).getSelectionModel().isSelectedIndex(index); +} + +Point minimumSize (int wHint, int hHint, boolean changed) { + java.awt.Dimension size = handle.getPreferredSize(); + return new Point(size.width, size.height); +} + +void releaseChildren (boolean destroy) { + if(itemList != null) { + for (int i=itemList.size()-1; i>=0; i--) { + TableItem item = (TableItem)itemList.get(i); + if (item != null && !item.isDisposed ()) item.release (false); + } + itemList = null; + } + if(columnList != null) { + for(int i=0; i1000) where each +// * of the subitems in the table has a string, it is much +// * faster to delete each item with LVM_DELETEITEM rather +// * than using LVM_DELETEALLITEMS. The fix is to detect +// * this case and delete the items, one by one. The fact +// * that the fix is only necessary on Windows 98 was +// * confirmed using version 5.81 of COMCTL32.DLL on both +// * Windows 98 and NT. +// * +// * NOTE: LVM_DELETEALLITEMS is also sent by the table +// * when the table is destroyed. +// */ +// if (OS.IsWin95 && columnCount > 1) { +// /* Turn off redraw and leave it off */ +// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// for (int i=itemCount-1; i>=0; --i) { +// TableItem item = items [i]; +// ignoreSelect = ignoreShrink = true; +// OS.SendMessage (handle, OS.LVM_DELETEITEM, i, 0); +// ignoreSelect = ignoreShrink = false; +// if (item != null && !item.isDisposed ()) item.releaseResources (); +// } +// } else { +// for (int i=0; i + *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • + *
  • ERROR_NULL_ARGUMENT - if the indices array is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + if (indices.length == 0) return; + int [] newIndices = new int [indices.length]; + System.arraycopy (indices, 0, newIndices, 0, indices.length); + // Sort puts the biggest indices first + sort (newIndices); + int start = newIndices [newIndices.length - 1], end = newIndices [0]; + int count = getItemCount(); + if (!(0 <= start && start <= end && end < count)) { + error (SWT.ERROR_INVALID_RANGE); + } + for(int i=0; i + *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + TableItem tableItem = (TableItem)itemList.get(index); + if(tableItem != null) { + tableItem.dispose(); + } else { + itemList.remove(index); + ((CTable)handle).removeItem(index); + } +} + +/** + * Removes the items from the receiver which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int start, int end) { + checkWidget (); + if (start > end) return; + int count = getItemCount(); + if (!(0 <= start && start <= end && end < count)) { + error (SWT.ERROR_INVALID_RANGE); + } + for(int i=end; i>=start; i--) { + TableItem tableItem = (TableItem)itemList.get(i); + if(tableItem != null) { + tableItem.dispose(); + } else { + itemList.remove(i); + ((CTable)handle).removeItem(i); + } + } +} + +/** + * Removes all of the items from the receiver. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void removeAll () { + checkWidget (); + for(int i=itemList.size()-1; i>=0; i--) { + TableItem tableItem = (TableItem)itemList.get(i); + if(tableItem != null) { + tableItem.dispose(); + } else { + itemList.remove(i); + ((CTable)handle).removeItem(i); + } + } +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's selection changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener(SelectionListener) + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +boolean isAdjustingSelection; + +/** + * Selects the items at the given zero-relative indices in the receiver. + * The current selection is not cleared before the new items are selected. + *

    + * If the item at a given index is not selected, it is selected. + * If the item at a given index was already selected, it remains selected. + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + *

    + * + * @param indices the array of indices for the items to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#setSelection(int[]) + */ +public void select (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + int length = indices.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + isAdjustingSelection = true; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void select (int index) { + checkWidget (); + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().addSelectionInterval(index, index); + isAdjustingSelection = false; +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is not cleared before the new items are selected. + *

    + * If an item in the given range is not selected, it is selected. + * If an item in the given range was already selected, it remains selected. + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + *

    + * + * @param start the start of the range + * @param end the end of the range + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#setSelection(int,int) + */ +public void select (int start, int end) { + checkWidget (); + if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return; + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().addSelectionInterval(start, end); + isAdjustingSelection = false; +} + +/** + * Selects all of the items in the receiver. + *

    + * If the receiver is single-select, do nothing. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void selectAll () { + checkWidget (); + if ((style & SWT.SINGLE) != 0) return; + if(!itemList.isEmpty()) { + isAdjustingSelection = true; + ((CTable)handle).getSelectionModel().addSelectionInterval(0, itemList.size() - 1); + isAdjustingSelection = false; + } +} + +//LRESULT sendMouseDownEvent (int type, int button, int msg, int wParam, int lParam) { +// /* +// * Feature in Windows. Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN, +// * the widget starts a modal loop to determine if the user wants +// * to begin a drag/drop operation or marque select. Unfortunately, +// * this modal loop eats the corresponding mouse up. The fix is to +// * detect the cases when the modal loop has eaten the mouse up and +// * issue a fake mouse up. +// * +// * By observation, when the mouse is clicked anywhere but the check +// * box, the widget eats the mouse up. When the mouse is dragged, +// * the widget does not eat the mouse up. +// */ +// LVHITTESTINFO pinfo = new LVHITTESTINFO (); +// pinfo.x = (short) (lParam & 0xFFFF); +// pinfo.y = (short) (lParam >> 16); +// OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo); +// sendMouseEvent (type, button, handle, msg, wParam, lParam); +// +// /* +// * Force the table to have focus so that when the user +// * reselects the focus item, the LVIS_FOCUSED state bits +// * for the item will be set. These bits are used when +// * the table is multi-select to issue the selection +// * event. If the user did not click on an item, then +// * set focus to the table so that it will come to the +// * front and take focus in the work around below. +// */ +// OS.SetFocus (handle); +// +// /* +// * Feature in Windows. When the user selects outside of +// * a table item, Windows deselects all the items, even +// * when the table is multi-select. While not strictly +// * wrong, this is unexpected. The fix is to detect the +// * case and avoid calling the window proc. +// */ +// if (pinfo.iItem == -1) { +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// return LRESULT.ZERO; +// } +// +// /* +// * Feature in Windows. When a table item is reselected +// * in a single-select table, Windows does not issue a +// * WM_NOTIFY because the item state has not changed. +// * This is strictly correct but is inconsistent with the +// * list widget and other widgets in Windows. The fix is +// * to detect the case when an item is reselected and issue +// * the notification. +// * +// * NOTE: This code runs for multi-select as well, ignoring +// * the selection that is issed from WM_NOTIFY. +// */ +// boolean wasSelected = false; +// int count = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0); +// if (count == 1 && pinfo.iItem != -1) { +// LVITEM lvItem = new LVITEM (); +// lvItem.mask = OS.LVIF_STATE; +// lvItem.stateMask = OS.LVIS_SELECTED; +// lvItem.iItem = pinfo.iItem; +// OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem); +// wasSelected = (lvItem.state & OS.LVIS_SELECTED) != 0; +// if (wasSelected) ignoreSelect = true; +// } +// dragStarted = false; +// int code = callWindowProc (handle, msg, wParam, lParam); +// if (wasSelected) { +// ignoreSelect = false; +// Event event = new Event (); +// event.item = _getItem (pinfo.iItem); +// postEvent (SWT.Selection, event); +// } +// if (dragStarted) { +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// } else { +// int flags = OS.LVHT_ONITEMLABEL | OS.LVHT_ONITEMICON; +// boolean fakeMouseUp = (pinfo.flags & flags) != 0; +// if (!fakeMouseUp && (style & SWT.MULTI) != 0) { +// fakeMouseUp = (pinfo.flags & OS.LVHT_ONITEMSTATEICON) == 0; +// } +// if (fakeMouseUp) { +// mouseDown = false; +// sendMouseEvent (SWT.MouseUp, button, handle, msg, wParam, lParam); +// } +// } +// dragStarted = false; +// return new LRESULT (code); +//} + +/** + * Sets the order that the items in the receiver should + * be displayed in to the given argument which is described + * in terms of the zero-relative ordering of when the items + * were added. + * + * @param order the new order to display the items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item order is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
    • + *
    + * + * @see Table#getColumnOrder() + * @see TableColumn#getMoveable() + * @see TableColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.1 + */ +public void setColumnOrder (int [] order) { + checkWidget (); + if (order == null) error (SWT.ERROR_NULL_ARGUMENT); + int columnCount = getColumnCount(); + if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT); + ((CTable)handle).setColumnOrder(order); +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0 ); +// if (count == 1 && columns [0] == null) { +// if (order.length != 0) error (SWT.ERROR_INVALID_ARGUMENT); +// return; +// } +// if (order.length != count) error (SWT.ERROR_INVALID_ARGUMENT); +// int [] oldOrder = new int [count]; +// OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, count, oldOrder); +// boolean reorder = false; +// boolean [] seen = new boolean [count]; +// for (int i=0; i= count) error (SWT.ERROR_INVALID_RANGE); +// if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT); +// seen [index] = true; +// if (index != oldOrder [i]) reorder = true; +// } +// if (reorder) { +// RECT [] oldRects = new RECT [count]; +// for (int i=0; i= 6 && OS.IsAppThemed ()) { +// int hTheme = OS.OpenThemeData (handle, BUTTON); +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDNORMAL, rect, null); +// OS.CloseThemeData (hTheme); +// } else { +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_INACTIVE | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_INACTIVE | OS.DFCS_FLAT); +// } +// OS.SelectObject (memDC, hOldBitmap); +// OS.DeleteDC (memDC); +// OS.ReleaseDC (handle, hDC); +// OS.ImageList_Add (hImageList, hBitmap, 0); +// OS.DeleteObject (hBitmap); +// int hOldStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0); +// OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_STATE, hImageList); +// if (hOldStateList != 0) OS.ImageList_Destroy (hOldStateList); +//} + +void setFocusIndex (int index) { +// checkWidget (); + if(index < 0 || index >= getItemCount()) return; + DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel(); + selectionModel.addSelectionInterval(index, index); + selectionModel.setAnchorSelectionIndex(index); + selectionModel.setLeadSelectionIndex(index); +} + +/** + * Marks the receiver's header as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param show the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setHeaderVisible (boolean show) { + checkWidget (); + ((CTable)handle).setHeaderVisible(show); +} + +/** + * Sets the number of items contained in the receiver. + * + * @param count the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setItemCount (int count) { + checkWidget (); + count = Math.max (0, count); + int itemCount = getItemCount(); + if (count == itemCount) return; + boolean isVirtual = (style & SWT.VIRTUAL) != 0; +// if (!isVirtual) setRedraw (false); + int index = count; + int tmpItemCount = itemCount; + while (index < tmpItemCount) { + TableItem item = (TableItem)itemList.get(tmpItemCount - 1); +// if (!isVirtual) { +// ((CTable)handle).removeItem(index); +// } + if (item != null && !item.isDisposed ()) { + item.release (true); + } else { + itemList.remove(index); + ((CTable)handle).removeItem(index); + } + tmpItemCount--; + } +// if (index < itemCount) error (SWT.ERROR_ITEM_NOT_REMOVED); + itemList.ensureCapacity(count); + for(int i=itemCount; ione of the items in the table. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +/*public*/ void setItemHeight (int itemHeight) { + checkWidget (); + if (itemHeight < 0) error (SWT.ERROR_INVALID_ARGUMENT); + ((CTable)handle).setRowHeight(itemHeight); +} + +/** + * Marks the receiver's lines as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param show the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLinesVisible (boolean show) { + checkWidget (); + ((CTable)handle).setGridVisible(show); +} + +//public void setRedraw (boolean redraw) { +// checkWidget (); +// /* +// * Feature in Windows. When WM_SETREDRAW is used to turn +// * off drawing in a widget, it clears the WS_VISIBLE bits +// * and then sets them when redraw is turned back on. This +// * means that WM_SETREDRAW will make a widget unexpectedly +// * visible. The fix is to track the visibility state while +// * drawing is turned off and restore it when drawing is turned +// * back on. +// */ +// if (drawCount == 0) { +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN; +// } +// if (redraw) { +// if (--drawCount == 0) { +// /* +// * When many items are added to a table, it is faster to +// * temporarily unsubclass the window proc so that messages +// * are dispatched directly to the table. +// * +// * NOTE: This is optimization somewhat dangerous because any +// * operation can occur when redraw is turned off, even operations +// * where the table must be subclassed in order to have the correct +// * behavior or work around a Windows bug. +// * +// * This code is intentionally commented. +// */ +//// subclass (); +// +// /* Set the width of the horizontal scroll bar */ +// setScrollWidth (null, true); +// +// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 1, 0); +// if ((state & HIDDEN) != 0) { +// state &= ~HIDDEN; +// OS.ShowWindow (handle, OS.SW_HIDE); +// } else { +// if (OS.IsWinCE) { +// OS.InvalidateRect (handle, null, false); +// if (hwndHeader != 0) { +// OS.InvalidateRect (hwndHeader, null, false); +// } +// } else { +// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; +// OS.RedrawWindow (handle, null, 0, flags); +// } +// } +// } +// } else { +// if (drawCount++ == 0) { +// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 0, 0); +// +// /* +// * When many items are added to a table, it is faster to +// * temporarily unsubclass the window proc so that messages +// * are dispatched directly to the table. +// * +// * NOTE: This is optimization somewhat dangerous because any +// * operation can occur when redraw is turned off, even operations +// * where the table must be subclassed in order to have the correct +// * behavior or work around a Windows bug. +// * +// * This code is intentionally commented. +// */ +//// unsubclass (); +// } +// } +//} + +//boolean setScrollWidth (TableItem item, boolean force) { +// if (currentItem != null) { +// if (currentItem != item) fixScrollWidth = true; +// return false; +// } +// if (!force && (drawCount != 0 || !OS.IsWindowVisible (handle))) { +// fixScrollWidth = true; +// return false; +// } +// fixScrollWidth = false; +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// /* +// * NOTE: It is much faster to measure the strings and compute the +// * width of the scroll bar in non-virtual table rather than using +// * LVM_SETCOLUMNWIDTH with LVSCW_AUTOSIZE. +// */ +// if (count == 1 && columns [0] == null) { +// int newWidth = 0; +// count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// int index = 0; +// int imageIndent = 0; +// while (index < count) { +// String string = null; +// int font = -1; +// if (item != null) { +// string = item.text; +// imageIndent = Math.max (imageIndent, item.imageIndent); +// if (item.cellFont != null) font = item.cellFont [0]; +// if (font == -1) font = item.font; +// } else { +// if (items [index] != null) { +// TableItem tableItem = items [index]; +// string = tableItem.text; +// imageIndent = Math.max (imageIndent, tableItem.imageIndent); +// if (tableItem.cellFont != null) font = tableItem.cellFont [0]; +// if (font == -1) font = tableItem.font; +// } +// } +// if (string != null && string.length () != 0) { +// if (font != -1) { +// int hDC = OS.GetDC (handle); +// int oldFont = OS.SelectObject (hDC, font); +// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX; +// TCHAR buffer = new TCHAR (getCodePage (), string, false); +// RECT rect = new RECT (); +// OS.DrawText (hDC, buffer, buffer.length (), rect, flags); +// OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// newWidth = Math.max (newWidth, rect.right - rect.left); +// } else { +// TCHAR buffer = new TCHAR (getCodePage (), string, true); +// newWidth = Math.max (newWidth, OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer)); +// } +// } +// if (item != null) break; +// index++; +// } +// int hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0); +// if (hStateList != 0) { +// int [] cx = new int [1], cy = new int [1]; +// OS.ImageList_GetIconSize (hStateList, cx, cy); +// newWidth += cx [0] + INSET; +// } +// int hImageList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0); +// if (hImageList != 0) { +// int [] cx = new int [1], cy = new int [1]; +// OS.ImageList_GetIconSize (hImageList, cx, cy); +// newWidth += (imageIndent + 1) * cx [0]; +// } else { +// /* +// * Bug in Windows. When LVM_SETIMAGELIST is used to remove the +// * image list by setting it to NULL, the item width and height +// * is not changed and space is reserved for icons despite the +// * fact that there are none. The fix is to set the image list +// * to be very small before setting it to NULL. This causes +// * Windows to reserve the smallest possible space when an image +// * list is removed. In this case, the scroll width must be one +// * pixel larger. +// */ +// newWidth++; +// } +// newWidth += INSET * 2; +// int oldWidth = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0); +// if (newWidth > oldWidth) { +// OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, newWidth); +// return true; +// } +// } +// return false; +//} + +/** + * Selects the items at the given zero-relative indices in the receiver. + * The current selection is cleared before the new items are selected. + *

    + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + *

    + * + * @param indices the indices of the items to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#deselectAll() + * @see Table#select(int[]) + */ +public void setSelection (int [] indices) { + checkWidget (); + if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); + deselectAll (); + int length = indices.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + select (indices); + int focusIndex = indices [0]; + if (focusIndex != -1) setFocusIndex (focusIndex); + showSelection (); +} + +/** + * Sets the receiver's selection to the given item. + * The current selection is cleared before the new item is selected. + *

    + * If the item is not in the receiver, then it is ignored. + *

    + * + * @param item the item to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSelection (TableItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + setSelection (new TableItem [] {item}); +} + +/** + * Sets the receiver's selection to be the given array of items. + * The current selection is cleared before the new items are selected. + *

    + * Items that are not in the receiver are ignored. + * If the receiver is single-select and multiple items are specified, + * then all items are ignored. + *

    + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of items is null
    • + *
    • ERROR_INVALID_ARGUMENT - if one of the items has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#deselectAll() + * @see Table#select(int[]) + * @see Table#setSelection(int[]) + */ +public void setSelection (TableItem [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + isAdjustingSelection = true; + deselectAll (); + isAdjustingSelection = false; + int length = items.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; + int focusIndex = -1; + for (int i=length-1; i>=0; --i) { + int index = indexOf (items [i]); + if (index != -1) { + select (focusIndex = index); + } + } + if (focusIndex != -1) setFocusIndex (focusIndex); + showSelection (); +} + +/** + * Selects the item at the given zero-relative index in the receiver. + * The current selection is first cleared, then the new item is selected. + * + * @param index the index of the item to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#deselectAll() + * @see Table#select(int) + */ +public void setSelection (int index) { + checkWidget (); + deselectAll (); + select (index); + if (index != -1) setFocusIndex (index); + showSelection (); +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is cleared before the new items are selected. + *

    + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + *

    + * + * @param start the start index of the items to select + * @param end the end index of the items to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#deselectAll() + * @see Table#select(int,int) + */ +public void setSelection (int start, int end) { + checkWidget (); + deselectAll (); + if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return; + ((CTable)handle).getSelectionModel().setSelectionInterval(start, end); + showSelection (); +} + +/** + * Sets the column used by the sort indicator for the receiver. A null + * value will clear the sort indicator. The current sort column is cleared + * before the new column is set. + * + * @param column the column used by the sort indicator or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the column is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSortColumn (TableColumn column) { + checkWidget (); + if (column != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + sortColumn = column; + handle.repaint(); +} + +/** + * Sets the direction of the sort indicator for the receiver. The value + * can be one of UP, DOWN or NONE. + * + * @param direction the direction of the sort indicator + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSortDirection (int direction) { + checkWidget (); + if ((direction & (SWT.UP | SWT.DOWN)) == 0 && direction != SWT.NONE) return; + sortDirection = direction; + handle.repaint(); +} + +/** + * Sets the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items + * are scrolled or new items are added and removed. + * + * @param index the index of the top item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTopIndex (int index) { + checkWidget (); + ((CTable)handle).setTopIndex(index); +} + +/** + * Shows the column. If the column is already showing in the receiver, + * this method simply returns. Otherwise, the columns are scrolled until + * the column is visible. + * + * @param column the column to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the column is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the column has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void showColumn (TableColumn column) { + checkWidget (); + if (column == null) error (SWT.ERROR_NULL_ARGUMENT); + if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + if (column.parent != this) return; + int index = indexOf (column); + if (index == -1) return; + ((CTable)handle).ensureColumnVisible(index); +} + +//void showItem (int index) { +// /* +// * Bug in Windows. For some reason, when there is insufficient space +// * to show an item, LVM_ENSUREVISIBLE causes blank lines to be +// * inserted at the top of the widget. A call to LVM_GETTOPINDEX will +// * return a negative number (this is an impossible result). The fix +// * is to use LVM_GETCOUNTPERPAGE to detect the case when the number +// * of visible items is zero and use LVM_ENSUREVISIBLE with the +// * fPartialOK flag set to true to scroll the table. +// */ +// if (OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0) <= 0) { +// /* +// * Bug in Windows. For some reason, LVM_ENSUREVISIBLE can +// * scroll one item more or one item less when there is not +// * enough space to show a single table item. The fix is +// * to detect the case and call LVM_ENSUREVISIBLE again with +// * the same arguments. It seems that once LVM_ENSUREVISIBLE +// * has scrolled into the general area, it is able to scroll +// * to the exact item. +// */ +// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1); +// if (index != OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) { +// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1); +// } +// } else { +// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0); +// } +//} + +/** + * Shows the item. If the item is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the item is visible. + * + * @param item the item to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#showSelection() + */ +public void showItem (TableItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + int index = indexOf (item); + if (index != -1) { + ((CTable)handle).ensureRowVisible(index); + } +} + +/** + * Shows the selection. If the selection is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the selection is visible. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#showItem(TableItem) + */ +public void showSelection () { + checkWidget (); + int selectionIndex = getSelectionIndex(); + if(selectionIndex == -1) { + return; + } + ((CTable)handle).ensureRowVisible(selectionIndex); +} + +static int checkStyle (int style) { + style |= SWT.H_SCROLL | SWT.V_SCROLL; + return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0); +} + +//String toolTipText (NMTTDISPINFO hdr) { +// int hwndToolTip = OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0); +// if (hwndToolTip == hdr.hwndFrom && toolTipText != null) return ""; //$NON-NLS-1$ +// return super.toolTipText (hdr); +//} +// +//int widgetStyle () { +// int bits = super.widgetStyle () | OS.LVS_SHAREIMAGELISTS; +// if ((style & SWT.HIDE_SELECTION) == 0) bits |= OS.LVS_SHOWSELALWAYS; +// if ((style & SWT.SINGLE) != 0) bits |= OS.LVS_SINGLESEL; +// /* +// * This code is intentionally commented. In the future, +// * the FLAT bit may be used to make the header flat and +// * unresponsive to mouse clicks. +// */ +//// if ((style & SWT.FLAT) != 0) bits |= OS.LVS_NOSORTHEADER; +// bits |= OS.LVS_REPORT | OS.LVS_NOCOLUMNHEADER; +// if ((style & SWT.VIRTUAL) != 0) bits |= OS.LVS_OWNERDATA; +// return bits; +//} +// +//TCHAR windowClass () { +// return TableClass; +//} +// +//int windowProc () { +// return TableProc; +//} +// +//LRESULT WM_CHAR (int wParam, int lParam) { +// LRESULT result = super.WM_CHAR (wParam, lParam); +// if (result != null) return result; +// switch (wParam) { +// case SWT.CR: +// /* +// * Feature in Windows. Windows sends LVN_ITEMACTIVATE from WM_KEYDOWN +// * instead of WM_CHAR. This means that application code that expects +// * to consume the key press and therefore avoid a SWT.DefaultSelection +// * event will fail. The fix is to ignore LVN_ITEMACTIVATE when it is +// * caused by WM_KEYDOWN and send SWT.DefaultSelection from WM_CHAR. +// */ +// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED); +// if (index != -1) { +// Event event = new Event (); +// event.item = _getItem (index); +// postEvent (SWT.DefaultSelection, event); +// } +// return LRESULT.ZERO; +// } +// return result; +//} +// +//LRESULT WM_ERASEBKGND (int wParam, int lParam) { +// LRESULT result = super.WM_ERASEBKGND (wParam, lParam); +// if (result != null) return result; +// /* +// * This code is intentionally commented. When a table contains +// * images that are not in the first column, the work around causes +// * pixel corruption. +// */ +//// if (!OS.IsWindowEnabled (handle)) return result; +//// /* +//// * Feature in Windows. When WM_ERASEBKGND is called, +//// * it clears the damaged area by filling it with the +//// * background color. During WM_PAINT, when the table +//// * items are drawn, the background for each item is +//// * also drawn, causing flashing. The fix is to adjust +//// * the damage by subtracting the bounds of each visible +//// * table item. +//// */ +//// int itemCount = getItemCount (); +//// if (itemCount == 0) return result; +//// GCData data = new GCData(); +//// data.device = display; +//// GC gc = GC.win32_new (wParam, data); +//// Region region = new Region (display); +//// gc.getClipping (region); +//// int columnCount = Math.max (1, getColumnCount ()); +//// Rectangle clientArea = getClientArea (); +//// int i = getTopIndex (); +//// int bottomIndex = i + OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0); +//// bottomIndex = Math.min (itemCount, bottomIndex); +//// while (i < bottomIndex) { +//// int j = 0; +//// while (j < columnCount) { +//// if (j != 0 || (!isSelected (i) && i != getFocusIndex ())) { +//// RECT rect = new RECT (); +//// rect.top = j; +//// rect.left = OS.LVIR_LABEL; +//// OS.SendMessage (handle, OS. LVM_GETSUBITEMRECT, i, rect); +//// int width = Math.max (0, rect.right - rect.left); +//// int height = Math.max (0, rect.bottom - rect.top); +//// Rectangle rect2 = new Rectangle (rect.left, rect.top, width, height); +//// if (!rect2.intersects (clientArea)) break; +//// region.subtract (rect2); +//// } +//// j++; +//// } +//// i++; +//// } +//// gc.setClipping (region); +//// drawBackground (wParam); +//// gc.setClipping ((Region) null); +//// region.dispose (); +//// gc.dispose (); +//// return LRESULT.ONE; +// return result; +//} +// +//LRESULT WM_GETOBJECT (int wParam, int lParam) { +// /* +// * Ensure that there is an accessible object created for this +// * control because support for checked item accessibility is +// * temporarily implemented in the accessibility package. +// */ +// if ((style & SWT.CHECK) != 0) { +// if (accessible == null) accessible = new_Accessible (this); +// } +// return super.WM_GETOBJECT (wParam, lParam); +//} +// +//LRESULT WM_KEYDOWN (int wParam, int lParam) { +// LRESULT result = super.WM_KEYDOWN (wParam, lParam); +// if (result != null) return result; +// if ((style & SWT.CHECK) != 0 && wParam == OS.VK_SPACE) { +// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED); +// if (index != -1) { +// TableItem item = _getItem (index); +// item.setChecked (!item.getChecked (), true); +// if (!OS.IsWinCE) { +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1); +// } +// } +// } +// return result; +//} +// +//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { +// mouseDown = true; +// +// /* +// * Feature in Windows. When the user selects outside of +// * a table item, Windows deselects all the items, even +// * when the table is multi-select. While not strictly +// * wrong, this is unexpected. The fix is to detect the +// * case and avoid calling the window proc. +// */ +// LVHITTESTINFO pinfo = new LVHITTESTINFO (); +// pinfo.x = (short) (lParam & 0xFFFF); +// pinfo.y = (short) (lParam >> 16); +// int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo); +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// if (pinfo.iItem != -1) callWindowProc (handle, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// +// /* Look for check/uncheck */ +// if ((style & SWT.CHECK) != 0) { +// /* +// * Note that when the table has LVS_EX_FULLROWSELECT and the +// * user clicks anywhere on a row except on the check box, all +// * of the bits are set. The hit test flags are LVHT_ONITEM. +// * This means that a bit test for LVHT_ONITEMSTATEICON is not +// * the correct way to determine that the user has selected +// * the check box, equality is needed. +// */ +// if (index != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) { +// TableItem item = _getItem (index); +// item.setChecked (!item.getChecked (), true); +// if (!OS.IsWinCE) { +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1); +// } +// } +// } +// return LRESULT.ZERO; +//} +// +//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +// mouseDown = true; +// +// /* +// * Feature in Windows. For some reason, capturing +// * the mouse after processing the mouse event for the +// * widget interferes with the normal mouse processing +// * for the widget. The fix is to avoid the automatic +// * mouse capture. +// */ +// LRESULT result = sendMouseDownEvent (SWT.MouseDown, 1, OS.WM_LBUTTONDOWN, wParam, lParam); +// +// /* Look for check/uncheck */ +// if ((style & SWT.CHECK) != 0) { +// LVHITTESTINFO pinfo = new LVHITTESTINFO (); +// pinfo.x = (short) (lParam & 0xFFFF); +// pinfo.y = (short) (lParam >> 16); +// /* +// * Note that when the table has LVS_EX_FULLROWSELECT and the +// * user clicks anywhere on a row except on the check box, all +// * of the bits are set. The hit test flags are LVHT_ONITEM. +// * This means that a bit test for LVHT_ONITEMSTATEICON is not +// * the correct way to determine that the user has selected +// * the check box, equality is needed. +// */ +// int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo); +// if (index != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) { +// TableItem item = _getItem (index); +// item.setChecked (!item.getChecked (), true); +// if (!OS.IsWinCE) { +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1); +// } +// } +// } +// +// return result; +//} +// +//LRESULT WM_LBUTTONUP (int wParam, int lParam) { +// mouseDown = false; +// return super.WM_LBUTTONUP (wParam, lParam); +//} +// +//LRESULT WM_MOUSEHOVER (int wParam, int lParam) { +// /* +// * Feature in Windows. Despite the fact that hot +// * tracking is not enabled, the hot tracking code +// * in WM_MOUSEHOVER is executed causing the item +// * under the cursor to be selected. The fix is to +// * avoid calling the window proc. +// */ +// LRESULT result = super.WM_MOUSEHOVER (wParam, lParam); +// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); +// int mask = OS.LVS_EX_ONECLICKACTIVATE | OS.LVS_EX_TRACKSELECT | OS.LVS_EX_TWOCLICKACTIVATE; +// if ((bits & mask) != 0) return result; +// return LRESULT.ZERO; +//} +// +//LRESULT WM_PAINT (int wParam, int lParam) { +// if (!ignoreShrink) { +// /* Resize the item array to match the item count */ +// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// if (items.length > 4 && items.length - count > 3) { +// int length = Math.max (4, (count + 3) / 4 * 4); +// TableItem [] newItems = new TableItem [length]; +// System.arraycopy (items, 0, newItems, 0, count); +// items = newItems; +// } +// } +// if (fixScrollWidth) setScrollWidth (null, true); +// return super.WM_PAINT (wParam, lParam); +//} +// +//LRESULT WM_NOTIFY (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// if (hdr.hwndFrom == hwndHeader) { +// /* +// * Feature in Windows. On NT, the automatically created +// * header control is created as a UNICODE window, not an +// * ANSI window despite the fact that the parent is created +// * as an ANSI window. This means that it sends UNICODE +// * notification messages to the parent window on NT for +// * no good reason. The data and size in the NMHEADER and +// * HDITEM structs is identical between the platforms so no +// * different message is actually necessary. Despite this, +// * Windows sends different messages. The fix is to look +// * for both messages, despite the platform. This works +// * because only one will be sent on either platform, never +// * both. +// */ +// switch (hdr.code) { +// case OS.HDN_BEGINTRACKW: +// case OS.HDN_BEGINTRACKA: +// case OS.HDN_DIVIDERDBLCLICKW: +// case OS.HDN_DIVIDERDBLCLICKA: { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count == 1 && columns [0] == null) return LRESULT.ONE; +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// TableColumn column = columns [phdn.iItem]; +// if (column != null && !column.getResizable ()) { +// return LRESULT.ONE; +// } +// break; +// } +// case OS.HDN_BEGINDRAG: { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count == 1 && columns [0] == null) return LRESULT.ONE; +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// if (phdn.iItem != -1) { +// TableColumn column = columns [phdn.iItem]; +// if (column != null && !column.getMoveable ()) { +// OS.ReleaseCapture (); +// return LRESULT.ONE; +// } +// } +// break; +// } +// case OS.HDN_ENDDRAG: { +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// if (phdn.iItem != -1 && phdn.pitem != 0) { +// HDITEM pitem = new HDITEM (); +// OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof); +// if ((pitem.mask & OS.HDI_ORDER) != 0 && pitem.iOrder != -1) { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count == 1 && columns [0] == null) break; +// int [] order = new int [count]; +// OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, count, order); +// int index = 0; +// while (index < order.length) { +// if (order [index] == phdn.iItem) break; +// index++; +// } +// if (index == order.length) index = 0; +// if (index == pitem.iOrder) break; +// int start = Math.min (index, pitem.iOrder); +// int end = Math.max (index, pitem.iOrder); +// for (int i=start; i<=end; i++) { +// TableColumn column = columns [order [i]]; +// if (!column.isDisposed ()) { +// column.postEvent (SWT.Move); +// } +// } +// } +// } +// break; +// } +// case OS.HDN_ITEMCHANGEDW: +// case OS.HDN_ITEMCHANGEDA: { +// /* +// * Bug in Windows. When a table has the LVS_EX_GRIDLINES extended +// * style and the user drags any column over the first column in the +// * table, making the size become zero, when the user drags a column +// * such that the size of the first column becomes non-zero, the grid +// * lines are not redrawn. The fix is to detect the case and force +// * a redraw of the first column. +// */ +// int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0); +// if (lastWidth == 0 && width > 0) { +// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); +// if ((bits & OS.LVS_EX_GRIDLINES) != 0) { +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// rect.right = rect.left + width; +// OS.InvalidateRect (handle, rect, true); +// } +// } +// lastWidth = width; +// if (!ignoreResize) { +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// if (phdn.pitem != 0) { +// HDITEM pitem = new HDITEM (); +// OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof); +// if ((pitem.mask & OS.HDI_WIDTH) != 0) { +// TableColumn column = columns [phdn.iItem]; +// if (column != null) { +// column.sendEvent (SWT.Resize); +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the resize +// * event. If this happens, end the processing of the +// * Windows message by returning zero as the result of +// * the window proc. +// */ +// if (isDisposed ()) return LRESULT.ZERO; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count == 1 && columns [0] == null) count = 0; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the column in the move +// * event. If this happens, process the move event +// * for those columns that have not been destroyed. +// */ +// TableColumn [] newColumns = new TableColumn [count]; +// System.arraycopy (columns, 0, newColumns, 0, count); +// int [] order = new int [count]; +// OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, count, order); +// boolean moved = false; +// for (int i=0; i> 16); +// OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo); +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_RBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_RBUTTONDBLCLK, wParam, lParam); +// if (pinfo.iItem != -1) callWindowProc (handle, OS.WM_RBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// return LRESULT.ZERO; +//} +// +//LRESULT WM_RBUTTONDOWN (int wParam, int lParam) { +// /* +// * Feature in Windows. For some reason, capturing +// * the mouse after processing the mouse event for the +// * widget interferes with the normal mouse processing +// * for the widget. The fix is to avoid the automatic +// * mouse capture. +// */ +// return sendMouseDownEvent (SWT.MouseDown, 3, OS.WM_RBUTTONDOWN, wParam, lParam); +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_SETFOCUS (wParam, lParam); +// /* +// * Bug in Windows. For some reason, the table does +// * not set the default focus rectangle to be the first +// * item in the table when it gets focus and there is +// * no selected item. The fix to make the first item +// * be the focus item. +// */ +// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); +// if (count == 0) return result; +// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED); +// if (index == -1) { +// LVITEM lvItem = new LVITEM (); +// lvItem.state = OS.LVIS_FOCUSED; +// lvItem.stateMask = OS.LVIS_FOCUSED; +// ignoreSelect = true; +// OS.SendMessage (handle, OS.LVM_SETITEMSTATE, 0, lvItem); +// ignoreSelect = false; +// } +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// /* +// * Bug in Windows. If the table column widths are adjusted +// * in WM_SIZE, blank lines may be inserted at the top of the +// * widget. A call to LVM_GETTOPINDEX will return a negative +// * number (this is an impossible result). The fix is to do +// * the WM_SIZE processing in WM_WINDOWPOSCHANGED after the +// * table has been updated. +// */ +// return null; +//} +// +//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) { +// LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam); +// if (result != null) return result; +// if (background == -1) { +// int pixel = defaultBackground (); +// OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, pixel); +// OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, pixel); +// } +// if ((style & SWT.CHECK) != 0) setCheckboxImageListColor (); +// return result; +//} +// +//LRESULT WM_VSCROLL (int wParam, int lParam) { +// LRESULT result = super.WM_VSCROLL (wParam, lParam); +// /* +// * Bug in Windows. When a table is drawing grid lines and the +// * user scrolls vertically up or down by a line or a page, the +// * table does not redraw the grid lines for newly exposed items. +// * The fix is to invalidate the items. +// */ +// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); +// if ((bits & OS.LVS_EX_GRIDLINES) != 0) { +// int code = wParam & 0xFFFF; +// switch (code) { +// case OS.SB_THUMBPOSITION: +// case OS.SB_ENDSCROLL: +// case OS.SB_THUMBTRACK: +// case OS.SB_TOP: +// case OS.SB_BOTTOM: +// break; +// case OS.SB_LINEDOWN: +// case OS.SB_LINEUP: +// int headerHeight = 0; +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// if (hwndHeader != 0) { +// RECT rect = new RECT (); +// OS.GetWindowRect (hwndHeader, rect); +// headerHeight = rect.bottom - rect.top; +// } +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// rect.top += headerHeight; +// int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); +// int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); +// int itemHeight = (oneItem >> 16) - (empty >> 16); +// if (code == OS.SB_LINEDOWN) { +// rect.top = rect.bottom - itemHeight - GRID_WIDTH; +// } else { +// rect.bottom = rect.top + itemHeight + GRID_WIDTH; +// } +// OS.InvalidateRect (handle, rect, true); +// break; +// case OS.SB_PAGEDOWN: +// case OS.SB_PAGEUP: +// OS.InvalidateRect (handle, null, true); +// break; +// } +// } +// return result; +//} +// +//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) { +// if (ignoreResize) return null; +// LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam); +// if (result != null) return result; +// WINDOWPOS lpwp = new WINDOWPOS (); +// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof); +// if ((lpwp.flags & OS.SWP_NOSIZE) == 0) { +// setResizeChildren (false); +// int code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam); +// sendEvent (SWT.Resize); +// if (isDisposed ()) return new LRESULT (code); +// if (layout != null) { +// markLayout (false, false); +// updateLayout (false, false); +// } +// setResizeChildren (true); +// return new LRESULT (code); +// } +// return result; +//} +// +//LRESULT wmNotifyChild (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// switch (hdr.code) { +// case OS.LVN_ODFINDITEMA: +// case OS.LVN_ODFINDITEMW: { +// if ((style & SWT.VIRTUAL) != 0) { +// NMLVFINDITEM pnmfi = new NMLVFINDITEM (); +// OS.MoveMemory (pnmfi, lParam, NMLVFINDITEM.sizeof); +// int index = Math.max (0, pnmfi.iStart - 1); +// return new LRESULT (index); +// } +// break; +// } +// case OS.LVN_GETDISPINFOA: +// case OS.LVN_GETDISPINFOW: { +//// if (drawCount != 0 || !OS.IsWindowVisible (handle)) break; +// NMLVDISPINFO plvfi = new NMLVDISPINFO (); +// OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof); +// lastIndexOf = plvfi.iItem; +// TableItem item = _getItem (plvfi.iItem); +// /* +// * The cached flag is used by both virtual and non-virtual +// * tables to indicate that Windows has asked at least once +// * for a table item. +// */ +// if (!item.cached) { +// if ((style & SWT.VIRTUAL) != 0) { +// if (!checkData (item, false)) break; +// TableItem newItem = fixScrollWidth ? null : item; +// if (setScrollWidth (newItem, true)) { +// OS.InvalidateRect (handle, null, true); +// } +// } +// item.cached = true; +// } +// if ((plvfi.mask & OS.LVIF_TEXT) != 0) { +// String string = null; +// if (plvfi.iSubItem == 0) { +// string = item.text; +// } else { +// String [] strings = item.strings; +// if (strings != null) string = strings [plvfi.iSubItem]; +// } +// if (string != null) { +// /* +// * Bug in Windows. When pszText points to a zero length +// * NULL terminated string, Windows correctly draws the +// * empty string but the cache of the bounds for the item +// * is not reset. This means that when the text for the +// * item is set and then reset to an empty string, the +// * selection draws using the bounds of the previous text. +// * The fix is to use a space rather than an empty string +// * when anything but a tool tip is requested (to avoid +// * a tool tip that is a single space). +// * +// * NOTE: This is only a problem for items in the first +// * column. Assigning NULL to other columns stops Windows +// * from drawing the selection when LVS_EX_FULLROWSELECT +// * is set. +// */ +// if (!tipRequested && string.length () == 0 && plvfi.iSubItem == 0) { +// string = " "; //$NON-NLS-1$ +// } +// TCHAR buffer = new TCHAR (getCodePage (), string, false); +// int byteCount = Math.min (buffer.length (), plvfi.cchTextMax - 1) * TCHAR.sizeof; +// OS.MoveMemory (plvfi.pszText, buffer, byteCount); +// OS.MoveMemory (plvfi.pszText + byteCount, new byte [TCHAR.sizeof], TCHAR.sizeof); +// plvfi.cchTextMax = Math.min (plvfi.cchTextMax, string.length () + 1); +// } +// } +// if ((plvfi.mask & OS.LVIF_IMAGE) != 0) { +// Image image = null; +// if (plvfi.iSubItem == 0) { +// image = item.image; +// } else { +// Image [] images = item.images; +// if (images != null) image = images [plvfi.iSubItem]; +// } +// if (image != null) plvfi.iImage = imageIndex (image); +// } +// if ((plvfi.mask & OS.LVIF_STATE) != 0) { +// if (plvfi.iSubItem == 0) { +// int state = 1; +// if (item.checked) state++; +// if (item.grayed) state +=2; +// plvfi.state = state << 12; +// plvfi.stateMask = OS.LVIS_STATEIMAGEMASK; +// } +// } +// if ((plvfi.mask & OS.LVIF_INDENT) != 0) { +// if (plvfi.iSubItem == 0) plvfi.iIndent = item.imageIndent; +// } +// OS.MoveMemory (lParam, plvfi, NMLVDISPINFO.sizeof); +// break; +// } +// case OS.NM_CUSTOMDRAW: { +// if (!customDraw) break; +// NMLVCUSTOMDRAW nmcd = new NMLVCUSTOMDRAW (); +// OS.MoveMemory (nmcd, lParam, NMLVCUSTOMDRAW.sizeof); +// switch (nmcd.dwDrawStage) { +// case OS.CDDS_PREPAINT: return new LRESULT (OS.CDRF_NOTIFYITEMDRAW); +// case OS.CDDS_ITEMPREPAINT: return new LRESULT (OS.CDRF_NOTIFYSUBITEMDRAW); +// case OS.CDDS_ITEMPREPAINT | OS.CDDS_SUBITEM: { +// TableItem item = _getItem (nmcd.dwItemSpec); +// int hFont = item.cellFont != null ? item.cellFont [nmcd.iSubItem] : -1; +// if (hFont == -1) hFont = item.font; +// int clrText = item.cellForeground != null ? item.cellForeground [nmcd.iSubItem] : -1; +// if (clrText == -1) clrText = item.foreground; +// int clrTextBk = item.cellBackground != null ? item.cellBackground [nmcd.iSubItem] : -1; +// if (clrTextBk == -1) clrTextBk = item.background; +// /* +// * Feature in Windows. When the font is set for one cell in a table, +// * Windows does not reset the font for the next cell. As a result, +// * all subsequent cells are drawn using the new font. The fix is to +// * reset the font to the default. +// * +// * NOTE: This does not happen for foreground and background. +// */ +// if (hFont == -1 && clrText == -1 && clrTextBk == -1) { +// if (item.cellForeground == null && item.cellBackground == null && item.cellFont == null) { +// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count == 1) break; +// } +// } +// if (hFont == -1) hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// OS.SelectObject (nmcd.hdc, hFont); +// if (OS.IsWindowEnabled (handle)) { +// nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText; +// nmcd.clrTextBk = clrTextBk == -1 ? getBackgroundPixel () : clrTextBk; +// OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof); +// } +// return new LRESULT (OS.CDRF_NEWFONT); +// } +// } +// break; +// } +// case OS.LVN_MARQUEEBEGIN: return LRESULT.ONE; +// case OS.LVN_BEGINDRAG: +// case OS.LVN_BEGINRDRAG: { +// dragStarted = true; +// if (hdr.code == OS.LVN_BEGINDRAG) { +// int pos = OS.GetMessagePos (); +// POINT pt = new POINT (); +// pt.x = (short) (pos & 0xFFFF); +// pt.y = (short) (pos >> 16); +// OS.ScreenToClient (handle, pt); +// Event event = new Event (); +// event.x = pt.x; +// event.y = pt.y; +// postEvent (SWT.DragDetect, event); +// } +// break; +// } +// case OS.LVN_COLUMNCLICK: { +// NMLISTVIEW pnmlv = new NMLISTVIEW (); +// OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof); +// TableColumn column = columns [pnmlv.iSubItem]; +// if (column != null) { +// column.postEvent (SWT.Selection); +// } +// break; +// } +// case OS.LVN_ITEMACTIVATE: { +// if (ignoreActivate) break; +// NMLISTVIEW pnmlv = new NMLISTVIEW (); +// OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof); +// if (pnmlv.iItem != -1) { +// Event event = new Event (); +// event.item = _getItem (pnmlv.iItem); +// postEvent (SWT.DefaultSelection, event); +// } +// break; +// } +// case OS.LVN_ITEMCHANGED: { +// if (!ignoreSelect) { +// NMLISTVIEW pnmlv = new NMLISTVIEW (); +// OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof); +// if (pnmlv.iItem != -1 && (pnmlv.uChanged & OS.LVIF_STATE) != 0) { +// boolean isFocus = (pnmlv.uNewState & OS.LVIS_FOCUSED) != 0; +// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED); +// if ((style & SWT.MULTI) != 0) { +// if (OS.GetKeyState (OS.VK_CONTROL) < 0) { +// if (!isFocus) { +// if (index == pnmlv.iItem) { +// boolean isSelected = (pnmlv.uNewState & OS.LVIS_SELECTED) != 0; +// boolean wasSelected = (pnmlv.uOldState & OS.LVIS_SELECTED) != 0; +// isFocus = isSelected != wasSelected; +// } +// } else { +// isFocus = mouseDown; +// } +// } +// } +// if (OS.GetKeyState (OS.VK_SPACE) < 0) isFocus = true; +// if (isFocus) { +// Event event = new Event(); +// if (index != -1) { +// /* +// * This code is intentionally commented. +// */ +//// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0); +// event.item = _getItem (index); +// } +// postEvent (SWT.Selection, event); +// } +// } +// } +// break; +// } +// case OS.NM_RECOGNIZEGESTURE: +// /* +// * Feature on Pocket PC. The tree and table controls detect the tap +// * and hold gesture by default. They send a GN_CONTEXTMENU message to show +// * the popup menu. This default behaviour is unwanted on Pocket PC 2002 +// * when no menu has been set, as it still draws a red circle. The fix +// * is to disable this default behaviour when no menu is set by returning +// * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE +// * message. +// */ +// if (OS.IsPPC) { +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE; +// } +// break; +// case OS.GN_CONTEXTMENU: +// if (OS.IsPPC) { +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (hasMenu || hooks (SWT.MenuDetect)) { +// NMRGINFO nmrg = new NMRGINFO (); +// OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof); +// showMenu (nmrg.x, nmrg.y); +// return LRESULT.ONE; +// } +// } +// break; +// } +// return super.wmNotifyChild (wParam, lParam); +//} + +public void processEvent(EventObject e) { + if(e instanceof CellPaintEvent) { + switch(((CellPaintEvent)e).getType()) { + case CellPaintEvent.ERASE_TYPE: if(!hooks(SWT.EraseItem)) { super.processEvent(e); return; } break; + case CellPaintEvent.PAINT_TYPE: if(!hooks(SWT.PaintItem)) { super.processEvent(e); return; } break; + case CellPaintEvent.MEASURE_TYPE: if(!hooks(SWT.MeasureItem)) { super.processEvent(e); return; } break; + default: super.processEvent(e); return; + } + } else if(e instanceof ListSelectionEvent) { + if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; }; + } else { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof CellPaintEvent) { + CellPaintEvent cellPaintEvent = (CellPaintEvent)e; + switch(cellPaintEvent.getType()) { + case CellPaintEvent.ERASE_TYPE: { + TableItem tableItem = cellPaintEvent.tableItem.getTableItem(); + Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column); + Event event = new Event(); + event.x = cellBounds.x; + event.y = cellBounds.y; + event.width = cellBounds.width; + event.height = cellBounds.height; + event.item = tableItem; + event.index = cellPaintEvent.column; + if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND; + if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND; + if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED; + if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED; + event.gc = new GC(this); + event.gc.handle.setUserClip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); +// event.gc.isSwingPainting = true; + sendEvent(SWT.EraseItem, event); + if(event.doit) { + cellPaintEvent.ignoreDrawForeground = (event.detail & SWT.FOREGROUND) == 0; + cellPaintEvent.ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0; + cellPaintEvent.ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0; + cellPaintEvent.ignoreDrawFocused = (event.detail & SWT.FOCUSED) == 0; + } else { + cellPaintEvent.ignoreDrawForeground = true; + cellPaintEvent.ignoreDrawBackground = true; + cellPaintEvent.ignoreDrawSelection = true; + cellPaintEvent.ignoreDrawFocused = true; + } +// event.gc.isSwingPainting = false; + break; + } + case CellPaintEvent.PAINT_TYPE: { + TableItem tableItem = cellPaintEvent.tableItem.getTableItem(); + Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column); + Event event = new Event(); + event.x = cellBounds.x; + event.y = cellBounds.y; + event.width = cellBounds.width; + event.height = cellBounds.height; + event.item = tableItem; + event.index = cellPaintEvent.column; + if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND; + if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND; + if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED; + if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED; + event.gc = new GC(this); + event.gc.handle.setUserClip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); + sendEvent(SWT.PaintItem, event); + break; + } + case CellPaintEvent.MEASURE_TYPE: + TableItem tableItem = cellPaintEvent.tableItem.getTableItem(); +// Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column); + Event event = new Event(); +// event.x = cellBounds.x; +// event.y = cellBounds.y; +// event.width = cellBounds.width; +// event.height = cellBounds.height; + event.height = cellPaintEvent.rowHeight; + event.item = tableItem; + event.index = cellPaintEvent.column; + event.gc = new GC(this); +// event.gc.handle.clip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); + sendEvent(SWT.MeasureItem, event); +// cellPaintEvent.rowHeight -= event.height - cellBounds.height; + cellPaintEvent.rowHeight = event.height; + break; + } + } else if(e instanceof ListSelectionEvent) { + if(!((ListSelectionEvent)e).getValueIsAdjusting()) { + Event event = new Event (); + int selectionIndex = ((CTable)handle).getSelectionModel().getLeadSelectionIndex(); + if(selectionIndex != -1) { + // TODO: should we send the previous item? + event.item = _getItem(selectionIndex); + } + sendEvent(SWT.Selection, event); + } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case KeyEvent.KEY_PRESSED: { + KeyEvent ke = (KeyEvent)e; + if(ke.getKeyCode() != KeyEvent.VK_ENTER || ((CTable)handle).getSelectionModel().getLeadSelectionIndex() == -1 || !hooks(SWT.DefaultSelection)) { super.processEvent(e); return; } break; + } + case MouseEvent.MOUSE_PRESSED: { + MouseEvent me = (MouseEvent)e; + if(me.getID() != MouseEvent.MOUSE_PRESSED || me.getClickCount() != 2 || ((CTable)handle).getSelectionModel().getLeadSelectionIndex() == -1 || !hooks(SWT.DefaultSelection)) { + super.processEvent(e); + return; + }; + break; + } + case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case KeyEvent.KEY_PRESSED: + if(((CTable)handle).getSelectionModel().getLeadSelectionIndex() != -1) { + Event event = new Event (); + event.item = _getItem(((CTable)handle).getSelectionModel().getLeadSelectionIndex()); + sendEvent(SWT.DefaultSelection, event); + } + break; + case MouseEvent.MOUSE_PRESSED: + if(((CTable)handle).getSelectionModel().getLeadSelectionIndex() != -1) { + Event event = new Event (); + event.item = _getItem(((CTable)handle).getSelectionModel().getLeadSelectionIndex()); + sendEvent(SWT.DefaultSelection, event); + } + break; + case ItemEvent.ITEM_STATE_CHANGED: + Event event = new Event(); + event.detail = SWT.CHECK; + event.item = ((CTableItem)((ItemEvent)e).getItem()).getTableItem(); + sendEvent(SWT.Selection, event); + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java new file mode 100644 index 00000000000..4535f6de48d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java @@ -0,0 +1,686 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.beans.PropertyChangeEvent; +import java.util.EventObject; + +import javax.swing.ImageIcon; +import javax.swing.SwingConstants; +import javax.swing.event.TableColumnModelEvent; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.CTable; +import org.eclipse.swt.internal.swing.CTableColumn; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class represent a column in a table widget. + *

    + *
    Styles:
    + *
    LEFT, RIGHT, CENTER
    + *
    Events:
    + *
    Move, Resize, Selection
    + *
    + *

    + * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class TableColumn extends Item { + Table parent; + CTableColumn handle; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Table) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#CENTER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TableColumn (Table parent, int style) { + super (parent, checkStyle (style)); + handle = createHandle(); + this.parent = parent; + parent.createItem (this, parent.getColumnCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Table), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#CENTER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TableColumn (Table parent, int style, int index) { + super (parent, checkStyle (style)); + handle = createHandle(); + this.parent = parent; + parent.createItem (this, index); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is moved or resized, by sending + * it one of the messages defined in the ControlListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #removeControlListener + */ +public void addControlListener(ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Resize,typedListener); + addListener (SWT.Move,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the column header is selected. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +CTableColumn createHandle () { + return CTableColumn.Factory.newInstance(this, style); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns a value which describes the position of the + * text or image in the receiver. The value will be one of + * LEFT, RIGHT or CENTER. + * + * @return the alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAlignment () { + checkWidget (); + if ((style & SWT.LEFT) != 0) return SWT.LEFT; + if ((style & SWT.CENTER) != 0) return SWT.CENTER; + if ((style & SWT.RIGHT) != 0) return SWT.RIGHT; + return SWT.LEFT; +} + +String getNameText () { + return getText (); +} + +/** + * Returns the receiver's parent, which must be a Table. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Table getParent () { + checkWidget (); + return parent; +} + +boolean moveable; + +/** + * Gets the moveable attribute. A column that is + * not moveable cannot be reordered by the user + * by dragging the header but may be reordered + * by the programmer. + * + * @return the moveable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#getColumnOrder() + * @see Table#setColumnOrder(int[]) + * @see TableColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.1 + */ +public boolean getMoveable () { + checkWidget (); + return moveable; +} + +/** + * Gets the resizable attribute. A column that is + * not resizable cannot be dragged by the user but + * may be resized by the programmer. + * + * @return the resizable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getResizable () { + checkWidget (); + return ((javax.swing.table.TableColumn)handle).getResizable(); +} + +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public String getToolTipText () { + checkWidget(); + return handle.getToolTipText(); +} + +/** + * Gets the width of the receiver. + * + * @return the width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getWidth () { + checkWidget (); + int index = parent.indexOf (this); + if (index == -1) return 0; + return ((javax.swing.table.TableColumn)handle).getWidth(); +} + +/** + * Causes the receiver to be resized to its preferred size. + * For a composite, this involves computing the preferred size + * from its layout, if there is one. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + */ +public void pack () { + checkWidget (); + int index = parent.indexOf (this); + if (index == -1) return; + int oldWidth = getWidth(); + CTable cTable = (CTable)parent.handle; + int newWidth = cTable.getPreferredColumnWidth(index); + // TODO: check why in the old SWTSwing, +2 is added. + cTable.getColumnModel().getColumn(index).setPreferredWidth(newWidth + 2); + +// int hwnd = parent.handle; +// int oldWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); +// TCHAR buffer = new TCHAR (parent.getCodePage (), text, true); +// int headerWidth = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + Table.HEADER_MARGIN; +// if (image != null) { +// int margin = 0; +// if (OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) { +// int hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0); +// margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0); +// } else { +// margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3; +// } +// Rectangle rect = image.getBounds (); +// headerWidth += rect.width + margin * 2; +// } +// boolean oldIgnoreRezize = parent.ignoreResize; +// parent.ignoreResize = true; +// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE); +// int columnWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); +// if (index == 0) { +// /* +// * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE +// * where each item has I_IMAGECALLBACK but there are no images in the +// * table, the size computed by LVM_SETCOLUMNWIDTH is too small for the +// * first column, causing long items to be clipped with '...'. The fix +// * is to increase the column width by a small amount. +// */ +// if (parent.imageList == null) columnWidth += 2; +// /* +// * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE +// * for a table with a state image list, the column is width does not +// * include space for the state icon. The fix is to increase the column +// * width by the width of the image list. +// */ +// if ((parent.style & SWT.CHECK) != 0) { +// int hStateList = OS.SendMessage (hwnd, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0); +// if (hStateList != 0) { +// int [] cx = new int [1], cy = new int [1]; +// OS.ImageList_GetIconSize (hStateList, cx, cy); +// columnWidth += cx [0]; +// } +// } +// } +// if (headerWidth > columnWidth) { +// if (image == null) { +// /* +// * Feature in Windows. When LVSCW_AUTOSIZE_USEHEADER is used +// * with LVM_SETCOLUMNWIDTH to resize the last column, the last +// * column is expanded to fill the client area. The fix is to +// * resize the table to be small, set the column width and then +// * restore the table to its original size. +// */ +// RECT rect = null; +// boolean fixWidth = index == parent.getColumnCount () - 1; +// if (fixWidth) { +// rect = new RECT (); +// OS.GetWindowRect (hwnd, rect); +// OS.UpdateWindow (hwnd); +// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER; +// SetWindowPos (hwnd, 0, 0, 0, 0, rect.bottom - rect.top, flags); +// } +// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER); +// if (fixWidth) { +// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER; +// SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags); +// } +// } else { +// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth); +// } +// } else { +// if (index == 0) { +// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth); +// } +// } +// parent.ignoreResize = oldIgnoreRezize; +// int newWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); + if (oldWidth != newWidth) { + sendEvent (SWT.Resize); +// if (isDisposed ()) return; +// boolean moved = false; +// int [] order = parent.getColumnOrder (); +// TableColumn [] columns = parent.getColumns (); +// for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #addControlListener + */ +public void removeControlListener (ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Move, listener); + eventTable.unhook (SWT.Resize, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Controls how text and images will be displayed in the receiver. + * The argument should be one of LEFT, RIGHT + * or CENTER. + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAlignment (int alignment) { + checkWidget (); + if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return; + int index = parent.indexOf (this); + if (index == -1 || index == 0) return; + style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); + style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if ((style & SWT.LEFT) == SWT.LEFT) handle.setAlignment(SwingConstants.LEFT); + if ((style & SWT.CENTER) == SWT.CENTER) handle.setAlignment(SwingConstants.CENTER); + if ((style & SWT.RIGHT) == SWT.RIGHT) handle.setAlignment(SwingConstants.RIGHT); + // TODO: notify change +} + +public void setImage (Image image) { + checkWidget(); + if (image != null && image.isDisposed ()) { + error (SWT.ERROR_INVALID_ARGUMENT); + } + int index = parent.indexOf (this); + if (index == -1) return; + super.setImage (image); + handle.setIcon(image == null? null: new ImageIcon(image.handle)); +} + +/** + * Sets the moveable attribute. A column that is + * moveable can be reordered by the user by dragging + * the header. A column that is not moveable cannot be + * dragged by the user but may be reordered + * by the programmer. + * + * @param moveable the moveable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Table#setColumnOrder(int[]) + * @see Table#getColumnOrder() + * @see TableColumn#getMoveable() + * @see SWT#Move + * + * @since 3.1 + */ +public void setMoveable (boolean moveable) { + checkWidget (); + this.moveable = moveable; +} + +/** + * Sets the resizable attribute. A column that is + * resizable can be resized by the user dragging the + * edge of the header. A column that is not resizable + * cannot be dragged by the user but may be resized + * by the programmer. + * + * @param resizable the resize attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setResizable (boolean resizable) { + checkWidget (); + ((javax.swing.table.TableColumn)handle).setResizable(resizable); +} + +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if (string.equals (text)) return; + int index = parent.indexOf (this); + if (index == -1) return; + super.setText (string); + // TODO: check what happens with mnemonics + ((javax.swing.table.TableColumn)handle).setHeaderValue(string); +} + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setToolTipText (String string) { + checkWidget(); + handle.setToolTipText(string); +} + +/** + * Sets the width of the receiver. + * + * @param width the new width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setWidth (int width) { + checkWidget (); + int index = parent.indexOf (this); + if (index == -1) return; + ((javax.swing.table.TableColumn)handle).setPreferredWidth(width); +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case java.awt.event.MouseEvent.MOUSE_CLICKED: if(!hooks(SWT.Selection)) return; break; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + switch(id) { + case java.awt.event.MouseEvent.MOUSE_CLICKED: { + sendEvent(SWT.Selection); + break; + } + } + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(EventObject e) { + if(e instanceof PropertyChangeEvent) { + if(!hooks(SWT.Resize) && !hooks(SWT.Move) || !"width".equals(((PropertyChangeEvent)e).getPropertyName())) { return; } + } else if(e instanceof TableColumnModelEvent) { + if(!hooks(SWT.Move)) { return; } + } else { + return; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + if(e instanceof PropertyChangeEvent) { + String propertyName = ((PropertyChangeEvent)e).getPropertyName(); + if("width".equals(propertyName)) { + sendEvent(SWT.Resize); + int columnCount = parent.getColumnCount(); + for(int i=parent.indexOf(this) + 1; i + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + * + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class TableItem extends Item { + /** + * the handle to the OS resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + public CTableItem handle; + Table parent; +// String [] strings; + Image [] images; +// boolean checked, grayed + boolean cached; +// int imageIndent, background = -1, foreground = -1, font = -1; +// int [] cellBackground, cellForeground, cellFont; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Table) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TableItem (Table parent, int style) { + this (parent, style, checkNull (parent).getItemCount (), true); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Table), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TableItem (Table parent, int style, int index) { + this (parent, style, index, true); +} + +TableItem (Table parent, int style, int index, boolean create) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + if (create) parent.createItem (this, index); +} + +static Table checkNull (Table control) { + if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return control; +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +CTableItem createHandle () { + return CTableItem.Factory.newInstance(this, style); +} + +void clear () { + text = ""; + image = null; + images = null; + handle.setBackground(null); + handle.setForeground(null); + handle.setFont(null); + handle.setChecked(false); + handle.setGrayed(false); + int count = parent.getColumnCount(); + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.0 + */ +public Color getBackground () { + checkWidget (); + java.awt.Color color = handle.getBackground(); + if(color == null) return parent.getBackground(); + return Color.swing_new(display, color); +} + +/** + * Returns the background color at the given column index in the receiver. + * + * @param index the column index + * @return the background color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Color getBackground (int index) { + checkWidget (); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return getBackground (); + java.awt.Color color = handle.getTableItemObject(index).getBackground(); + if(color == null) { + if(index != 0) { + return getBackground(); + } + return Color.swing_new(display, parent.handle.getBackground()); + } + return Color.swing_new(display, color); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public Rectangle getBounds () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int itemIndex = parent.indexOf (this); + if (itemIndex == -1) return new Rectangle (0, 0, 0, 0); + return getBounds(0); +// RECT rect = getBounds (itemIndex, 0, true, false, false); +// int width = rect.right - rect.left, height = rect.bottom - rect.top; +// return new Rectangle (rect.left, rect.top, width, height); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent at a column in the table. + * + * @param index the index that specifies the column + * @return the receiver's bounding column rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + java.awt.Rectangle rect = ((CTable)parent.handle).getCellRect(parent.indexOf(this), index, false); + Point offset = parent.getInternalOffset(); + return new Rectangle(rect.x + offset.x, rect.y + offset.y, rect.width, rect.height); +} + +/** + * Returns true if the receiver is checked, + * and false otherwise. When the parent does not have + * the CHECK style, return false. + * + * @return the checked state of the checkbox + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getChecked () { + checkWidget(); + if ((parent.style & SWT.CHECK) == 0) return false; + return handle.isChecked(); +} + +/** + * Returns the font that the receiver will use to paint textual information for this item. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Font getFont () { + return getFont(0); +} + +/** + * Returns the font that the receiver will use to paint textual information + * for the specified cell in this item. + * + * @param index the column index + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Font getFont (int index) { + checkWidget (); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count -1) return getFont (); + java.awt.Font font = handle.getTableItemObject(index).getFont(); + if(font == null) { + if(index != 0) { + return getFont(); + } + return Font.swing_new(display, parent.handle.getFont()); + } + return Font.swing_new(display, font); +} + +/** + * Returns the foreground color that the receiver will use to draw. + * + * @return the receiver's foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public Color getForeground () { + checkWidget (); + java.awt.Color color = handle.getForeground(); + if(color == null) return parent.getForeground(); + return Color.swing_new(display, color); +} + +/** + * + * Returns the foreground color at the given column index in the receiver. + * + * @param index the column index + * @return the foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Color getForeground (int index) { + checkWidget (); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count -1) return getForeground (); + java.awt.Color color = handle.getTableItemObject(index).getForeground(); + if(color == null) { + if(index != 0) { + return getBackground(); + } + return Color.swing_new(display, parent.handle.getForeground()); + } + return Color.swing_new(display, color); +} + +/** + * Returns true if the receiver is grayed, + * and false otherwise. When the parent does not have + * the CHECK style, return false. + * + * @return the grayed state of the checkbox + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getGrayed () { + checkWidget (); + if ((parent.style & SWT.CHECK) == 0) return false; + return handle.isGrayed(); +} + +public Image getImage () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return super.getImage (); +} + +/** + * Returns the image stored at the given column index in the receiver, + * or null if the image has not been set or if the column does not exist. + * + * @param index the column index + * @return the image stored at the given column index in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getImage (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + if (index == 0) return getImage (); + if (images != null) { + if (0 <= index && index < images.length) return images [index]; + } + return null; +} + +/** + * Returns a rectangle describing the size and location + * relative to its parent of an image at a column in the + * table. An empty rectangle is returned if index exceeds + * the index of the table's last column. + * + * @param index the index that specifies the column + * @return the receiver's bounding image rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getImageBounds (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int itemIndex = parent.indexOf (this); + if (itemIndex == -1) return new Rectangle (0, 0, 0, 0); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return new Rectangle (0, 0, 0, 0); + java.awt.Rectangle imageBounds = ((CTable)parent.handle).getImageBounds(itemIndex, index); + return new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height); +// RECT rect = getBounds (itemIndex, index, false, true); +// int width = rect.right - rect.left, height = rect.bottom - rect.top; +// return new Rectangle (rect.left, rect.top, width, height); +} + +/** + * Gets the image indent. + * + * @return the indent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getImageIndent () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + Utils.notImplemented(); return 0; +// return imageIndent; +} + +String getNameText () { + if ((parent.style & SWT.VIRTUAL) != 0) { + if (!cached) return "*virtual*"; //$NON-NLS-1$ + } + return super.getNameText (); +} + +/** + * Returns the receiver's parent, which must be a Table. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Table getParent () { + checkWidget(); + return parent; +} + +public String getText () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return super.getText (); +} + +/** + * Returns the text stored at the given column index in the receiver, + * or empty string if the text has not been set. + * + * @param index the column index + * @return the text stored at the given column index in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return ""; + return handle.getTableItemObject(index).getText(); +} + +//void redraw () { +// if ((parent.style & SWT.VIRTUAL) != 0) cached = true; +// if (parent.currentItem == this || parent.drawCount != 0) return; +// int hwnd = parent.handle; +// if (!OS.IsWindowVisible (hwnd)) return; +// int index = parent.indexOf (this); +// if (index == -1) return; +// OS.SendMessage (hwnd, OS.LVM_REDRAWITEMS, index, index); +//} + +//void redraw (int column, boolean drawText, boolean drawImage) { +// if ((parent.style & SWT.VIRTUAL) != 0) cached = true; +// if (parent.currentItem == this || parent.drawCount != 0) return; +// int hwnd = parent.handle; +// if (!OS.IsWindowVisible (hwnd)) return; +// int index = parent.indexOf (this); +// if (index == -1) return; +// RECT rect = getBounds (index, column, drawText, drawImage); +// OS.InvalidateRect (hwnd, rect, true); +//} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseWidget () { + super.releaseWidget (); +// strings = null; + images = null; +// cellBackground = cellForeground = cellFont = null; +} + +/** + * Sets the receiver's background color to the color specified + * by the argument, or to the default system color for the item + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + * + */ +public void setBackground (Color color) { + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setBackground(color == null? null: color.handle); + int index = parent.indexOf(this); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index); +} + +/** + * Sets the background color at the given column index in the receiver + * to the color specified by the argument, or to the default system color for the item + * if the argument is null. + * + * @param index the column index + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + * + */ +public void setBackground (int index, Color color) { + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTableItemObject(index).setBackground(color == null? null: color.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index); +} + +/** + * Sets the checked state of the checkbox for this item. This state change + * only applies if the Table was created with the SWT.CHECK style. + * + * @param checked the new checked state of the checkbox + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setChecked (boolean checked) { + checkWidget(); + if ((parent.style & SWT.CHECK) == 0) return; + handle.setChecked(checked); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + // TODO: is it always 0 if columns are reordered? + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), 0); +} + +//void setChecked (boolean checked, boolean notify) { +// this.checked = checked; +// if (notify) { +// Event event = new Event(); +// event.item = this; +// event.detail = SWT.CHECK; +// parent.postEvent (SWT.Selection, event); +// } +// redraw (); +//} + +/** + * Sets the font that the receiver will use to paint textual information + * for this item to the font specified by the argument, or to the default font + * for that kind of control if the argument is null. + * + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setFont (Font font){ + checkWidget (); + if (font != null && font.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setFont(font == null? null: font.handle); + int index = parent.indexOf(this); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index); +} + +/** + * Sets the font that the receiver will use to paint textual information + * for the specified cell in this item to the font specified by the + * argument, or to the default font for that kind of control if the + * argument is null. + * + * @param index the column index + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setFont (int index, Font font) { + checkWidget (); + if (font != null && font.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTableItemObject(index).setFont(font == null? null: font.handle); + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + parent.adjustColumnWidth(); +} + +/** + * Sets the receiver's foreground color to the color specified + * by the argument, or to the default system color for the item + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + */ +public void setForeground (Color color){ + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setForeground(color == null? null: color.handle); + int index = parent.indexOf(this); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index); +} + +/** + * Sets the foreground color at the given column index in the receiver + * to the color specified by the argument, or to the default system color for the item + * if the argument is null. + * + * @param index the column index + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setForeground (int index, Color color){ + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTableItemObject(index).setForeground(color == null? null: color.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index); +} + +/** + * Sets the grayed state of the checkbox for this item. This state change + * only applies if the Table was created with the SWT.CHECK style. + * + * @param grayed the new grayed state of the checkbox; + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setGrayed (boolean grayed) { + checkWidget (); + if ((parent.style & SWT.CHECK) == 0) return; + handle.setGrayed(grayed); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + // TODO: is it always 0 if columns are reordered? + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), 0); +} + +/** + * Sets the image for multiple columns in the table. + * + * @param images the array of new images + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of images is null
    • + *
    • ERROR_INVALID_ARGUMENT - if one of the images has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image [] images) { + checkWidget(); + if (images == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; i + *
  • ERROR_INVALID_ARGUMENT - if the image has been disposed
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (int index, Image image) { + checkWidget(); + if (image != null && image.isDisposed ()) { + error(SWT.ERROR_INVALID_ARGUMENT); + } + if (index == 0) { + if (image != null && image.type == SWT.ICON) { + if (image.equals (this.image)) return; + } + super.setImage (image); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + if (images == null && index != 0) { + images = new Image [count]; + images [0] = image; + } + if (images != null) { + if (image != null && image.type == SWT.ICON) { + if (image.equals (images [index])) return; + } + images [index] = image; + } + handle.getTableItemObject(index).setIcon(image != null? new ImageIcon(image.handle): null); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableCellUpdated(index, index); + parent.adjustColumnWidth(); +// +// +// if (images == null && index != 0) images = new Image [count]; +// if (images != null) { +// if (image != null && image.type == SWT.ICON) { +// if (image.equals (images [index])) return; +// } +// images [index] = image; +// } +// +// /* Ensure that the image list is created */ +// parent.imageIndex (image); +// +// if (index == 0) parent.setScrollWidth (this, false); +// redraw (index, false, true); +} + +public void setImage (Image image) { + checkWidget (); + setImage (0, image); +} + +/** + * Sets the indent of the first column's image, expressed in terms of the image's width. + * + * @param indent the new indent + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @deprecated this functionality is not supported on most platforms + */ +public void setImageIndent (int indent) { + checkWidget(); + if (indent < 0) return; + Utils.notImplemented(); +// if (imageIndent == indent) return; +// imageIndent = indent; +// if ((parent.style & SWT.VIRTUAL) != 0) { +// cached = true; +// } else { +// int index = parent.indexOf (this); +// if (index != -1) { +// int hwnd = parent.handle; +// LVITEM lvItem = new LVITEM (); +// lvItem.mask = OS.LVIF_INDENT; +// lvItem.iItem = index; +// lvItem.iIndent = indent; +// OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem); +// } +// } +// parent.setScrollWidth (this, false); +// redraw (); +} + +/** + * Sets the text for multiple columns in the table. + * + * @param strings the array of new strings + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String [] strings) { + checkWidget(); + if (strings == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the text is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (int index, String string) { + checkWidget(); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + if(index == 0) { + super.setText(string); + } + handle.getTableItemObject(index).setText(string); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index); + parent.adjustColumnWidth(); +} + +public void setText (String string) { + checkWidget(); + setText (0, string); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java new file mode 100644 index 00000000000..4f5a5e94630 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java @@ -0,0 +1,1796 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.util.EventObject; + +import javax.swing.JButton; +import javax.swing.RootPaneContainer; +import javax.swing.event.DocumentEvent; +import javax.swing.text.BadLocationException; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.internal.swing.CText; +import org.eclipse.swt.internal.swing.TextFilterEvent; +import org.eclipse.swt.internal.swing.UIThreadUtils; + +/** + * Instances of this class are selectable user interface + * objects that allow the user to enter and modify text. + *

    + *

    + *
    Styles:
    + *
    CENTER, LEFT, MULTI, PASSWORD, SINGLE, RIGHT, READ_ONLY, WRAP
    + *
    Events:
    + *
    DefaultSelection, Modify, Verify
    + *
    + *

    + * Note: Only one of the styles MULTI and SINGLE may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class Text extends Scrollable { + int tabs, oldStart, oldEnd; + boolean doubleClick, ignoreModify, ignoreCharacter; + + /** + * The maximum number of characters that can be entered + * into a text widget. + *

    + * Note that this value is platform dependent, based upon + * the native widget implementation. + *

    + */ + public static final int LIMIT; + + /** + * The delimiter used by multi-line text widgets. When text + * is queried and from the widget, it will be delimited using + * this delimiter. + */ + public static final String DELIMITER; + + /* + * This code is intentionally commented. + */ +// static final char PASSWORD; + + /* + * These values can be different on different platforms. + * Therefore they are not initialized in the declaration + * to stop the compiler from inlining. + */ + static { + LIMIT = 0x7FFFFFFF; + DELIMITER = System.getProperty("line.separator");//"\n"; + } + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SINGLE + * @see SWT#MULTI + * @see SWT#READ_ONLY + * @see SWT#WRAP + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Text (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is modified, by sending + * it one of the messages defined in the ModifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #removeModifyListener + */ +public void addModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Modify, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is not called for texts. + * widgetDefaultSelected is typically called when ENTER is pressed in a single-line text. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is verified, by sending + * it one of the messages defined in the VerifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #removeVerifyListener + */ +public void addVerifyListener (VerifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Verify, typedListener); +} + +/** + * Appends a string. + *

    + * The new text is appended to the text at + * the end of the widget. + *

    + * + * @param string the string to be appended + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void append (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + CText cText = (CText)handle; + String text = cText.getText(); +// if (hooks (SWT.Verify) || filters (SWT.Verify)) { +// int length = text.length(); +// string = verifyText (string, length, length, null); +// if (string == null) return; +// } + cText.setText(text + string); +} + +static int checkStyle (int style) { + if ((style & SWT.SINGLE) != 0 && (style & SWT.MULTI) != 0) { + style &= ~SWT.MULTI; + } + style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0); + if ((style & SWT.SINGLE) != 0) style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP); + if ((style & SWT.WRAP) != 0) { + style |= SWT.MULTI; + style &= ~SWT.H_SCROLL; + } + if ((style & SWT.MULTI) != 0) style &= ~SWT.PASSWORD; + if ((style & (SWT.SINGLE | SWT.MULTI)) != 0) return style; + if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) return style | SWT.MULTI; + return style | SWT.SINGLE; +} + +/** + * Clears the selection. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void clearSelection () { + checkWidget (); + CText cText = (CText)handle; + cText.setSelectionStart(0); + cText.setSelectionStart(0); +} + +//public Point computeSize (int wHint, int hHint, boolean changed) { +// checkWidget (); +// int height = 0, width = 0; +// if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { +// int newFont, oldFont = 0; +// int hDC = OS.GetDC (handle); +// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// int count = OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0); +// height = count * tm.tmHeight; +// RECT rect = new RECT (); +// int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX; +// boolean wrap = (style & SWT.MULTI) != 0 && (style & SWT.WRAP) != 0; +// if (wrap && wHint != SWT.DEFAULT) { +// flags |= OS.DT_WORDBREAK; +// rect.right = wHint; +// } +// int length = OS.GetWindowTextLength (handle); +// if (length != 0) { +// TCHAR buffer = new TCHAR (getCodePage (), length + 1); +// OS.GetWindowText (handle, buffer, length + 1); +// OS.DrawText (hDC, buffer, length, rect, flags); +// width = rect.right - rect.left; +// } +// if (wrap && hHint == SWT.DEFAULT) { +// int newHeight = rect.bottom - rect.top; +// if (newHeight != 0) height = newHeight; +// } +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (handle, hDC); +// } +// if (width == 0) width = DEFAULT_WIDTH; +// if (height == 0) height = DEFAULT_HEIGHT; +// if (wHint != SWT.DEFAULT) width = wHint; +// if (hHint != SWT.DEFAULT) height = hHint; +// Rectangle trim = computeTrim (0, 0, width, height); +// return new Point (trim.width, trim.height); +//} +// +//public Rectangle computeTrim (int x, int y, int width, int height) { +// checkWidget (); +// Rectangle rect = super.computeTrim (x, y, width, height); +// /* +// * The preferred height of a single-line text widget +// * has been hand-crafted to be the same height as +// * the single-line text widget in an editable combo +// * box. +// */ +// int margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0); +// rect.x -= margins & 0xFFFF; +// rect.width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); +// if ((style & SWT.H_SCROLL) != 0) rect.width++; +// if ((style & SWT.BORDER) != 0) { +// rect.x -= 1; +// rect.y -= 1; +// rect.width += 2; +// rect.height += 2; +// } +// return rect; +//} + +/** + * Copies the selected text. + *

    + * The current selection is copied to the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void copy () { + checkWidget (); + ((CText)handle).copy(); +} + +Container createHandle () { + return (Container)CText.Factory.newInstance(this, style); +} + +void createWidget () { + super.createWidget (); + doubleClick = true; + setTabStops (tabs = 8); +// fixAlignment (); +} + +/** + * Cuts the selected text. + *

    + * The current selection is first copied to the + * clipboard and then deleted from the widget. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void cut () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CText)handle).cut(); +} + +/** + * Returns the line number of the caret. + *

    + * The line number of the caret is returned. + *

    + * + * @return the line number + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getCaretLineNumber () { + checkWidget (); + return ((CText)handle).getCaretLineNumber(); +} + +/** + * Returns a point describing the receiver's location relative + * to its parent (or its display if its parent is null). + *

    + * The location of the caret is returned. + *

    + * + * @return a point, the location of the caret + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getCaretLocation () { + checkWidget (); + java.awt.Point point = ((CText)handle).getCaretLocation(); + return new Point(point.x, point.y); +} + +/** + * Returns the character position of the caret. + *

    + * Indexing is zero based. + *

    + * + * @return the position of the caret + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getCaretPosition () { + checkWidget (); + return ((CText)handle).getCaretPosition(); +} + +/** + * Returns the number of characters. + * + * @return number of characters in the widget + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getCharCount () { + checkWidget (); + return ((CText)handle).getText().length(); +} + +/** + * Returns the double click enabled flag. + *

    + * The double click flag enables or disables the + * default action of the text widget when the user + * double clicks. + *

    + * + * @return whether or not double click is enabled + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getDoubleClickEnabled () { + checkWidget (); + return doubleClick; +} + +/** + * Returns the echo character. + *

    + * The echo character is the character that is + * displayed when the user enters text or the + * text is changed by the programmer. + *

    + * + * @return the echo character + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setEchoChar + */ +public char getEchoChar () { + checkWidget (); + return ((CText)handle).getEchoChar(); +} + +/** + * Returns the editable state. + * + * @return whether or not the receiver is editable + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getEditable () { + checkWidget (); + return ((CText)handle).isEditable(); +} + +/** + * Returns the number of lines. + * + * @return the number of lines in the widget + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getLineCount () { + checkWidget (); + return ((CText)handle).getLineCount(); +} + +/** + * Returns the line delimiter. + * + * @return a string that is the line delimiter + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #DELIMITER + */ +public String getLineDelimiter () { + checkWidget (); + return DELIMITER; +} + +/** + * Returns the height of a line. + * + * @return the height of a row of text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getLineHeight () { + checkWidget (); + return ((CText)handle).getRowHeight(); +} + +/** + * Returns the orientation of the receiver, which will be one of the + * constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. + * + * @return the orientation style + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1.2 + */ +public int getOrientation () { + checkWidget(); + return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); +} + +/** + * Returns a Point whose x coordinate is the + * character position representing the start of the selected + * text, and whose y coordinate is the character position + * representing the end of the selection. An "empty" selection + * is indicated by the x and y coordinates having the same value. + *

    + * Indexing is zero based. The range of a selection is from + * 0..N where N is the number of characters in the widget. + *

    + * + * @return a point representing the selection start and end + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelection () { + checkWidget (); + CText cText = (CText)handle; + return new Point(cText.getSelectionStart(), cText.getSelectionEnd()); +} + +/** + * Returns the number of selected characters. + * + * @return the number of selected characters. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionCount () { + checkWidget (); + Point selection = getSelection (); + return selection.y - selection.x; +} + +/** + * Gets the selected text, or an empty string if there is no current selection. + * + * @return the selected text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getSelectionText () { + checkWidget (); + /* + * NOTE: The current implementation uses substring () + * which can reference a potentially large character + * array. + */ + Point selection = getSelection (); + return getText ().substring (selection.x, selection.y); +} + +/** + * Returns the number of tabs. + *

    + * Tab stop spacing is specified in terms of the + * space (' ') character. The width of a single + * tab stop is the pixel width of the spaces. + *

    + * + * @return the number of tab characters + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTabs () { + checkWidget (); + return tabs; +} + +/** + * Returns the widget text. + *

    + * The text for a text widget is the characters in the widget, or + * an empty string if this has never been set. + *

    + * + * @return the widget text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + return ((CText)handle).getText(); +} + +/** + * Returns a range of text. Returns an empty string if the + * start of the range is greater than the end. + *

    + * Indexing is zero based. The range of + * a selection is from 0..N-1 where N is + * the number of characters in the widget. + *

    + * + * @param start the start of the range + * @param end the end of the range + * @return the range of text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText (int start, int end) { + checkWidget (); + if (!(start <= end && 0 <= end)) return ""; + CText cText = (CText)handle; + int length = cText.getText().length(); + end = Math.min (end, length - 1); + start = Math.max (0, start); + if(start > end) { + return ""; + } + try { + return cText.getText(start, end - start); + } catch(BadLocationException e) { + } + return ""; +} + +/** + * Returns the maximum number of characters that the receiver is capable of holding. + *

    + * If this has not been changed by setTextLimit(), + * it will be the constant Text.LIMIT. + *

    + * + * @return the text limit + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #LIMIT + */ +public int getTextLimit () { + checkWidget (); + return ((CText)handle).getTextLimit(); +} + +/** + * Returns the zero-relative index of the line which is currently + * at the top of the receiver. + *

    + * This index can change when lines are scrolled or new lines are added or removed. + *

    + * + * @return the index of the top line + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopIndex () { + checkWidget (); + if ((style & SWT.SINGLE) != 0) return 0; + return ((CText)handle).getViewPosition().y / getLineHeight(); +} + +/** + * Returns the top pixel. + *

    + * The top pixel is the pixel position of the line + * that is currently at the top of the widget. On + * some platforms, a text widget can be scrolled by + * pixels instead of lines so that a partial line + * is displayed at the top of the widget. + *

    + * The top pixel changes when the widget is scrolled. + * The top pixel does not include the widget trimming. + *

    + * + * @return the pixel position of the top line + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTopPixel () { + checkWidget (); + return ((CText)handle).getViewPosition().y; +} + +/** + * Inserts a string. + *

    + * The old selection is replaced with the new text. + *

    + * + * @param string the string + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void insert (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + CText cText = (CText)handle; +// if (hooks (SWT.Verify) || filters (SWT.Verify)) { +// string = verifyText (string, cText.getSelectionStart(), cText.getSelectionEnd(), null); +// if (string == null) return; +// } + cText.replaceSelection(string); +} + +/** + * Pastes text from clipboard. + *

    + * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void paste () { + checkWidget (); + if ((style & SWT.READ_ONLY) != 0) return; + ((CText)handle).paste(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #addModifyListener + */ +public void removeModifyListener (ModifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Modify, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is verified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see VerifyListener + * @see #addVerifyListener + */ +public void removeVerifyListener (VerifyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Verify, listener); +} + +/** + * Selects all the text in the receiver. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void selectAll () { + checkWidget (); + ((CText)handle).selectAll(); +} + +//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) { +// if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) { +// return false; +// } +// if ((style & SWT.READ_ONLY) != 0) return true; +// if (ignoreVerify) return true; +// if (type != SWT.KeyDown) return true; +// if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) { +// return true; +// } +// if (event.character == 0) return true; +// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true; +// char key = event.character; +// int stateMask = event.stateMask; +// +// /* +// * Disable all magic keys that could modify the text +// * and don't send events when Alt, Shift or Ctrl is +// * pressed. +// */ +// switch (msg) { +// case OS.WM_CHAR: +// if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break; +// // FALL THROUGH +// case OS.WM_KEYDOWN: +// if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false; +// break; +// } +// +// /* +// * If the left button is down, the text widget refuses the character. +// */ +// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) { +// return true; +// } +// +// /* Verify the character */ +// String oldText = ""; +// int [] start = new int [1], end = new int [1]; +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// switch (key) { +// case 0x08: /* Bs */ +// if (start [0] == end [0]) { +// if (start [0] == 0) return true; +// int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0); +// if (start [0] == lineStart) { +// start [0] = start [0] - DELIMITER.length (); +// } else { +// start [0] = start [0] - 1; +// if (OS.IsDBLocale) { +// int [] newStart = new int [1], newEnd = new int [1]; +// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]); +// OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd); +// if (start [0] != newStart [0]) start [0] = start [0] - 1; +// } +// } +// start [0] = Math.max (start [0], 0); +// } +// break; +// case 0x7F: /* Del */ +// if (start [0] == end [0]) { +// int length = OS.GetWindowTextLength (handle); +// if (start [0] == length) return true; +// int line = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0); +// int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0); +// if (end [0] == lineStart - DELIMITER.length ()) { +// end [0] = end [0] + DELIMITER.length (); +// } else { +// end [0] = end [0] + 1; +// if (OS.IsDBLocale) { +// int [] newStart = new int [1], newEnd = new int [1]; +// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]); +// OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd); +// if (end [0] != newEnd [0]) end [0] = end [0] + 1; +// } +// } +// end [0] = Math.min (end [0], length); +// } +// break; +// case '\r': /* Return */ +// if ((style & SWT.SINGLE) != 0) return true; +// oldText = DELIMITER; +// break; +// default: /* Tab and other characters */ +// if (key != '\t' && key < 0x20) return true; +// oldText = new String (new char [] {key}); +// break; +// } +// String newText = verifyText (oldText, start [0], end [0], event); +// if (newText == null) return false; +// if (newText == oldText) return true; +// newText = Display.withCrLf (newText); +// TCHAR buffer = new TCHAR (getCodePage (), newText, true); +// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]); +// /* +// * Feature in Windows. When an edit control with ES_MULTILINE +// * style that does not have the WS_VSCROLL style is full (i.e. +// * there is no space at the end to draw any more characters), +// * EM_REPLACESEL sends a WM_CHAR with a backspace character +// * to remove any further text that is added. This is an +// * implementation detail of the edit control that is unexpected +// * and can cause endless recursion when EM_REPLACESEL is sent +// * from a WM_CHAR handler. The fix is to ignore calling the +// * handler from WM_CHAR. +// */ +// ignoreCharacter = true; +// OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer); +// ignoreCharacter = false; +// return false; +//} +// + +/** + * Sets the double click enabled flag. + *

    + * The double click flag enables or disables the + * default action of the text widget when the user + * double clicks. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *

    + * + * @param doubleClick the new double click flag + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDoubleClickEnabled (boolean doubleClick) { + checkWidget (); + this.doubleClick = doubleClick; +} + +/** + * Sets the echo character. + *

    + * The echo character is the character that is + * displayed when the user enters text or the + * text is changed by the programmer. Setting + * the echo character to '\0' clears the echo + * character and redraws the original text. + * If for any reason the echo character is invalid, + * or if the platform does not allow modification + * of the echo character, the default echo character + * for the platform is used. + *

    + * + * @param echo the new echo character + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEchoChar (char echo) { + checkWidget (); + if ((style & SWT.MULTI) != 0) return; + ((CText)handle).setEchoChar(echo); +} + +/** + * Sets the editable state. + * + * @param editable the new editable state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEditable (boolean editable) { + checkWidget (); + style &= ~SWT.READ_ONLY; + if (!editable) style |= SWT.READ_ONLY; + ((CText)handle).setEditable(editable); +} + +/** + * Sets the orientation of the receiver, which must be one + * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *

    + * + * @param orientation new orientation style + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1.2 + */ +public void setOrientation (int orientation) { + checkWidget(); + int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT; + if ((orientation & flags) == 0 || (orientation & flags) == flags) return; + style &= ~flags; + style |= orientation & flags; + ComponentOrientation o; + if ((style & SWT.RIGHT_TO_LEFT) != 0) { + o = ComponentOrientation.RIGHT_TO_LEFT; + } else { + o = ComponentOrientation.LEFT_TO_RIGHT; + } + ((CText)handle).setComponentOrientation(o); +} + +/** + * Sets the selection. + *

    + * Indexing is zero based. The range of + * a selection is from 0..N where N is + * the number of characters in the widget. + *

    + * Text selections are specified in terms of + * caret positions. In a text widget that + * contains N characters, there are N+1 caret + * positions, ranging from 0..N. This differs + * from other functions that address character + * position such as getText () that use the + * regular array indexing rules. + *

    + * + * @param start new caret position + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int start) { + checkWidget (); + ((CText)handle).setSelectionStart(start); + ((CText)handle).setSelectionEnd(start); +} + +/** + * Sets the selection to the range specified + * by the given start and end indices. + *

    + * Indexing is zero based. The range of + * a selection is from 0..N where N is + * the number of characters in the widget. + *

    + * Text selections are specified in terms of + * caret positions. In a text widget that + * contains N characters, there are N+1 caret + * positions, ranging from 0..N. This differs + * from other functions that address character + * position such as getText () that use the + * usual array indexing rules. + *

    + * + * @param start the start of the range + * @param end the end of the range + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (int start, int end) { + checkWidget (); + ((CText)handle).setSelectionStart(start); + ((CText)handle).setSelectionEnd(end); +} + +//public void setRedraw (boolean redraw) { +// checkWidget (); +// super.setRedraw (redraw); +// /* +// * Feature in Windows. When WM_SETREDRAW is used to turn +// * redraw off, the edit control is not scrolled to show the +// * i-beam. The fix is to detect that the i-beam has moved +// * while redraw is turned off and force it to be visible +// * when redraw is restored. +// */ +// if (drawCount != 0) return; +// int [] start = new int [1], end = new int [1]; +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// if (!redraw) { +// oldStart = start [0]; oldEnd = end [0]; +// } else { +// if (oldStart == start [0] && oldEnd == end [0]) return; +// OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0); +// } +//} + +/** + * Sets the selection to the range specified + * by the given point, where the x coordinate + * represents the start index and the y coordinate + * represents the end index. + *

    + * Indexing is zero based. The range of + * a selection is from 0..N where N is + * the number of characters in the widget. + *

    + * Text selections are specified in terms of + * caret positions. In a text widget that + * contains N characters, there are N+1 caret + * positions, ranging from 0..N. This differs + * from other functions that address character + * position such as getText () that use the + * usual array indexing rules. + *

    + * + * @param selection the point + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (Point selection) { + checkWidget (); + if (selection == null) error (SWT.ERROR_NULL_ARGUMENT); + setSelection (selection.x, selection.y); +} + +/** + * Sets the number of tabs. + *

    + * Tab stop spacing is specified in terms of the + * space (' ') character. The width of a single + * tab stop is the pixel width of the spaces. + *

    + * + * @param tabs the number of tabs + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTabs (int tabs) { + checkWidget (); + if (tabs < 0) return; + setTabStops (this.tabs = tabs); +} + +void setTabStops (int tabs) { + ((CText)handle).setTabSize(tabs); +} + +/** + * Sets the contents of the receiver to the given string. If the receiver has style + * SINGLE and the argument contains multiple lines of text, the result of this + * operation is undefined and may vary from platform to platform. + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + CText cText = (CText)handle; +// if (hooks (SWT.Verify) || filters (SWT.Verify)) { +// int length = cText.getText().length(); +// string = verifyText (string, 0, length, null); +// if (string == null) return; +// } + cText.setText(string); + if ((style & SWT.MULTI) != 0) { + sendEvent (SWT.Modify); + // widget could be disposed at this point + } +} + +/** + * Sets the maximum number of characters that the receiver + * is capable of holding to be the argument. + *

    + * Instead of trying to set the text limit to zero, consider + * creating a read-only text widget. + *

    + * To reset this value to the default, use setTextLimit(Text.LIMIT). + * Specifying a limit value larger than Text.LIMIT sets the + * receiver's limit to Text.LIMIT. + *

    + * + * @param limit new text limit + * + * @exception IllegalArgumentException
      + *
    • ERROR_CANNOT_BE_ZERO - if the limit is zero
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #LIMIT + */ +public void setTextLimit (int limit) { + checkWidget (); + if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO); + ((CText)handle).setTextLimit(limit); +} + +/** + * Sets the zero-relative index of the line which is currently + * at the top of the receiver. This index can change when lines + * are scrolled or new lines are added and removed. + * + * @param index the index of the top item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTopIndex (int index) { + checkWidget (); + if ((style & SWT.SINGLE) != 0) return; + CText cText = (CText)handle; + cText.setViewPosition(new java.awt.Point(cText.getViewPosition().x, index / getLineHeight())); +} + +/** + * Shows the selection. + *

    + * If the selection is already showing + * in the receiver, this method simply returns. Otherwise, + * lines are scrolled until the selection is visible. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void showSelection () { + checkWidget (); + ((CText)handle).showSelection(); +} + +String verifyText (String string, int start, int end, Event keyEvent) { + Event event = new Event (); + event.text = string; + event.start = start; + event.end = end; + if (keyEvent != null) { + event.character = keyEvent.character; + event.keyCode = keyEvent.keyCode; + event.stateMask = keyEvent.stateMask; + } + sendEvent (SWT.Verify, event); + if (!event.doit || isDisposed ()) return null; + return event.text; +} + +//int wcsToMbcsPos (int wcsPos) { +// if (wcsPos <= 0) return 0; +// if (OS.IsUnicode) return wcsPos; +// int cp = getCodePage (); +// int wcsTotal = 0, mbcsTotal = 0; +// byte [] buffer = new byte [128]; +// String delimiter = getLineDelimiter (); +// int delimiterSize = delimiter.length (); +// int count = OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0); +// for (int line=0; line buffer.length) { +// buffer = new byte [mbcsSize + delimiterSize]; +// } +// //ENDIAN +// buffer [0] = (byte) (mbcsSize & 0xFF); +// buffer [1] = (byte) (mbcsSize >> 8); +// mbcsSize = OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer); +// wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer, mbcsSize, null, 0); +// } +// if (line - 1 != count) { +// for (int i=0; i= wcsPos) { +// wcsSize = 0; +// int index = 0; +// while (index < mbcsSize) { +// if ((wcsTotal + wcsSize) == wcsPos) { +// return mbcsTotal + index; +// } +// if (OS.IsDBCSLeadByte (buffer [index++])) index++; +// wcsSize++; +// } +// return mbcsTotal + mbcsSize; +// } +// wcsTotal += wcsSize; +// mbcsTotal += mbcsSize; +// } +// return mbcsTotal; +//} + +//LRESULT WM_CHAR (int wParam, int lParam) { +// if (ignoreCharacter) return null; +// LRESULT result = super.WM_CHAR (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Bug in Windows. When the user types CTRL and BS +// * in an edit control, a DEL character is generated. +// * Rather than deleting the text, the DEL character +// * is inserted into the control. The fix is to detect +// * this case and not call the window proc. +// */ +// switch (wParam) { +// case SWT.DEL: +// if (OS.GetKeyState (OS.VK_CONTROL) < 0) { +// return LRESULT.ZERO; +// } +// } +// +// /* +// * Feature in Windows. For some reason, when the +// * widget is a single line text widget, when the +// * user presses tab, return or escape, Windows beeps. +// * The fix is to look for these keys and not call +// * the window proc. +// */ +// if ((style & SWT.SINGLE) != 0) { +// switch (wParam) { +// case SWT.CR: +// postEvent (SWT.DefaultSelection); +// // FALL THROUGH +// case SWT.TAB: +// case SWT.ESC: return LRESULT.ZERO; +// } +// } +// return result; +//} +// +//LRESULT WM_CLEAR (int wParam, int lParam) { +// LRESULT result = super.WM_CLEAR (wParam, lParam); +// if (result != null) return result; +// return wmClipboard (OS.WM_CLEAR, wParam, lParam); +//} +// +//LRESULT WM_CUT (int wParam, int lParam) { +// LRESULT result = super.WM_CUT (wParam, lParam); +// if (result != null) return result; +// return wmClipboard (OS.WM_CUT, wParam, lParam); +//} +// +//LRESULT WM_GETDLGCODE (int wParam, int lParam) { +// LRESULT result = super.WM_GETDLGCODE (wParam, lParam); +// if (result != null) return result; +// +// /* +// * Bug in WinCE PPC. For some reason, sending WM_GETDLGCODE +// * to a multi-line edit control causes it to ignore return and +// * tab keys. The fix is to return the value which is normally +// * returned by the text window proc on other versions of Windows. +// */ +// if (OS.IsPPC) { +// if ((style & SWT.MULTI) != 0 && (style & SWT.READ_ONLY) == 0 && lParam == 0) { +// return new LRESULT (OS.DLGC_HASSETSEL | OS.DLGC_WANTALLKEYS | OS.DLGC_WANTCHARS); +// } +// } +// +// /* +// * Feature in Windows. Despite the fact that the +// * edit control is read only, it still returns a +// * dialog code indicating that it wants all keys. +// * The fix is to detect this case and clear the bits. +// * +// * NOTE: A read only edit control processes arrow keys +// * so DLGC_WANTARROWS should not be cleared. +// */ +// if ((style & SWT.READ_ONLY) != 0) { +// int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam); +// code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB); +// return new LRESULT (code); +// } +// return null; +//} +// +//LRESULT WM_IME_CHAR (int wParam, int lParam) { +// +// /* Process a DBCS character */ +// Display display = this.display; +// display.lastKey = 0; +// display.lastAscii = wParam; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) { +// return LRESULT.ZERO; +// } +// +// /* +// * Feature in Windows. The Windows text widget uses +// * two 2 WM_CHAR's to process a DBCS key instead of +// * using WM_IME_CHAR. The fix is to allow the text +// * widget to get the WM_CHAR's but ignore sending +// * them to the application. +// */ +// ignoreCharacter = true; +// int result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam); +// MSG msg = new MSG (); +// int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; +// while (OS.PeekMessage (msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) { +// OS.TranslateMessage (msg); +// OS.DispatchMessage (msg); +// } +// ignoreCharacter = false; +// +// sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam); +// // widget could be disposed at this point +// display.lastKey = display.lastAscii = 0; +// return new LRESULT (result); +//} +// +//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { +// /* +// * Prevent Windows from processing WM_LBUTTONDBLCLK +// * when double clicking behavior is disabled by not +// * calling the window proc. +// */ +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// if (!doubleClick) return LRESULT.ZERO; +// +// /* +// * Bug in Windows. When the last line of text in the +// * widget is double clicked and the line is empty, Windows +// * hides the i-beam then moves it to the first line in +// * the widget but does not scroll to show the user. +// * If the user types without clicking the mouse, invalid +// * characters are displayed at the end of each line of +// * text in the widget. The fix is to detect this case +// * and avoid calling the window proc. +// */ +// int [] start = new int [1], end = new int [1]; +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// if (start [0] == end [0]) { +// int length = OS.GetWindowTextLength (handle); +// if (length == start [0]) { +// int result = OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0); +// if (result == 0) return LRESULT.ZERO; +// } +// } +// return null; +//} +// +//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +// if (!OS.IsPPC) return super.WM_LBUTTONDOWN (wParam, lParam); +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// /* +// * Note: On WinCE PPC, only attempt to recognize the gesture for +// * a context menu when the control contains a valid menu or there +// * are listeners for the MenuDetect event. +// * +// * Note: On WinCE PPC, the gesture that brings up a popup menu +// * on the text widget must keep the current text selection. As a +// * result, the window proc is only called if the menu is not shown. +// */ +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (hasMenu || hooks (SWT.MenuDetect)) { +// int x = (short) (lParam & 0xFFFF); +// int y = (short) (lParam >> 16); +// SHRGINFO shrg = new SHRGINFO (); +// shrg.cbSize = SHRGINFO.sizeof; +// shrg.hwndClient = handle; +// shrg.ptDown_x = x; +// shrg.ptDown_y = y; +// shrg.dwFlags = OS.SHRG_RETURNCMD; +// int type = OS.SHRecognizeGesture (shrg); +// if (type == OS.GN_CONTEXTMENU) { +// showMenu (x, y); +// return LRESULT.ONE; +// } +// } +// int result = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// return new LRESULT (result); +//} +// +//LRESULT WM_PASTE (int wParam, int lParam) { +// LRESULT result = super.WM_PASTE (wParam, lParam); +// if (result != null) return result; +// return wmClipboard (OS.WM_PASTE, wParam, lParam); +//} +// +//LRESULT WM_UNDO (int wParam, int lParam) { +// LRESULT result = super.WM_UNDO (wParam, lParam); +// if (result != null) return result; +// return wmClipboard (OS.WM_UNDO, wParam, lParam); +//} +// +//LRESULT wmClipboard (int msg, int wParam, int lParam) { +// if ((style & SWT.READ_ONLY) != 0) return null; +// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null; +// boolean call = false; +// int [] start = new int [1], end = new int [1]; +// String newText = null; +// switch (msg) { +// case OS.WM_CLEAR: +// case OS.WM_CUT: +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// if (start [0] != end [0]) { +// newText = ""; +// call = true; +// } +// break; +// case OS.WM_PASTE: +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// newText = getClipboardText (); +// break; +// case OS.EM_UNDO: +// case OS.WM_UNDO: +// if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) { +// OS.SendMessage (handle, OS.EM_GETSEL, start, end); +// ignoreModify = ignoreCharacter = true; +// callWindowProc (handle, msg, wParam, lParam); +// newText = getSelectionText (); +// callWindowProc (handle, msg, wParam, lParam); +// ignoreModify = ignoreCharacter = false; +// } +// break; +// } +// if (newText != null) { +// String oldText = newText; +// newText = verifyText (newText, start [0], end [0], null); +// if (newText == null) return LRESULT.ZERO; +// if (!newText.equals (oldText)) { +// if (call) { +// callWindowProc (handle, msg, wParam, lParam); +// } +// newText = Display.withCrLf (newText); +// TCHAR buffer = new TCHAR (getCodePage (), newText, true); +// /* +// * Feature in Windows. When an edit control with ES_MULTILINE +// * style that does not have the WS_VSCROLL style is full (i.e. +// * there is no space at the end to draw any more characters), +// * EM_REPLACESEL sends a WM_CHAR with a backspace character +// * to remove any further text that is added. This is an +// * implementation detail of the edit control that is unexpected +// * and can cause endless recursion when EM_REPLACESEL is sent +// * from a WM_CHAR handler. The fix is to ignore calling the +// * handler from WM_CHAR. +// */ +// ignoreCharacter = true; +// OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer); +// ignoreCharacter = false; +// return LRESULT.ZERO; +// } +// } +// if (msg == OS.WM_UNDO) { +// ignoreVerify = ignoreCharacter = true; +// callWindowProc (handle, OS.WM_UNDO, wParam, lParam); +// ignoreVerify = ignoreCharacter = false; +// return LRESULT.ONE; +// } +// return null; +//} +// +//LRESULT wmCommandChild (int wParam, int lParam) { +// int code = wParam >> 16; +// switch (code) { +// case OS.EN_CHANGE: +// if (ignoreModify) break; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the modify +// * event. If this happens, end the processing of the +// * Windows message by returning zero as the result of +// * the window proc. +// */ +// sendEvent (SWT.Modify); +// if (isDisposed ()) return LRESULT.ZERO; +// break; +// case OS.EN_ALIGN_LTR_EC: +// style &= ~SWT.RIGHT_TO_LEFT; +// style |= SWT.LEFT_TO_RIGHT; +// fixAlignment (); +// break; +// case OS.EN_ALIGN_RTL_EC: +// style &= ~SWT.LEFT_TO_RIGHT; +// style |= SWT.RIGHT_TO_LEFT; +// fixAlignment (); +// break; +// } +// return super.wmCommandChild (wParam, lParam); +//} + +public void processEvent(EventObject e) { + if(e instanceof TextFilterEvent) { + if(!hooks(SWT.Verify)) { super.processEvent(e); return; } + } else { super.processEvent(e); return; } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + if(e instanceof TextFilterEvent) { + TextFilterEvent filterEvent = (TextFilterEvent)e; + filterEvent.setText(verifyText(filterEvent.getText(), filterEvent.getStart(), filterEvent.getStart() + filterEvent.getEnd(), createKeyEvent(filterEvent.getKeyEvent()))); + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +protected boolean isTraversalKey(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_ENTER: + return (style & SWT.MULTI) == 0 || ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton() != null; + } + return super.isTraversalKey(ke); +} + +protected int getTraversalKeyDetail(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_ENTER: + return SWT.TRAVERSE_RETURN; + } + return super.getTraversalKeyDetail(ke); +} + +protected boolean getTraversalKeyDefault(java.awt.event.KeyEvent ke) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_TAB: + case java.awt.event.KeyEvent.VK_ENTER: + int modifiers = ke.getModifiers(); + if((modifiers & java.awt.event.KeyEvent.CTRL_MASK) == 0 && (modifiers & java.awt.event.KeyEvent.SHIFT_MASK) == 0) { + return (style & SWT.MULTI) == 0; + } + default: + return super.getTraversalKeyDefault(ke); + } +} + +protected void validateTraversalKey(java.awt.event.KeyEvent ke, Event event) { + switch(ke.getKeyCode()) { + case java.awt.event.KeyEvent.VK_ENTER: + if(event.doit) { + if(!hooks(SWT.DefaultSelection)) { + if(event.detail == SWT.TRAVERSE_RETURN) { + JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton(); + if(defaultButton != null) { + defaultButton.requestFocus(); + defaultButton.doClick(); + } + } + } else { + sendEvent(SWT.DefaultSelection); + } + ke.consume(); + } else if((style & SWT.MULTI) == 0) { + ke.consume(); + } + break; + default: + super.validateTraversalKey(ke, event); + break; + } +} + +public void processEvent(DocumentEvent e) { + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + postEvent(SWT.Modify, new Event()); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java new file mode 100644 index 00000000000..599f90bbc26 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java @@ -0,0 +1,575 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.util.ArrayList; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.CToolBar; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class support the layout of selectable + * tool bar items. + *

    + * The item children that may be added to instances of this class + * must be of type ToolItem. + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to add Control children to it, + * or set a layout on it. + *

    + *

    + *
    Styles:
    + *
    FLAT, WRAP, RIGHT, HORIZONTAL, VERTICAL, SHADOW_OUT
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class ToolBar extends Composite { +// int lastFocusId; + ArrayList itemList = new ArrayList(); +// ToolItem [] items; +// boolean ignoreResize, ignoreMouse; +// ImageList imageList, disabledImageList, hotImageList; + +// static final int DEFAULT_WIDTH = 24; +// static final int DEFAULT_HEIGHT = 22; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#FLAT + * @see SWT#WRAP + * @see SWT#RIGHT + * @see SWT#HORIZONTAL + * @see SWT#SHADOW_OUT + * @see SWT#VERTICAL + * @see Widget#checkSubclass() + * @see Widget#getStyle() + */ +public ToolBar (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +ScrollBar createScrollBar (int type) { + return null; +} + +static int checkStyle (int style) { + /* + * A vertical tool bar cannot wrap. + */ + if ((style & SWT.VERTICAL) != 0) style &= ~SWT.WRAP; + return style; +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget (); + Point cSize = super.computeSize (wHint, hHint, changed); + if((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + isAdjustingSize = true; + } + }); + java.awt.Dimension size = handle.getSize(); + handle.setSize(wHint, Integer.MAX_VALUE); + handle.validate(); + Component[] components = handle.getComponents(); + int maxHeight = 0; + for(int i=0; i + *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ToolItem getItem (int index) { + checkWidget (); + int count = getItemCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return (ToolItem)itemList.get(index); +// return items [handle.getclpButton.idCommand]; +} + +/** + * Returns the item at the given point in the receiver + * or null if no such item exists. The point is in the + * coordinate system of the receiver. + * + * @param point the point used to locate the item + * @return the item at the given point + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ToolItem getItem (Point point) { + checkWidget (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + ToolItem [] items = getItems (); + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public int getItemCount () { + checkWidget (); + return itemList.size(); +} + +/** + * Returns an array of ToolItems which are the items + * in the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ToolItem [] getItems () { + checkWidget (); + return (ToolItem [])itemList.toArray(new ToolItem [0]); +// int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0); +// TBBUTTON lpButton = new TBBUTTON (); +// ToolItem [] result = new ToolItem [count]; +// for (int i=0; iWRAP style, the + * number of rows can be greater than one. Otherwise, + * the number of rows is always one. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getRowCount () { + checkWidget (); + Utils.notImplemented(); return 1; +// if ((style & SWT.VERTICAL) != 0) { +// return OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0); +// } +// return OS.SendMessage (handle, OS.TB_GETROWS, 0, 0); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the tool item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the tool item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (ToolItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + return itemList.indexOf(item); +// return OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, item.id, 0); +} + +//void layoutItems () { +//// if ((style & SWT.WRAP) != 0) { +//// OS.SendMessage(handle, OS.TB_AUTOSIZE, 0, 0); +//// } +// int count = itemList.size(); +// for (int i=0; i + *
    Styles:
    + *
    PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN
    + *
    Events:
    + *
    Selection
    + * + *

    + * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN + * may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class ToolItem extends Item { + ToolBar parent; + Control control; + Image disabledImage, hotImage; +// Image disabledImage2; +// int id; + Container handle; + +/** + * Constructs a new instance of this class given its parent + * (which must be a ToolBar) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#PUSH + * @see SWT#CHECK + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ToolItem (ToolBar parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a ToolBar), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#PUSH + * @see SWT#CHECK + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see SWT#DROP_DOWN + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ToolItem (ToolBar parent, int style, int index) { + super (parent, checkStyle (style)); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, index); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called when the mouse is over the arrow portion of a drop-down tool, + * the event object detail field contains the value SWT.ARROW. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +//void click (boolean dropDown) { +// int hwnd = parent.handle; +// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return; +// int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0); +// RECT rect = new RECT (); +// OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect); +// int hotIndex = OS.SendMessage (hwnd, OS.TB_GETHOTITEM, 0, 0); +// +// /* +// * In order to emulate all the processing that +// * happens when a mnemonic key is pressed, fake +// * a mouse press and release. This will ensure +// * that radio and pull down items are handled +// * properly. +// */ +// int y = rect.top + (rect.bottom - rect.top) / 2; +// int lParam = (dropDown ? rect.right - 1 : rect.left) | (y << 16); +// parent.ignoreMouse = true; +// OS.SendMessage (hwnd, OS.WM_LBUTTONDOWN, 0, lParam); +// OS.SendMessage (hwnd, OS.WM_LBUTTONUP, 0, lParam); +// parent.ignoreMouse = false; +// +// if (hotIndex != -1) { +// OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0); +// } +//} + +//Image createDisabledImage (Image image, Color color) { +// /* +// * In order to be consistent with the way that disabled +// * images appear in other places in the user interface, +// * use the SWT Graphics to create a disabled image instead +// * of calling DrawState(). +// */ +// return new Image (display, image, SWT.IMAGE_DISABLE); +// /* +// * This code is intentionally commented. +// */ +//// if (OS.IsWinCE) { +//// return new Image (display, image, SWT.IMAGE_DISABLE); +//// } +//// Rectangle rect = image.getBounds (); +//// Image disabled = new Image (display, rect); +//// GC gc = new GC (disabled); +//// gc.setBackground (color); +//// gc.fillRectangle (rect); +//// int hDC = gc.handle; +//// int hImage = image.handle; +//// int fuFlags = OS.DSS_DISABLED; +//// switch (image.type) { +//// case SWT.BITMAP: fuFlags |= OS.DST_BITMAP; break; +//// case SWT.ICON: fuFlags |= OS.DST_ICON; break; +//// } +//// OS.DrawState (hDC, 0, 0, hImage, 0, 0, 0, rect.width, rect.height, fuFlags); +//// gc.dispose (); +//// return disabled; +//} + +Container createHandle () { + return (Container)CToolItem.Factory.newInstance(this, style); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds () { + checkWidget(); + java.awt.Rectangle bounds = handle.getBounds(); + return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); +} + +/** + * Returns the control that is used to fill the bounds of + * the item when the item is a SEPARATOR. + * + * @return the control + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Control getControl () { + checkWidget(); + return control; +} + +/** + * Returns the receiver's disabled image if it has one, or null + * if it does not. + *

    + * The disabled image is displayed when the receiver is disabled. + *

    + * + * @return the receiver's disabled image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getDisabledImage () { + checkWidget(); + return disabledImage; +} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public boolean getEnabled () { + checkWidget(); + return handle.isEnabled(); +} + +/** + * Returns the receiver's hot image if it has one, or null + * if it does not. + *

    + * The hot image is displayed when the mouse enters the receiver. + *

    + * + * @return the receiver's hot image + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Image getHotImage () { + checkWidget(); + return hotImage; +} + +/** + * Returns the receiver's parent, which must be a ToolBar. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public ToolBar getParent () { + checkWidget(); + return parent; +} + +/** + * Returns true if the receiver is selected, + * and false otherwise. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked (which some platforms draw as a + * pushed in button). If the receiver is of any other type, this method + * returns false. + *

    + * + * @return the selection state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getSelection () { + checkWidget(); + if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false; + return ((CToolItem)handle).isSelected(); +} + +/** + * Returns the receiver's tool tip text, or null if it has not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getToolTipText () { + checkWidget(); + return toolTipText; +} + +/** + * Gets the width of the receiver. + * + * @return the width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getWidth () { + checkWidget(); + return handle.getWidth(); +// int hwnd = parent.handle; +// int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0); +// RECT rect = new RECT (); +// OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect); +// return rect.right - rect.left; +} + +/** + * Returns true if the receiver is enabled and all + * of the receiver's ancestors are enabled, and false + * otherwise. A disabled control is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public boolean isEnabled () { + checkWidget(); + return getEnabled () && parent.isEnabled (); +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +void releaseWidget () { + super.releaseWidget (); + control = null; + disabledImage = hotImage = null; +// if (disabledImage2 != null) disabledImage2.dispose (); +// disabledImage2 = null; +} + +//void releaseImages () { +// TBBUTTONINFO info = new TBBUTTONINFO (); +// info.cbSize = TBBUTTONINFO.sizeof; +// info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE; +// int hwnd = parent.handle; +// OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info); +// /* +// * Feature in Windows. For some reason, a tool item that has +// * the style BTNS_SEP does not return I_IMAGENONE when queried +// * for an image index, despite the fact that no attempt has been +// * made to assign an image to the item. As a result, operations +// * on an image list that use the wrong index cause random results. +// * The fix is to ensure that the tool item is not a separator +// * before using the image index. Since separators cannot have +// * an image and one is never assigned, this is not a problem. +// */ +// if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) { +// ImageList imageList = parent.getImageList (); +// ImageList hotImageList = parent.getHotImageList (); +// ImageList disabledImageList = parent.getDisabledImageList(); +// if (imageList != null) imageList.put (info.iImage, null); +// if (hotImageList != null) hotImageList.put (info.iImage, null); +// if (disabledImageList != null) disabledImageList.put (info.iImage, null); +// } +//} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +//void resizeControl () { +// if (control != null && !control.isDisposed ()) { +// /* +// * Set the size and location of the control +// * separately to minimize flashing in the +// * case where the control does not resize +// * to the size that was requested. This +// * case can occur when the control is a +// * combo box. +// */ +// Rectangle itemRect = getBounds (); +// control.setSize (itemRect.width, itemRect.height); +// Rectangle rect = control.getBounds (); +// rect.x = itemRect.x + (itemRect.width - rect.width) / 2; +// rect.y = itemRect.y + (itemRect.height - rect.height) / 2; +// control.setLocation (rect.x, rect.y); +//// } else { +//// handle.setSize(handle.getPreferredSize()); +//// parent.handle.invalidate(); +//// parent.handle.validate(); +//// parent.handle.repaint(); +// } +//} + +void selectRadio () { + int index = 0; + ToolItem [] items = parent.getItems (); + while (index < items.length && items [index] != this) index++; + int i = index - 1; + while (i >= 0 && items [i].setRadioSelection (false)) --i; + int j = index + 1; + while (j < items.length && items [j].setRadioSelection (false)) j++; + setSelection (true); +} + +/** + * Sets the control that is used to fill the bounds of + * the item when the item is a SEPARATOR. + * + * @param control the new control + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setControl (Control control) { + checkWidget(); + if (control != null) { + if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); + if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT); + } + if ((style & SWT.SEPARATOR) == 0) return; + if(this.control != null) { + handle.remove(this.control.handle); + } + this.control = control; + handle.add(control.handle); + handle.invalidate(); + handle.validate(); + handle.repaint(); +// handle.setPreferredSize(control.handle.getPreferredSize()); +// resizeControl (); +} + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. + *

    + * A disabled control is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + *

    + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (boolean enabled) { + checkWidget(); + handle.setEnabled(enabled); + // TODO: save the disabled image that is used +} + +/** + * Sets the receiver's disabled image to the argument, which may be + * null indicating that no disabled image should be displayed. + *

    + * The disbled image is displayed when the receiver is disabled. + *

    + * + * @param image the disabled image to display on the receiver (may be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setDisabledImage (Image image) { + checkWidget(); + if ((style & SWT.SEPARATOR) != 0) return; + if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + disabledImage = image; + ((CToolItem)handle).setDisabledIcon(image == null? null: new ImageIcon(image.handle)); +// updateImages (); +} + +/** + * Sets the receiver's hot image to the argument, which may be + * null indicating that no hot image should be displayed. + *

    + * The hot image is displayed when the mouse enters the receiver. + *

    + * + * @param image the hot image to display on the receiver (may be null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setHotImage (Image image) { + checkWidget(); + if ((style & SWT.SEPARATOR) != 0) return; + if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + hotImage = image; +// hotImage = Image.swing_new(getDisplay(), SWT.BITMAP, ); + ((CToolItem)handle).setRolloverIcon(image == null? null: new ImageIcon(image.handle)); +// updateImages (); +} + +public void setImage (Image image) { + checkWidget(); + if ((style & SWT.SEPARATOR) != 0) return; + if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + super.setImage (image); + ((CToolItem)handle).setIcon(image == null? null: new ImageIcon(image.handle)); +// updateImages (); +} + +boolean setRadioSelection (boolean value) { + if ((style & SWT.RADIO) == 0) return false; + if (getSelection () != value) { + setSelection (value); + if(!isAdjustingSelection) { + sendEvent (SWT.Selection); + } + } + return true; +} + +boolean isAdjustingSelection; + +/** + * Sets the selection state of the receiver. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked (which some platforms draw as a + * pushed in button). + *

    + * + * @param selected the new selection state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (boolean selected) { + checkWidget(); + if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return; + isAdjustingSelection = true; + ((CToolItem)handle).setSelected(selected); + isAdjustingSelection = false; +} + +/** + * Sets the receiver's text. The string may include + * the mnemonic character. + *

    + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, a selection + * event occurs. On most platforms, the mnemonic appears + * underlined but may be emphasised in a platform specific + * manner. The mnemonic indicator character '&' can be + * escaped by doubling it in the string, causing a single + * '&' to be displayed. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget(); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.SEPARATOR) != 0) return; + if (string.equals (text)) return; + super.setText (string); + CToolItem cToolItem = (CToolItem)handle; + int index = findMnemonicIndex(string); + char mnemonic; + if(index < 0) { + mnemonic = '\0'; + cToolItem.setText(string); + } else { + mnemonic = string.charAt(index); + cToolItem.setText(string.substring(0, index - 1) + string.substring(index)); + } + cToolItem.setMnemonic(mnemonic); +// parent.layoutItems (); +} + +String toolTipText; + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setToolTipText (String string) { + checkWidget(); + toolTipText = string; + ((CToolItem)handle).setToolTipText(Utils.convertStringToHTML(string)); +} + +/** + * Sets the width of the receiver, for SEPARATOR ToolItems. + * + * @param width the new width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setWidth (int width) { + checkWidget(); + if ((style & SWT.SEPARATOR) == 0) return; + if (width < 0) return; + ((CToolItem)handle).setWidth(width); + parent.handle.invalidate(); + parent.handle.validate(); + parent.handle.repaint(); +// parent.layoutItems (); +} + +//void updateImages () { +// int hwnd = parent.handle; +// TBBUTTONINFO info = new TBBUTTONINFO (); +// info.cbSize = TBBUTTONINFO.sizeof; +// info.dwMask = OS.TBIF_IMAGE; +// OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info); +// if (info.iImage == OS.I_IMAGENONE && image == null) return; +// ImageList imageList = parent.getImageList (); +// ImageList hotImageList = parent.getHotImageList (); +// ImageList disabledImageList = parent.getDisabledImageList(); +// if (info.iImage == OS.I_IMAGENONE) { +// Rectangle bounds = image.getBounds (); +// Point size = new Point (bounds.width, bounds.height); +// if (imageList == null) imageList = display.getToolImageList (size); +// info.iImage = imageList.add (image); +// parent.setImageList (imageList); +// if (disabledImageList == null) disabledImageList = display.getToolDisabledImageList (size); +// Image disabled = disabledImage; +// if (disabledImage == null) { +// if (disabledImage2 != null) disabledImage2.dispose (); +// disabledImage2 = null; +// disabled = image; +// if (!getEnabled ()) { +// Color color = parent.getBackground (); +// disabled = disabledImage2 = createDisabledImage (image, color); +// } +// } +// disabledImageList.add (disabled); +// parent.setDisabledImageList (disabledImageList); +//// if ((parent.style & SWT.FLAT) != 0) { +// if (hotImageList == null) hotImageList = display.getToolHotImageList (size); +// hotImageList.add (hotImage != null ? hotImage : image); +// parent.setHotImageList (hotImageList); +//// } +// } else { +// if (imageList != null) imageList.put (info.iImage, image); +// if (disabledImageList != null) { +// Image disabled = null; +// if (image != null) { +// if (disabledImage2 != null) disabledImage2.dispose (); +// disabledImage2 = null; +// disabled = disabledImage; +// if (disabledImage == null) { +// disabled = image; +// if (!getEnabled ()) { +// Color color = parent.getBackground (); +// disabled = disabledImage2 = createDisabledImage (image, color); +// } +// } +// } +// disabledImageList.put (info.iImage, disabled); +// } +// if (hotImageList != null) { +// Image hot = null; +// if (image != null) hot = hotImage != null ? hotImage : image; +// hotImageList.put (info.iImage, hot); +// } +// if (image == null) info.iImage = OS.I_IMAGENONE; +// } +// +// /* +// * Bug in Windows. If the width of an item has already been +// * calculated, the tool bar control will not recalculate it to +// * include the space for the image. The fix is to set the width +// * to zero, forcing the control recalculate the width for the item. +// */ +// info.dwMask |= OS.TBIF_SIZE; +// info.cx = 0; +// OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info); +// +// parent.layoutItems (); +//} + +//int widgetStyle () { +// if ((style & SWT.DROP_DOWN) != 0) return OS.BTNS_DROPDOWN; +// if ((style & SWT.PUSH) != 0) return OS.BTNS_BUTTON; +// if ((style & SWT.CHECK) != 0) return OS.BTNS_CHECK; +// /* +// * This code is intentionally commented. In order to +// * consistently support radio tool items across platforms, +// * the platform radio behavior is not used. +// */ +//// if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECKGROUP; +// if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECK; +// if ((style & SWT.SEPARATOR) != 0) return OS.BTNS_SEP; +// return OS.BTNS_BUTTON; +//} + +//LRESULT wmCommandChild (int wParam, int lParam) { +// if ((style & SWT.RADIO) != 0) { +// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) { +// selectRadio (); +// } +// } +// postEvent (SWT.Selection); +// return null; +//} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case java.awt.event.ActionEvent.ACTION_PERFORMED: if((style & SWT.RADIO) == 0 && (isAdjustingSelection || !hooks(SWT.Selection))) return; break; + case java.awt.event.ItemEvent.ITEM_STATE_CHANGED: if(isAdjustingSelection || !hooks(SWT.Selection)) return; break; + default: return; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + switch(id) { + case java.awt.event.ActionEvent.ACTION_PERFORMED: { + Event event = new Event(); + if((style & SWT.RADIO) != 0) { + if((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) { + selectRadio(); + } + } else if("Arrow".equals(((java.awt.event.ActionEvent)e).getActionCommand())) { + event.detail = SWT.ARROW; + } + if(!isAdjustingSelection) { + sendEvent(SWT.Selection, event); + } + break; + } + case java.awt.event.ItemEvent.ITEM_STATE_CHANGED: { + if(!isAdjustingSelection) { + sendEvent(SWT.Selection); + } + break; + } + } + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java new file mode 100644 index 00000000000..29ef02f5b40 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java @@ -0,0 +1,567 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.TrayIcon.MessageType; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.swing.Utils; +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; + +/** + * Instances of this class represent popup windows that are used + * to inform or warn the user. + *

    + *

    + *
    Styles:
    + *
    BALLOON, ICON_ERROR, ICON_INFORMATION, ICON_WARNING
    + *
    Events:
    + *
    Selection
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *

    + * + * @since 3.2 + */ + +public class ToolTip extends Widget { + Shell parent; + TrayItem item; + String text = ""; + String message = ""; + int x; + int y; + boolean autoHide = true, hasLocation, visible; + + /** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#ICON_ERROR + * @see SWT#ICON_INFORMATION + * @see SWT#ICON_WARNING + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public ToolTip (Shell parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + checkOrientation (parent); + Utils.notImplemented(); +// parent.createToolTip (this); +} + +static int checkStyle (int style) { + int mask = SWT.ICON_ERROR | SWT.ICON_INFORMATION | SWT.ICON_WARNING; + if ((style & mask) == 0) return style; + return checkBits (style, SWT.ICON_INFORMATION, SWT.ICON_WARNING, SWT.ICON_ERROR, 0, 0, 0); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's value changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +void destroyWidget () { + Utils.notImplemented(); +// if (parent != null) parent.destroyToolTip (this); + releaseHandle (); +} + +/** + * Returns true if the receiver is automatically + * hidden by the platform, and false otherwise. + * + * @return the receiver's auto hide state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + */ +public boolean getAutoHide () { + checkWidget(); + return autoHide; +} + +/** + * Returns the receiver's message, which will be an empty + * string if it has never been set. + * + * @return the receiver's message + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getMessage () { + checkWidget(); + return message; +} + +/** + * Returns the receiver's parent, which must be a Shell. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Shell getParent () { + checkWidget (); + return parent; +} + +/** + * Returns the receiver's text, which will be an empty + * string if it has never been set. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget(); + return text; +} + +/** + * Returns true if the receiver is visible, and + * false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget(); + Utils.notImplemented(); return false; +// if (OS.IsWinCE) return false; +// if (item != null) return visible; +// int hwndToolTip = hwndToolTip (); +// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) { +// TOOLINFO lpti = new TOOLINFO (); +// lpti.cbSize = TOOLINFO.sizeof; +// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) { +// return (lpti.uFlags & OS.TTF_IDISHWND) == 0 && lpti.uId == id; +// } +// } +// return false; +} + +//int hwndToolTip () { +// return (style & SWT.BALLOON) != 0 ? parent.balloonTipHandle () : parent.toolTipHandle (); +//} + +/** + * Returns true if the receiver is visible and all + * of the receiver's ancestors are visible and false + * otherwise. + * + * @return the receiver's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + */ +public boolean isVisible () { + checkWidget (); + if (item != null) return getVisible () && item.getVisible (); + return getVisible (); +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; + item = null; +} + +void releaseWidget () { + super.releaseWidget (); + if (item == null) { + if (autoHide) { + Utils.notImplemented(); +// int hwndToolTip = hwndToolTip (); +// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) { +// TOOLINFO lpti = new TOOLINFO (); +// lpti.cbSize = TOOLINFO.sizeof; +// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) { +// if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) { +// if (lpti.uId == id) OS.KillTimer (hwndToolTip, TIMER_ID); +// } +// } +// } + } + } + if (item != null && item.toolTip == this) { + item.toolTip = null; + } + item = null; + text = message = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's value changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Makes the receiver hide automatically when true, + * and remain visible when false. + * + * @param autoHide the auto hide state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getVisible + * @see #setVisible + */ +public void setAutoHide (boolean autoHide) { + checkWidget (); + this.autoHide = autoHide; + //TODO - update when visible +} + +/** + * Sets the location of the receiver, which must be a tooltip, + * to the point specified by the arguments which are relative + * to the display. + *

    + * Note that this is different from most widgets where the + * location of the widget is relative to the parent. + *

    + * + * @param x the new x coordinate for the receiver + * @param y the new y coordinate for the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (int x, int y) { + checkWidget (); + this.x = x; + this.y = y; + hasLocation = true; + //TODO - update when visible +} + +/** + * Sets the location of the receiver, which must be a tooltip, + * to the point specified by the argument which is relative + * to the display. + *

    + * Note that this is different from most widgets where the + * location of the widget is relative to the parent. + *

    + * Note that the platform window manager ultimately has control + * over the location of tooltips. + *

    + * + * @param location the new location for the receiver + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLocation (Point location) { + checkWidget (); + if (location == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + setLocation (location.x, location.y); +} + +/** + * Sets the receiver's message. + * + * @param string the new message + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMessage (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + message = string; + //TODO - update when visible +} + +/** + * Sets the receiver's text. + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + text = string; + //TODO - update when visible +} + +/** + * Marks the receiver as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget (); + if (visible == getVisible ()) return; + if(item == null) { + Utils.notImplemented(); + } else { + if(visible) { + MessageType messageType = null; + if((style & SWT.ICON_ERROR) != 0) { + messageType = MessageType.ERROR; + } else if((style & SWT.ICON_WARNING) != 0) { + messageType = MessageType.WARNING; + } else if((style & SWT.ICON_INFORMATION) != 0) { + messageType = MessageType.INFO; + } else { + messageType = MessageType.NONE; + } + item.trayIcon.displayMessage(text, message, messageType); + sendEvent (SWT.Show); + } else { + Utils.notImplemented(); + } + } +// if (OS.IsWinCE) return; +// if (visible == getVisible ()) return; +// if (item == null) { +// int hwnd = parent.handle; +// TOOLINFO lpti = new TOOLINFO (); +// lpti.cbSize = TOOLINFO.sizeof; +// lpti.uId = id; +// lpti.hwnd = hwnd; +// int hwndToolTip = hwndToolTip (); +// if (text.length () != 0) { +// int icon = OS.TTI_NONE; +// if ((style & SWT.ICON_INFORMATION) != 0) icon = OS.TTI_INFO; +// if ((style & SWT.ICON_WARNING) != 0) icon = OS.TTI_WARNING; +// if ((style & SWT.ICON_ERROR) != 0) icon = OS.TTI_ERROR; +// TCHAR pszTitle = new TCHAR (parent.getCodePage (), text, true); +// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle); +// } else { +// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0); +// } +// int maxWidth = 0; +// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) { +// RECT rect = new RECT (); +// OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, rect, 0); +// maxWidth = (rect.right - rect.left) / 4; +// } else { +// int hmonitor = OS.MonitorFromWindow (hwnd, OS.MONITOR_DEFAULTTONEAREST); +// MONITORINFO lpmi = new MONITORINFO (); +// lpmi.cbSize = MONITORINFO.sizeof; +// OS.GetMonitorInfo (hmonitor, lpmi); +// maxWidth = (lpmi.rcWork_right - lpmi.rcWork_left) / 4; +// } +// OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, maxWidth); +// if (visible) { +// int nX = x, nY = y; +// if (!hasLocation) { +// POINT pt = new POINT (); +// if (OS.GetCursorPos (pt)) { +// nX = pt.x; +// nY = pt.y; +// } +// } +// int lParam = nX | (nY << 16); +// OS.SendMessage (hwndToolTip, OS.TTM_TRACKPOSITION, 0, lParam); +// +// /* +// * Feature in Windows. Windows will not show a tool tip +// * if the cursor is outside the parent window (even on XP, +// * TTM_POPUP will not do this). The fix is to temporarily +// * move the cursor into the tool window, show the tool tip, +// * and then restore the cursor. +// */ +// POINT pt = new POINT (); +// OS.GetCursorPos (pt); +// RECT rect = new RECT (); +// OS.GetClientRect (hwnd, rect); +// OS.MapWindowPoints (hwnd, 0, rect, 2); +// if (!OS.PtInRect (rect, pt)) { +// int hCursor = OS.GetCursor (); +// OS.SetCursor (0); +// OS.SetCursorPos (rect.left, rect.top); +// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 1, lpti); +// OS.SetCursorPos (pt.x, pt.y); +// OS.SetCursor (hCursor); +// } else { +// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 1, lpti); +// } +// +// int time = OS.SendMessage (hwndToolTip, OS.TTM_GETDELAYTIME, OS.TTDT_AUTOPOP, 0); +// OS.SetTimer (hwndToolTip, TIMER_ID, time, 0); +// } else { +// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 0, lpti); +// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0); +// OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); +// OS.SendMessage (hwndToolTip, OS.TTM_POP, 0, 0); +// OS.KillTimer (hwndToolTip, TIMER_ID); +// } +// return; +// } +// if (item != null && OS.SHELL32_MAJOR >= 5) { +// if (visible) { +// NOTIFYICONDATA iconData = OS.IsUnicode ? (NOTIFYICONDATA) new NOTIFYICONDATAW () : new NOTIFYICONDATAA (); +// TCHAR buffer1 = new TCHAR (0, text, true); +// TCHAR buffer2 = new TCHAR (0, message, true); +// if (OS.IsUnicode) { +// char [] szInfoTitle = ((NOTIFYICONDATAW) iconData).szInfoTitle; +// int length1 = Math.min (szInfoTitle.length - 1, buffer1.length ()); +// System.arraycopy (buffer1.chars, 0, szInfoTitle, 0, length1); +// char [] szInfo = ((NOTIFYICONDATAW) iconData).szInfo; +// int length2 = Math.min (szInfo.length - 1, buffer2.length ()); +// System.arraycopy (buffer2.chars, 0, szInfo, 0, length2); +// } else { +// byte [] szInfoTitle = ((NOTIFYICONDATAA) iconData).szInfoTitle; +// int length = Math.min (szInfoTitle.length - 1, buffer1.length ()); +// System.arraycopy (buffer1.bytes, 0, szInfoTitle, 0, length); +// byte [] szInfo = ((NOTIFYICONDATAA) iconData).szInfo; +// int length2 = Math.min (szInfo.length - 1, buffer2.length ()); +// System.arraycopy (buffer2.bytes, 0, szInfo, 0, length2); +// } +// Display display = item.getDisplay (); +// iconData.cbSize = NOTIFYICONDATA.sizeof; +// iconData.uID = item.id; +// iconData.hWnd = display.hwndMessage; +// iconData.uFlags = OS.NIF_INFO; +// if ((style & SWT.ICON_INFORMATION) != 0) iconData.dwInfoFlags = OS.NIIF_INFO; +// if ((style & SWT.ICON_WARNING) != 0) iconData.dwInfoFlags = OS.NIIF_WARNING; +// if ((style & SWT.ICON_ERROR) != 0) iconData.dwInfoFlags = OS.NIIF_ERROR; +// sendEvent (SWT.Show); +// this.visible = OS.Shell_NotifyIcon (OS.NIM_MODIFY, iconData); +// } else { +// //TODO - hide the tray item +// } +// } +} +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java new file mode 100644 index 00000000000..5848a538fe4 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java @@ -0,0 +1,1236 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.Component; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; + +import javax.swing.SwingUtilities; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CControl; +import org.eclipse.swt.internal.swing.Compatibility; +import org.eclipse.swt.internal.swing.JTracker; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class implement rubber banding rectangles that are + * drawn onto a parent Composite or Display. + * These rectangles can be specified to respond to mouse and key events + * by either moving or resizing themselves accordingly. Trackers are + * typically used to represent window geometries in a lightweight manner. + * + *
    + *
    Styles:
    + *
    LEFT, RIGHT, UP, DOWN, RESIZE
    + *
    Events:
    + *
    Move, Resize
    + *
    + *

    + * Note: Rectangle move behavior is assumed unless RESIZE is specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class Tracker extends Widget { + + protected final class JTrackerExtension extends JTracker { + + protected final Window window; + + private JTrackerExtension(Component component, boolean isResizeType, Window window) { + super(component, isResizeType); + this.window = window; + } + + protected TrackerWindow createTrackerWindow(Window ownerWindow) { + return new TrackerWindow(ownerWindow) { + public java.awt.Cursor getCursor() { + return Utils.globalCursor != null? Utils.globalCursor: super.getCursor(); + } + }; + } + + protected Window createSharedOwnerWindow() { + return window != null? window: super.createSharedOwnerWindow(); + } + + protected void releaseSharedOwnerWindow(Window sharedOwnerWindow) { + if(window == null) { + super.releaseSharedOwnerWindow(sharedOwnerWindow); + } + } + + protected void processMouseEvent(MouseEvent me) { + if(!Compatibility.IS_JAVA_5_OR_GREATER) { + Utils.trackMouseProperties(me); + } + super.processMouseEvent(me); + if(Utils.capturedControl != null) { + Component target = ((CControl)Utils.capturedControl.handle).getClientArea(); + java.awt.Point point = SwingUtilities.convertPoint((Component)me.getSource(), me.getX(), me.getY(), target); + if(me.getID() == MouseEvent.MOUSE_WHEEL) { + MouseWheelEvent mwe = (MouseWheelEvent)me; + me = new MouseWheelEvent(target, mwe.getID(), mwe.getWhen(), mwe.getModifiers(), point.x, point.y, mwe.getClickCount(), mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation()); + } else { + me = new MouseEvent(target, me.getID(), me.getWhen(), me.getModifiers(), point.x, point.y, me.getClickCount(), me.isPopupTrigger()); + } + target.dispatchEvent(me); + } + } + + public void updateCursor() { + Window ownerWindow = getSharedOwnerWindow(); + if(ownerWindow == null) { + return; + } + Window w = new Window(ownerWindow) { + public boolean isFocusable() { + return false; + } + public java.awt.Cursor getCursor() { + return Utils.globalCursor != null? Utils.globalCursor: super.getCursor(); + } + }; + w.setFocusableWindowState(false); + Point mouseLocation; + if(Compatibility.IS_JAVA_5_OR_GREATER) { + mouseLocation = MouseInfo.getPointerInfo().getLocation(); + } else { + mouseLocation = getLastMouseLocation(); + } + if(mouseLocation != null) { + w.setBounds(mouseLocation.x, mouseLocation.y, 1, 1); + w.setVisible(true); + w.dispose(); + } + } + + public void hide() { + Utils.setGlobalCursor(null); + updateCursor(); + super.hide(); + } + + } + + Control parent; + JTrackerExtension handle; + boolean stippled; + Cursor cursor; +// boolean tracking, cancelled; +// Rectangle [] rectangles, proportions; +// Rectangle bounds; +// int resizeCursor, clientCursor, cursorOrientation = SWT.NONE; +// boolean inEvent = false; +// int oldProc, oldX, oldY; + +// /* +// * The following values mirror step sizes on Windows +// */ +// final static int STEPSIZE_SMALL = 1; +// final static int STEPSIZE_LARGE = 9; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#UP + * @see SWT#DOWN + * @see SWT#RESIZE + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Tracker (Composite parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + createWidget (); +} + +/** + * Constructs a new instance of this class given the display + * to create it on and a style value describing its behavior + * and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * Note: Currently, null can be passed in for the display argument. + * This has the effect of creating the tracker on the currently active + * display if there is one. If there is no current display, the + * tracker is created on a "default" display. Passing in null as + * the display argument is not considered to be good coding style, + * and may not be supported in a future release of SWT. + *

    + * + * @param display the display to create the tracker on + * @param style the style of control to construct + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#UP + * @see SWT#DOWN + */ +public Tracker (Display display, int style) { + if (display == null) display = Display.getCurrent (); + if (display == null) display = Display.getDefault (); + if (!display.isValidThread ()) { + error (SWT.ERROR_THREAD_INVALID_ACCESS); + } + this.style = checkStyle (style); + this.display = display; + createWidget (); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is moved or resized, by sending + * it one of the messages defined in the ControlListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #removeControlListener + */ +public void addControlListener (ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Resize, typedListener); + addListener (SWT.Move, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when keys are pressed and released on the system keyboard, by sending + * it one of the messages defined in the KeyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see KeyListener + * @see #removeKeyListener + */ +public void addKeyListener (KeyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.KeyUp,typedListener); + addListener (SWT.KeyDown,typedListener); +} + +//Point adjustMoveCursor () { +// int newX = bounds.x + bounds.width / 2; +// int newY = bounds.y; +// Utils.notImplemented(); return null; +//// POINT pt = new POINT (); +//// pt.x = newX; pt.y = newY; +//// /* +//// * Convert to screen coordinates iff needed +//// */ +//// if (parent != null) { +//// OS.ClientToScreen (parent.handle, pt); +//// } +//// OS.SetCursorPos (pt.x, pt.y); +//// return new Point (pt.x, pt.y); +//} + +//Point adjustResizeCursor () { +// int newX, newY; +// +// if ((cursorOrientation & SWT.LEFT) != 0) { +// newX = bounds.x; +// } else if ((cursorOrientation & SWT.RIGHT) != 0) { +// newX = bounds.x + bounds.width; +// } else { +// newX = bounds.x + bounds.width / 2; +// } +// +// if ((cursorOrientation & SWT.UP) != 0) { +// newY = bounds.y; +// } else if ((cursorOrientation & SWT.DOWN) != 0) { +// newY = bounds.y + bounds.height; +// } else { +// newY = bounds.y + bounds.height / 2; +// } +// +// Utils.notImplemented(); return null; +// POINT pt = new POINT (); +// pt.x = newX; pt.y = newY; +// /* +// * Convert to screen coordinates iff needed +// */ +// if (parent != null) { +// OS.ClientToScreen (parent.handle, pt); +// } +// OS.SetCursorPos (pt.x, pt.y); +// +// /* +// * If the client has not provided a custom cursor then determine +// * the appropriate resize cursor. +// */ +// if (clientCursor == 0) { +// int newCursor = 0; +// switch (cursorOrientation) { +// case SWT.UP: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENS); +// break; +// case SWT.DOWN: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENS); +// break; +// case SWT.LEFT: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE); +// break; +// case SWT.RIGHT: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE); +// break; +// case SWT.LEFT | SWT.UP: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE); +// break; +// case SWT.RIGHT | SWT.DOWN: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE); +// break; +// case SWT.LEFT | SWT.DOWN: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW); +// break; +// case SWT.RIGHT | SWT.UP: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW); +// break; +// default: +// newCursor = OS.LoadCursor (0, OS.IDC_SIZEALL); +// break; +// } +// OS.SetCursor (newCursor); +// if (resizeCursor != 0) { +// OS.DestroyCursor (resizeCursor); +// } +// resizeCursor = newCursor; +// } +// +// return new Point (pt.x, pt.y); +//} + +static int checkStyle (int style) { + if ((style & (SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN)) == 0) { + style |= SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN; + } + return style; +} + +/** + * Stops displaying the tracker rectangles. Note that this is not considered + * to be a cancelation by the user. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void close () { + checkWidget (); + handle.hide(); +// tracking = false; +} + +//Rectangle computeBounds () { +// int xMin = rectangles [0].x; +// int yMin = rectangles [0].y; +// int xMax = rectangles [0].x + rectangles [0].width; +// int yMax = rectangles [0].y + rectangles [0].height; +// +// for (int i = 1; i < rectangles.length; i++) { +// if (rectangles [i].x < xMin) xMin = rectangles [i].x; +// if (rectangles [i].y < yMin) yMin = rectangles [i].y; +// int rectRight = rectangles [i].x + rectangles [i].width; +// if (rectRight > xMax) xMax = rectRight; +// int rectBottom = rectangles [i].y + rectangles [i].height; +// if (rectBottom > yMax) yMax = rectBottom; +// } +// +// return new Rectangle (xMin, yMin, xMax - xMin, yMax - yMin); +//} + +//Rectangle [] computeProportions (Rectangle [] rects) { +// Rectangle [] result = new Rectangle [rects.length]; +// bounds = computeBounds (); +// for (int i = 0; i < rects.length; i++) { +// int x = 0, y = 0, width = 0, height = 0; +// if (bounds.width != 0) { +// x = (rects [i].x - bounds.x) * 100 / bounds.width; +// width = rects [i].width * 100 / bounds.width; +// } else { +// width = 100; +// } +// if (bounds.height != 0) { +// y = (rects [i].y - bounds.y) * 100 / bounds.height; +// height = rects [i].height * 100 / bounds.height; +// } else { +// height = 100; +// } +// result [i] = new Rectangle (x, y, width, height); +// } +// return result; +//} + +///** +// * Draw the rectangles displayed by the tracker. +// */ +//void drawRectangles (Rectangle [] rects, boolean stippled) { +// int bandWidth = 1; +// int hwndTrack = OS.GetDesktopWindow (); +// if (parent != null) hwndTrack = parent.handle; +// int hDC = OS.GetDCEx (hwndTrack, 0, OS.DCX_CACHE); +// int hBitmap = 0, hBrush = 0, oldBrush = 0; +// if (stippled) { +// bandWidth = 3; +// byte [] bits = {-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0}; +// hBitmap = OS.CreateBitmap (8, 8, 1, 1, bits); +// hBrush = OS.CreatePatternBrush (hBitmap); +// oldBrush = OS.SelectObject (hDC, hBrush); +// } +// for (int i=0; iDisplay then these are screen + * coordinates. + * + * @return the bounds of the Rectangles being drawn + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle [] getRectangles () { + checkWidget(); + java.awt.Rectangle[] rectangles = handle.getRectangles(); + int length = 0; + if (rectangles != null) length = rectangles.length; + Rectangle [] result = new Rectangle [length]; + for (int i = 0; i < length; i++) { + java.awt.Rectangle current = rectangles [i]; + result [i] = new Rectangle (current.x, current.y, current.width, current.height); + } + return result; +} + +/** + * Returns true if the rectangles are drawn with a stippled line, false otherwise. + * + * @return the stippled effect of the rectangles + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getStippled () { + checkWidget (); + return stippled; +} + +//void moveRectangles (int xChange, int yChange) { +// if (xChange < 0 && ((style & SWT.LEFT) == 0)) xChange = 0; +// if (xChange > 0 && ((style & SWT.RIGHT) == 0)) xChange = 0; +// if (yChange < 0 && ((style & SWT.UP) == 0)) yChange = 0; +// if (yChange > 0 && ((style & SWT.DOWN) == 0)) yChange = 0; +// if (xChange == 0 && yChange == 0) return; +// bounds.x += xChange; bounds.y += yChange; +// for (int i = 0; i < rectangles.length; i++) { +// rectangles [i].x += xChange; +// rectangles [i].y += yChange; +// } +//} + +/** + * Displays the Tracker rectangles for manipulation by the user. Returns when + * the user has either finished manipulating the rectangles or has cancelled the + * Tracker. + * + * @return true if the user did not cancel the Tracker, false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean open () { + checkWidget (); + if (!hasRectangles) return false; +// cancelled = false; +// tracking = true; + +// /* +// * If exactly one of UP/DOWN is specified as a style then set the cursor +// * orientation accordingly (the same is done for LEFT/RIGHT styles below). +// */ +// int vStyle = style & (SWT.UP | SWT.DOWN); +// if (vStyle == SWT.UP || vStyle == SWT.DOWN) { +// cursorOrientation |= vStyle; +// } +// int hStyle = style & (SWT.LEFT | SWT.RIGHT); +// if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) { +// cursorOrientation |= hStyle; +// } + Utils.setGlobalCursor(cursor == null? null: cursor.handle); + boolean isValid = handle.show(); + Utils.setGlobalCursor(null); + return isValid; +// /* +// * If this tracker is being created without a mouse drag then +// * we need to create a transparent window that fills the screen +// * in order to get all mouse/keyboard events that occur +// * outside of our visible windows (ie.- over the desktop). +// */ +// int hwndTransparent = 0; +// Callback newProc = null; +// boolean mouseDown = OS.GetKeyState(OS.VK_LBUTTON) < 0; +// if (!mouseDown) { +// int width = OS.GetSystemMetrics (OS.SM_CXSCREEN); +// int height = OS.GetSystemMetrics (OS.SM_CYSCREEN); +// hwndTransparent = OS.CreateWindowEx ( +// OS.WS_EX_TRANSPARENT, +// display.windowClass, +// null, +// OS.WS_POPUP | OS.WS_VISIBLE, +// 0, 0, +// width, height, +// 0, +// 0, +// OS.GetModuleHandle (null), +// null); +// oldProc = OS.GetWindowLong (hwndTransparent, OS.GWL_WNDPROC); +// newProc = new Callback (this, "transparentProc", 4); //$NON-NLS-1$ +// OS.SetWindowLong (hwndTransparent, OS.GWL_WNDPROC, newProc.getAddress ()); +// } +// +// update (); +// drawRectangles (rectangles, stippled); +// Point cursorPos; +// if (mouseDown) { +// POINT pt = new POINT (); +// OS.GetCursorPos (pt); +// cursorPos = new Point (pt.x, pt.y); +// } else { +// if ((style & SWT.RESIZE) != 0) { +// cursorPos = adjustResizeCursor (); +// } else { +// cursorPos = adjustMoveCursor (); +// } +// } +// oldX = cursorPos.x; +// oldY = cursorPos.y; +// +// /* Tracker behaves like a Dialog with its own OS event loop. */ +// MSG msg = new MSG (); +// while (tracking && !cancelled) { +// if (parent != null && parent.isDisposed ()) break; +// OS.GetMessage (msg, 0, 0, 0); +// OS.TranslateMessage (msg); +// switch (msg.message) { +// case OS.WM_LBUTTONUP: +// case OS.WM_MOUSEMOVE: +// wmMouse (msg.message, msg.wParam, msg.lParam); +// break; +// case OS.WM_IME_CHAR: wmIMEChar (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_CHAR: wmChar (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_KEYDOWN: wmKeyDown (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_KEYUP: wmKeyUp (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_SYSCHAR: wmSysChar (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_SYSKEYDOWN: wmSysKeyDown (msg.hwnd, msg.wParam, msg.lParam); break; +// case OS.WM_SYSKEYUP: wmSysKeyUp (msg.hwnd, msg.wParam, msg.lParam); break; +// } +// if (OS.WM_KEYFIRST <= msg.message && msg.message <= OS.WM_KEYLAST) continue; +// if (OS.WM_MOUSEFIRST <= msg.message && msg.message <= OS.WM_MOUSELAST) continue; +// if (msg.message == OS.WM_PAINT) { +// update (); +// drawRectangles (rectangles, stippled); +// } +// OS.DispatchMessage (msg); +// if (msg.message == OS.WM_PAINT) { +// drawRectangles (rectangles, stippled); +// } +// } +// if (mouseDown) OS.ReleaseCapture (); +// if (!isDisposed()) { +// update (); +// drawRectangles (rectangles, stippled); +// } +// /* +// * Cleanup: If a transparent window was created in order to capture events then +// * destroy it and its callback object now. +// */ +// if (hwndTransparent != 0) { +// OS.DestroyWindow (hwndTransparent); +// } +// if (newProc != null) { +// newProc.dispose (); +// oldProc = 0; +// } +// /* +// * Cleanup: If this tracker was resizing then the last cursor that it created +// * needs to be destroyed. +// */ +// if (resizeCursor != 0) { +// OS.DestroyCursor (resizeCursor); +// resizeCursor = 0; +// } +// tracking = false; +// return !cancelled; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is moved or resized. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #addControlListener + */ +public void removeControlListener (ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Resize, listener); + eventTable.unhook (SWT.Move, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when keys are pressed and released on the system keyboard. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see KeyListener + * @see #addKeyListener + */ +public void removeKeyListener(KeyListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.KeyUp, listener); + eventTable.unhook (SWT.KeyDown, listener); +} + +//void resizeRectangles (int xChange, int yChange) { +// /* +// * If the cursor orientation has not been set in the orientation of +// * this change then try to set it here. +// */ +// if (xChange < 0 && ((style & SWT.LEFT) != 0) && ((cursorOrientation & SWT.RIGHT) == 0)) { +// cursorOrientation |= SWT.LEFT; +// } +// if (xChange > 0 && ((style & SWT.RIGHT) != 0) && ((cursorOrientation & SWT.LEFT) == 0)) { +// cursorOrientation |= SWT.RIGHT; +// } +// if (yChange < 0 && ((style & SWT.UP) != 0) && ((cursorOrientation & SWT.DOWN) == 0)) { +// cursorOrientation |= SWT.UP; +// } +// if (yChange > 0 && ((style & SWT.DOWN) != 0) && ((cursorOrientation & SWT.UP) == 0)) { +// cursorOrientation |= SWT.DOWN; +// } +// +// /* +// * If the bounds will flip about the x or y axis then apply the adjustment +// * up to the axis (ie.- where bounds width/height becomes 0), change the +// * cursor's orientation accordingly, and flip each Rectangle's origin (only +// * necessary for > 1 Rectangles) +// */ +// if ((cursorOrientation & SWT.LEFT) != 0) { +// if (xChange > bounds.width) { +// if ((style & SWT.RIGHT) == 0) return; +// cursorOrientation |= SWT.RIGHT; +// cursorOrientation &= ~SWT.LEFT; +// bounds.x += bounds.width; +// xChange -= bounds.width; +// bounds.width = 0; +// if (proportions.length > 1) { +// for (int i = 0; i < proportions.length; i++) { +// Rectangle proportion = proportions [i]; +// proportion.x = 100 - proportion.x - proportion.width; +// } +// } +// } +// } else if ((cursorOrientation & SWT.RIGHT) != 0) { +// if (bounds.width < -xChange) { +// if ((style & SWT.LEFT) == 0) return; +// cursorOrientation |= SWT.LEFT; +// cursorOrientation &= ~SWT.RIGHT; +// xChange += bounds.width; +// bounds.width = 0; +// if (proportions.length > 1) { +// for (int i = 0; i < proportions.length; i++) { +// Rectangle proportion = proportions [i]; +// proportion.x = 100 - proportion.x - proportion.width; +// } +// } +// } +// } +// if ((cursorOrientation & SWT.UP) != 0) { +// if (yChange > bounds.height) { +// if ((style & SWT.DOWN) == 0) return; +// cursorOrientation |= SWT.DOWN; +// cursorOrientation &= ~SWT.UP; +// bounds.y += bounds.height; +// yChange -= bounds.height; +// bounds.height = 0; +// if (proportions.length > 1) { +// for (int i = 0; i < proportions.length; i++) { +// Rectangle proportion = proportions [i]; +// proportion.y = 100 - proportion.y - proportion.height; +// } +// } +// } +// } else if ((cursorOrientation & SWT.DOWN) != 0) { +// if (bounds.height < -yChange) { +// if ((style & SWT.UP) == 0) return; +// cursorOrientation |= SWT.UP; +// cursorOrientation &= ~SWT.DOWN; +// yChange += bounds.height; +// bounds.height = 0; +// if (proportions.length > 1) { +// for (int i = 0; i < proportions.length; i++) { +// Rectangle proportion = proportions [i]; +// proportion.y = 100 - proportion.y - proportion.height; +// } +// } +// } +// } +// +// // apply the bounds adjustment +// if ((cursorOrientation & SWT.LEFT) != 0) { +// bounds.x += xChange; +// bounds.width -= xChange; +// } else if ((cursorOrientation & SWT.RIGHT) != 0) { +// bounds.width += xChange; +// } +// if ((cursorOrientation & SWT.UP) != 0) { +// bounds.y += yChange; +// bounds.height -= yChange; +// } else if ((cursorOrientation & SWT.DOWN) != 0) { +// bounds.height += yChange; +// } +// +// Rectangle [] newRects = new Rectangle [rectangles.length]; +// for (int i = 0; i < rectangles.length; i++) { +// Rectangle proportion = proportions[i]; +// newRects[i] = new Rectangle ( +// proportion.x * bounds.width / 100 + bounds.x, +// proportion.y * bounds.height / 100 + bounds.y, +// proportion.width * bounds.width / 100, +// proportion.height * bounds.height / 100); +// } +// rectangles = newRects; +//} + +/** + * Sets the Cursor of the Tracker. If this cursor is null + * then the cursor reverts to the default. + * + * @param newCursor the new Cursor to display + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setCursor(Cursor newCursor) { + checkWidget(); + if(cursor == newCursor) { + return; + } + cursor = newCursor; + if(handle.isVisible()) { + Utils.setGlobalCursor(cursor == null? null: cursor.handle); + } + handle.updateCursor(); +} + +boolean hasRectangles; + +/** + * Specifies the rectangles that should be drawn, expressed relative to the parent + * widget. If the parent is a Display then these are screen coordinates. + * + * @param rectangles the bounds of the rectangles to be drawn + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the set of rectangles is null or contains a null rectangle
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setRectangles (Rectangle [] rectangles) { + checkWidget (); + if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT); +// int length = rectangles.length; +// this.rectangles = new Rectangle [length]; +// for (int i = 0; i < length; i++) { +// Rectangle current = rectangles [i]; +// if (current == null) error (SWT.ERROR_NULL_ARGUMENT); +// this.rectangles [i] = new Rectangle (current.x, current.y, current.width, current.height); +// } + java.awt.Rectangle[] recs = new java.awt.Rectangle[rectangles.length]; + for(int i=0; itrue if rectangle should appear stippled + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setStippled (boolean stippled) { + checkWidget (); + this.stippled = stippled; + handle.setAppearance(stippled? JTracker.THICK_BORDER_APPEARANCE: JTracker.SINGLE_LINE_APPEARANCE); +} + +//int transparentProc (int hwnd, int msg, int wParam, int lParam) { +// switch (msg) { +// /* +// * We typically do not want to answer that the transparent window is +// * transparent to hits since doing so negates the effect of having it +// * to grab events. However, clients of the tracker should not be aware +// * of this transparent window. Therefore if there is a hit query +// * performed as a result of client code then answer that the transparent +// * window is transparent to hits so that its existence will not impact +// * the client. +// */ +// case OS.WM_NCHITTEST: +// if (inEvent) return OS.HTTRANSPARENT; +// break; +// case OS.WM_SETCURSOR: +// if (clientCursor != 0) { +// OS.SetCursor (clientCursor); +// return 1; +// } +// if (resizeCursor != 0) { +// OS.SetCursor (resizeCursor); +// return 1; +// } +// } +// return OS.CallWindowProc (oldProc, hwnd, msg, wParam, lParam); +//} +// +//void update () { +// if (parent != null) { +// if (parent.isDisposed ()) return; +// Shell shell = parent.getShell (); +// shell.update (true); +// } else { +// display.update (); +// } +//} +// +//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) { +// LRESULT result = super.wmKeyDown (hwnd, wParam, lParam); +// if (result != null) return result; +// boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0; +// int stepSize = OS.GetKeyState (OS.VK_CONTROL) < 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE; +// int xChange = 0, yChange = 0; +// switch (wParam) { +// case OS.VK_ESCAPE: +// cancelled = true; +// tracking = false; +// break; +// case OS.VK_RETURN: +// tracking = false; +// break; +// case OS.VK_LEFT: +// xChange = isMirrored ? stepSize : -stepSize; +// break; +// case OS.VK_RIGHT: +// xChange = isMirrored ? -stepSize : stepSize; +// break; +// case OS.VK_UP: +// yChange = -stepSize; +// break; +// case OS.VK_DOWN: +// yChange = stepSize; +// break; +// } +// if (xChange != 0 || yChange != 0) { +// Rectangle [] oldRectangles = rectangles; +// boolean oldStippled = stippled; +// Rectangle [] rectsToErase = new Rectangle [rectangles.length]; +// for (int i = 0; i < rectangles.length; i++) { +// Rectangle current = rectangles [i]; +// rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height); +// } +// Event event = new Event (); +// event.x = oldX + xChange; +// event.y = oldY + yChange; +// Point cursorPos; +// if ((style & SWT.RESIZE) != 0) { +// resizeRectangles (xChange, yChange); +// inEvent = true; +// sendEvent (SWT.Resize, event); +// inEvent = false; +// /* +// * It is possible (but unlikely) that application +// * code could have disposed the widget in the resize +// * event. If this happens return false to indicate +// * that the tracking has failed. +// */ +// if (isDisposed ()) { +// cancelled = true; +// return LRESULT.ONE; +// } +// boolean draw = false; +// /* +// * It is possible that application code could have +// * changed the rectangles in the resize event. If this +// * happens then only redraw the tracker if the rectangle +// * values have changed. +// */ +// if (rectangles != oldRectangles) { +// int length = rectangles.length; +// if (length != rectsToErase.length) { +// draw = true; +// } else { +// for (int i = 0; i < length; i++) { +// if (!rectangles [i].equals (rectsToErase [i])) { +// draw = true; +// break; +// } +// } +// } +// } else { +// draw = true; +// } +// if (draw) { +// drawRectangles (rectsToErase, oldStippled); +// update (); +// drawRectangles (rectangles, stippled); +// } +// cursorPos = adjustResizeCursor (); +// } else { +// moveRectangles (xChange, yChange); +// inEvent = true; +// sendEvent (SWT.Move, event); +// inEvent = false; +// /* +// * It is possible (but unlikely) that application +// * code could have disposed the widget in the move +// * event. If this happens return false to indicate +// * that the tracking has failed. +// */ +// if (isDisposed ()) { +// cancelled = true; +// return LRESULT.ONE; +// } +// boolean draw = false; +// /* +// * It is possible that application code could have +// * changed the rectangles in the move event. If this +// * happens then only redraw the tracker if the rectangle +// * values have changed. +// */ +// if (rectangles != oldRectangles) { +// int length = rectangles.length; +// if (length != rectsToErase.length) { +// draw = true; +// } else { +// for (int i = 0; i < length; i++) { +// if (!rectangles [i].equals (rectsToErase [i])) { +// draw = true; +// break; +// } +// } +// } +// } else { +// draw = true; +// } +// if (draw) { +// drawRectangles (rectsToErase, oldStippled); +// update (); +// drawRectangles (rectangles, stippled); +// } +// cursorPos = adjustMoveCursor (); +// } +// oldX = cursorPos.x; +// oldY = cursorPos.y; +// } +// return result; +//} +// +//LRESULT wmSysKeyDown (int hwnd, int wParam, int lParam) { +// LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam); +// if (result != null) return result; +// cancelled = true; +// tracking = false; +// return result; +//} +// +//LRESULT wmMouse (int message, int wParam, int lParam) { +// boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0; +// int newPos = OS.GetMessagePos (); +// int newX = (short) (newPos & 0xFFFF); +// int newY = (short) (newPos >> 16); +// if (newX != oldX || newY != oldY) { +// Rectangle [] oldRectangles = rectangles; +// boolean oldStippled = stippled; +// Rectangle [] rectsToErase = new Rectangle [rectangles.length]; +// for (int i = 0; i < rectangles.length; i++) { +// Rectangle current = rectangles [i]; +// rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height); +// } +// Event event = new Event (); +// event.x = newX; +// event.y = newY; +// if ((style & SWT.RESIZE) != 0) { +// if (isMirrored) { +// resizeRectangles (oldX - newX, newY - oldY); +// } else { +// resizeRectangles (newX - oldX, newY - oldY); +// } +// inEvent = true; +// sendEvent (SWT.Resize, event); +// inEvent = false; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the resize +// * event. If this happens, return false to indicate +// * that the tracking has failed. +// */ +// if (isDisposed ()) { +// cancelled = true; +// return LRESULT.ONE; +// } +// boolean draw = false; +// /* +// * It is possible that application code could have +// * changed the rectangles in the resize event. If this +// * happens then only redraw the tracker if the rectangle +// * values have changed. +// */ +// if (rectangles != oldRectangles) { +// int length = rectangles.length; +// if (length != rectsToErase.length) { +// draw = true; +// } else { +// for (int i = 0; i < length; i++) { +// if (!rectangles [i].equals (rectsToErase [i])) { +// draw = true; +// break; +// } +// } +// } +// } +// else { +// draw = true; +// } +// if (draw) { +// drawRectangles (rectsToErase, oldStippled); +// update (); +// drawRectangles (rectangles, stippled); +// } +// Point cursorPos = adjustResizeCursor (); +// newX = cursorPos.x; newY = cursorPos.y; +// } else { +// if (isMirrored) { +// moveRectangles (oldX - newX, newY - oldY); +// } else { +// moveRectangles (newX - oldX, newY - oldY); +// } +// inEvent = true; +// sendEvent (SWT.Move, event); +// inEvent = false; +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the move +// * event. If this happens, return false to indicate +// * that the tracking has failed. +// */ +// if (isDisposed ()) { +// cancelled = true; +// return LRESULT.ONE; +// } +// boolean draw = false; +// /* +// * It is possible that application code could have +// * changed the rectangles in the move event. If this +// * happens then only redraw the tracker if the rectangle +// * values have changed. +// */ +// if (rectangles != oldRectangles) { +// int length = rectangles.length; +// if (length != rectsToErase.length) { +// draw = true; +// } else { +// for (int i = 0; i < length; i++) { +// if (!rectangles [i].equals (rectsToErase [i])) { +// draw = true; +// break; +// } +// } +// } +// } else { +// draw = true; +// } +// if (draw) { +// drawRectangles (rectsToErase, oldStippled); +// update (); +// drawRectangles (rectangles, stippled); +// } +// } +// oldX = newX; +// oldY = newY; +// } +// tracking = message != OS.WM_LBUTTONUP; +// return null; +//} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java new file mode 100644 index 00000000000..79775400985 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java @@ -0,0 +1,471 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.*; + +/** + * Instances of this class represent icons that can be placed on the + * system tray or task bar status area. + *

    + *

    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    DefaultSelection, MenuDetect, Selection
    + *
    + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @since 3.0 + */ +public class TrayItem extends Item { + Tray parent; + ToolTip toolTip; + boolean visible = true; + TrayIcon trayIcon; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tray) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TrayItem (Tray parent, int style) { + super (parent, style); + this.parent = parent; + parent.createItem (this, parent.getItemCount ()); + createWidget(); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the receiver is selected + * widgetDefaultSelected is called when the receiver is double-clicked + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +@Override +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +void createWidget () { + trayIcon = new TrayIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)); +// trayIcon.setImageAutoSize(true); + trayIcon.addMouseListener(new MouseAdapter() { + protected boolean processMenuEvent(MouseEvent e) { + switch(e.getClickCount()) { + case 1: + if(e.isPopupTrigger()) { + if (hooks (SWT.MenuDetect)) { + UIThreadUtils.startExclusiveSection(display); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return true; + } + sendEvent (SWT.MenuDetect); + UIThreadUtils.stopExclusiveSection(); + return true; + } + } + } + return false; + } + @Override + public void mousePressed(MouseEvent e) { + if(processMenuEvent(e)) return; + } + @Override + public void mouseReleased(MouseEvent e) { + if(processMenuEvent(e)) return; + // We can't use action listener because it does not make a difference between single click and double click... + switch(e.getClickCount()) { + case 1: + if (hooks (SWT.Selection)) { + UIThreadUtils.startExclusiveSection(display); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + postEvent (SWT.Selection); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } + } + break; + case 2: + if (hooks (SWT.DefaultSelection)) { + UIThreadUtils.startExclusiveSection(display); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + postEvent (SWT.DefaultSelection); + UIThreadUtils.stopExclusiveSection(); + } + break; + } + } + }); + try { + SystemTray.getSystemTray().add(trayIcon); + } catch(Exception e) { + e.printStackTrace(); + } +} + +@Override +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns the receiver's parent, which must be a Tray. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public Tray getParent () { + checkWidget (); + return parent; +} + +/** + * Returns the receiver's tool tip, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public ToolTip getToolTip () { + checkWidget (); + return toolTip; +} + +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getToolTipText () { + checkWidget (); + return trayIcon.getToolTip(); +} + +/** + * Returns true if the receiver is visible and + * false otherwise. + * + * @return the receiver's visibility + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getVisible () { + checkWidget (); + return visible; +} + +//int messageProc (int hwnd, int msg, int wParam, int lParam) { +// /* +// * Feature in Windows. When the user clicks on the tray +// * icon, another application may be the foreground window. +// * This means that the event loop is not running and can +// * cause problems. For example, if a menu is shown, when +// * the user clicks outside of the menu to cancel it, the +// * menu is not hidden until an event is processed. If +// * another application is the foreground window, then the +// * menu is not hidden. The fix is to force the tray icon +// * message window to the foreground when sending an event. +// */ +// switch (lParam) { +// case OS.WM_LBUTTONDOWN: +// if (hooks (SWT.Selection)) { +// OS.SetForegroundWindow (hwnd); +// postEvent (SWT.Selection); +// } +// break; +// case OS.WM_LBUTTONDBLCLK: +// case OS.WM_RBUTTONDBLCLK: +// if (hooks (SWT.DefaultSelection)) { +// OS.SetForegroundWindow (hwnd); +// postEvent (SWT.DefaultSelection); +// } +// break; +// case OS.WM_RBUTTONUP: { +// if (hooks (SWT.MenuDetect)) { +// OS.SetForegroundWindow (hwnd); +// sendEvent (SWT.MenuDetect); +// // widget could be disposed at this point +// if (isDisposed()) return 0; +// } +// break; +// } +// case OS.NIN_BALLOONSHOW: +// if (toolTip != null && !toolTip.visible) { +// toolTip.visible = true; +// if (toolTip.hooks (SWT.Show)) { +// OS.SetForegroundWindow (hwnd); +// toolTip.sendEvent (SWT.Show); +// // widget could be disposed at this point +// if (isDisposed()) return 0; +// } +// } +// break; +// case OS.NIN_BALLOONHIDE: +// case OS.NIN_BALLOONTIMEOUT: +// case OS.NIN_BALLOONUSERCLICK: +// if (toolTip != null) { +// if (toolTip.visible) { +// toolTip.visible = false; +// if (toolTip.hooks (SWT.Hide)) { +// OS.SetForegroundWindow (hwnd); +// toolTip.sendEvent (SWT.Hide); +// // widget could be disposed at this point +// if (isDisposed()) return 0; +// } +// } +// if (lParam == OS.NIN_BALLOONUSERCLICK) { +// if (toolTip.hooks (SWT.Selection)) { +// OS.SetForegroundWindow (hwnd); +// toolTip.postEvent (SWT.Selection); +// // widget could be disposed at this point +// if (isDisposed()) return 0; +// } +// } +// } +// break; +// } +// display.wakeThread (); +// return 0; +//} +// +//void recreate () { +// createWidget (); +// if (!visible) setVisible (false); +// if (text.length () != 0) setText (text); +// if (image != null) setImage (image); +// if (toolTipText != null) setToolTipText (toolTipText); +//} + +@Override +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +@Override +void releaseWidget () { + super.releaseWidget (); + if (toolTip != null) toolTip.item = null; + toolTip = null; + if(visible) { + SystemTray.getSystemTray().remove(trayIcon); + } + // TODO: send hide event? +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Sets the receiver's image. + * + * @param image the new image + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the image has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +@Override +public void setImage (Image image) { + checkWidget (); + if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + super.setImage (image); + trayIcon.setImage(image.handle); +} + +/** + * Sets the receiver's tool tip to the argument, which + * may be null indicating that no tool tip should be shown. + * + * @param toolTip the new tool tip (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setToolTip (ToolTip toolTip) { + checkWidget (); + ToolTip oldTip = this.toolTip, newTip = toolTip; + if (oldTip != null) oldTip.item = null; + this.toolTip = newTip; + if (newTip != null) newTip.item = this; +} + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param value the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setToolTipText (String value) { + checkWidget (); + trayIcon.setToolTip(value); +} + +/** + * Makes the receiver visible if the argument is true, + * and makes it invisible otherwise. + * + * @param visible the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setVisible (boolean visible) { + checkWidget (); + if(this.visible == visible) return; + this.visible = visible; + if(visible) { + try { + SystemTray.getSystemTray().add(trayIcon); + sendEvent (SWT.Show); + } catch(Exception e) { + e.printStackTrace(); + } + } else { + SystemTray.getSystemTray().remove(trayIcon); + sendEvent (SWT.Hide); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java new file mode 100644 index 00000000000..c9b0c05aff2 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java @@ -0,0 +1,3697 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.awt.Container; +import java.awt.event.ItemEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.EventObject; + +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreePath; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.TreeListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.swing.CTree; +import org.eclipse.swt.internal.swing.CTreeItem; +import org.eclipse.swt.internal.swing.DefaultMutableTreeTableNode; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.Utils; +import org.eclipse.swt.internal.swing.CTree.CellPaintEvent; + +/** + * Instances of this class provide a selectable user interface object + * that displays a hierarchy of items and issues notification when an + * item in the hierarchy is selected. + *

    + * The item children that may be added to instances of this class + * must be of type TreeItem. + *

    + * Style VIRTUAL is used to create a Tree whose + * TreeItems are to be populated by the client on an on-demand basis + * instead of up-front. This can provide significant performance improvements for + * trees that are very large or for which TreeItem population is + * expensive (for example, retrieving values from an external source). + *

    + * Here is an example of using a Tree with style VIRTUAL: + *

    + *  final Tree tree = new Tree(parent, SWT.VIRTUAL | SWT.BORDER);
    + *  tree.setItemCount(20);
    + *  tree.addListener(SWT.SetData, new Listener() {
    + *      public void handleEvent(Event event) {
    + *          TreeItem item = (TreeItem)event.item;
    + *          TreeItem parentItem = item.getParentItem();
    + *          String text = null;
    + *          if (parentItem == null) {
    + *              text = "node " + tree.indexOf(item);
    + *          } else {
    + *              text = parentItem.getText() + " - " + parentItem.indexOf(item);
    + *          }
    + *          item.setText(text);
    + *          System.out.println(text);
    + *          item.setItemCount(10);
    + *      }
    + *  });
    + * 
    + *

    + * Note that although this class is a subclass of Composite, + * it does not make sense to add Control children to it, + * or set a layout on it. + *

    + *

    + *
    Styles:
    + *
    SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL
    + *
    Events:
    + *
    Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem
    + *
    + *

    + * Note: Only one of the styles SINGLE and MULTI may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class Tree extends Composite { + ArrayList itemList; + ArrayList columnList; + TreeItem currentItem; +// TreeColumn [] columns; +// int hwndParent, hwndHeader, hAnchor; +// ImageList imageList; +// boolean dragStarted, gestureCompleted; +// boolean ignoreSelect, ignoreExpand, ignoreDeselect, ignoreResize; +// boolean lockSelection, oldSelected, newSelected; +// boolean linesVisible, customDraw, printClient; +// static final int INSET = 3; + static final int GRID_WIDTH = 1; +// static final int HEADER_MARGIN = 10; +// static final char [] BUTTON = new char [] {'B', 'U', 'T', 'T', 'O', 'N', 0}; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#SINGLE + * @see SWT#MULTI + * @see SWT#CHECK + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public Tree (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +static int checkStyle (int style) { +// /* +// * Feature in Windows. It is not possible to create +// * a tree that scrolls and does not have scroll bars. +// * The TVS_NOSCROLL style will remove the scroll bars +// * but the tree will never scroll. Therefore, no matter +// * what style bits are specified, set the H_SCROLL and +// * V_SCROLL bits so that the SWT style will match the +// * widget that Windows creates. +// */ + style |= SWT.H_SCROLL | SWT.V_SCROLL; + return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0); +} + +void adjustColumnWidth() { + // Could be more efficient. Should post, with coalescing? + if(getColumnCount() == 0) { + CTree cTree = (CTree)handle; + cTree.getColumnModel().getColumn(0).setPreferredWidth(cTree.getPreferredColumnWidth(0)); + } +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's selection changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the item field of the event object is valid. + * If the receiver has SWT.CHECK style set and the check selection changes, + * the event object detail field contains the value SWT.CHECK. + * widgetDefaultSelected is typically called when an item is double-clicked. + * The item field of the event object is valid for default selection, but the detail field is not used. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection, typedListener); + addListener (SWT.DefaultSelection, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when an item in the receiver is expanded or collapsed + * by sending it one of the messages defined in the TreeListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see TreeListener + * @see #removeTreeListener + */ +public void addTreeListener(TreeListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Expand, typedListener); + addListener (SWT.Collapse, typedListener); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +boolean checkData (TreeItem item, boolean redraw) { + if ((style & SWT.VIRTUAL) == 0) return true; + TreeItem parentItem = item.getParentItem (); + return checkData (item, parentItem == null ? indexOf (item) : parentItem.indexOf (item), redraw); +} + +boolean checkData (TreeItem item, int index, boolean redraw) { + if ((style & SWT.VIRTUAL) == 0) return true; + if (!item.cached) { + item.cached = true; + Event event = new Event (); + event.item = item; + event.index = index; + TreeItem oldItem = currentItem; + currentItem = item; + sendEvent (SWT.SetData, event); + //widget could be disposed at this point + currentItem = oldItem; + if (isDisposed () || item.isDisposed ()) return false; +// if (redraw) item.redraw (); + } + return true; +} + +/** + * Clears the item at the given zero-relative index in the receiver. + * The text, icon and other attributes of the item are set to the default + * value. If the tree was created with the SWT.VIRTUAL style, + * these attributes are requested again as needed. + * + * @param index the index of the item to clear + * @param all true if all child items of the indexed item should be + * cleared recursively, and false otherwise + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.2 + */ +public void clear (int index, boolean all) { + checkWidget (); + getItem(index).clearAll(all); +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); +// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE); +// hItem = findItem (hItem, index); +// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE); +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; +// clear (hItem, tvItem); +// if (all) { +// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem); +// clearAll (hItem, tvItem, all); +// } +} + +/** + * Clears all the items in the receiver. The text, icon and other + * attributes of the items are set to their default values. If the + * tree was created with the SWT.VIRTUAL style, these + * attributes are requested again as needed. + * + * @param all true if all child items should be cleared + * recursively, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.2 + */ +public void clearAll (boolean all) { + checkWidget (); + for(int i=getItemCount()-1; i>=0; i--) { + getItem(i).clearAll(all); + } +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); +// if (hItem == 0) return; +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; +// clearAll (hItem, tvItem, all); +} + +public Rectangle computeTrim(int x, int y, int width, int height) { + CTree cTree = (CTree)handle; + width += cTree.getVerticalScrollBar().getPreferredSize().width; + height += cTree.getHorizontalScrollBar().getPreferredSize().height; + return super.computeTrim(x, y, width, height); +} + +void createHandleInit() { + super.createHandleInit(); + state &= ~(CANVAS | THEME_BACKGROUND); +} + +protected Container createHandle () { + return (Container)CTree.Factory.newInstance(this, style); +} + +//void createHandle () { +// super.createHandle (); +// state &= ~CANVAS; +// +// /* +// * Feature in Windows. In version 5.8 of COMCTL32.DLL, +// * if the font is changed for an item, the bounds for the +// * item are not updated, causing the text to be clipped. +// * The fix is to detect the version of COMCTL32.DLL, and +// * if it is one of the versions with the problem, then +// * use version 5.00 of the control (a version that does +// * not have the problem). This is the recomended work +// * around from the MSDN. +// */ +// if (!OS.IsWinCE) { +// if (OS.COMCTL32_MAJOR < 6) { +// OS.SendMessage (handle, OS.CCM_SETVERSION, 5, 0); +// } +// } +// +// /* Set the checkbox image list */ +// if ((style & SWT.CHECK) != 0) setCheckboxImageList (); +// +// /* +// * Feature in Windows. When the control is created, +// * it does not use the default system font. A new HFONT +// * is created and destroyed when the control is destroyed. +// * This means that a program that queries the font from +// * this control, uses the font in another control and then +// * destroys this control will have the font unexpectedly +// * destroyed in the other control. The fix is to assign +// * the font ourselves each time the control is created. +// * The control will not destroy a font that it did not +// * create. +// */ +// int hFont = OS.GetStockObject (OS.SYSTEM_FONT); +// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0); +//} + +void createItem (TreeColumn column, int index) { +// int columnCount = getColumnCount(); + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void deselectAll () { + checkWidget (); + ((CTree)handle).clearSelection(); +} + +void destroyItem (TreeColumn column) { + int index = columnList.indexOf(column); + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 3.1 + */ +public int getGridLineWidth () { + checkWidget (); + return GRID_WIDTH; +} + +/** + * Returns the height of the receiver's header + * + * @return the height of the header or zero if the header is not visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public int getHeaderHeight () { + checkWidget (); + JTableHeader tableHeader = ((CTree)handle).getTableHeader(); + return tableHeader.isVisible()? tableHeader.getHeight(): 0; +} + +/** + * Returns true if the receiver's header is visible, + * and false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the receiver's header's visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public boolean getHeaderVisible () { + checkWidget (); + return ((CTree)handle).getTableHeader().isVisible(); +} + +//Point getImageSize () { +// if (imageList != null) return imageList.getImageSize (); +// return new Point (0, getItemHeight ()); +//} + +/** + * Returns the column at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * Columns are returned in the order that they were created. + * If no TreeColumns were created by the programmer, + * this method will throw ERROR_INVALID_RANGE despite + * the fact that a single column of data may be visible in the tree. + * This occurs when the programmer uses the tree like a list, adding + * items but never creating a column. + * + * @param index the index of the column to return + * @return the column at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#getColumnOrder() + * @see Tree#setColumnOrder(int[]) + * @see TreeColumn#getMoveable() + * @see TreeColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.1 + */ +public TreeColumn getColumn (int index) { + checkWidget (); + if (columnList == null) error (SWT.ERROR_INVALID_RANGE); + int count = getColumnCount(); + if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); + return (TreeColumn)columnList.get(index); +} + +/** + * Returns the number of columns contained in the receiver. + * If no TreeColumns were created by the programmer, + * this value is zero, despite the fact that visually, one column + * of items may be visible. This occurs when the programmer uses + * the tree like a list, adding items but never creating a column. + * + * @return the number of columns + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public int getColumnCount () { + checkWidget (); + if (columnList == null) return 0; + return columnList.size(); +} + +/** + * Returns an array of zero-relative integers that map + * the creation order of the receiver's items to the + * order in which they are currently being displayed. + *

    + * Specifically, the indices of the returned array represent + * the current visual order of the items, and the contents + * of the array represent the creation order of the items. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the current visual order of the receiver's items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#setColumnOrder(int[]) + * @see TreeColumn#getMoveable() + * @see TreeColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.2 + */ +public int[] getColumnOrder () { + checkWidget (); + return ((CTree)handle).getColumnOrder(); +// if (hwndHeader == 0) return new int [0]; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// int [] order = new int [count]; +// OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order); +// return order; +} + +/** + * Returns an array of TreeColumns which are the + * columns in the receiver. Columns are returned in the order + * that they were created. If no TreeColumns were + * created by the programmer, the array is empty, despite the fact + * that visually, one column of items may be visible. This occurs + * when the programmer uses the tree like a list, adding items but + * never creating a column. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#getColumnOrder() + * @see Tree#setColumnOrder(int[]) + * @see TreeColumn#getMoveable() + * @see TreeColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.1 + */ +public TreeColumn [] getColumns () { + checkWidget (); + if (columnList == null) return new TreeColumn [0]; + return (TreeColumn[])columnList.toArray(new TreeColumn[0]); +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public TreeItem getItem (int index) { + checkWidget (); + if (index < 0) error (SWT.ERROR_INVALID_RANGE); + if (index >= itemList.size()) error (SWT.ERROR_INVALID_RANGE); + return (TreeItem)itemList.get(index); +} + +/** + * Returns the item at the given point in the receiver + * or null if no such item exists. The point is in the + * coordinate system of the receiver. + *

    + * The item that is returned represents an item that could be selected by the user. + * For example, if selection only occurs in items in the first column, then null is + * returned if the point is outside of the item. + * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy, + * determines the extent of the selection. + *

    + * + * @param point the point used to locate the item + * @return the item at the given point, or null if the point is not in a selectable item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem getItem (Point point) { + checkWidget (); + if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + TreePath treePath = ((CTree)handle).getPathForLocation(point.x, point.y); + if(treePath == null) { + return null; + } + CTreeItem.TreeItemObject treeItemObject = ((CTreeItem.TreeItemObject)((DefaultMutableTreeNode)treePath.getLastPathComponent()).getUserObject()); + return treeItemObject.getTreeItem().getTreeItem(); +} + +/** + * Returns the number of items contained in the receiver + * that are direct item children of the receiver. The + * number that is returned is the number of roots in the + * tree. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return itemList == null? 0: itemList.size(); +} + +//int getItemCount (int hItem) { +// int count = 0; +// while (hItem != 0) { +// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); +// count++; +// } +// return count; +//} + +/** + * Returns the height of the area which would be used to + * display one of the items in the tree. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemHeight () { + checkWidget (); + return ((CTree)handle).getRowHeight(); +} + +/** + * Returns a (possibly empty) array of items contained in the + * receiver that are direct item children of the receiver. These + * are the roots of the tree. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem [] getItems () { + checkWidget (); + return (TreeItem[])itemList.toArray(new TreeItem[0]); +} + +//TreeItem [] getItems (int hTreeItem) { +// int count = 0, hItem = hTreeItem; +// while (hItem != 0) { +// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); +// count++; +// } +// int index = 0; +// TreeItem [] result = new TreeItem [count]; +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; +// tvItem.hItem = hTreeItem; +// /* +// * Feature in Windows. In some cases an expand or collapse message +// * can occurs from within TVM_DELETEITEM. When this happens, the item +// * being destroyed has been removed from the list of items but has not +// * been deleted from the tree. The fix is to check for null items and +// * remove them from the list. +// */ +// while (tvItem.hItem != 0) { +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// TreeItem item = items [tvItem.lParam]; +// if (item != null) result [index++] = item; +// tvItem.hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, tvItem.hItem); +// } +// if (index != count) { +// TreeItem [] newResult = new TreeItem [index]; +// System.arraycopy (result, 0, newResult, 0, index); +// result = newResult; +// } +// return result; +//} + +/** + * Returns true if the receiver's lines are visible, + * and false otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + *

    + * + * @return the visibility state of the lines + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public boolean getLinesVisible () { + checkWidget (); + return ((CTree)handle).isGridVisible(); +} + +/** + * Returns the receiver's parent item, which must be a + * TreeItem or null when the receiver is a + * root. + * + * @return the receiver's parent item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem getParentItem () { + checkWidget (); + return null; +} + +/** + * Returns an array of TreeItems that are currently + * selected in the receiver. The order of the items is unspecified. + * An empty array indicates that no items are selected. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + *

    + * @return an array representing the selection + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem [] getSelection () { + checkWidget (); + TreePath[] paths = ((CTree)handle).getSelectionModel().getSelectionPaths(); + if(paths == null || paths.length == 0) return new TreeItem[0]; + TreeItem[] items = new TreeItem[paths.length]; + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public int getSelectionCount () { + checkWidget (); + return ((CTree)handle).getSelectionModel().getSelectionCount(); +} + +TreeColumn sortColumn; +int sortDirection; + +/** + * Returns the column which shows the sort indicator for + * the receiver. The value may be null if no column shows + * the sort indicator. + * + * @return the sort indicator + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setSortColumn(TreeColumn) + * + * @since 3.2 + */ +public TreeColumn getSortColumn () { + checkWidget (); + return sortColumn; +} + +/** + * Returns the direction of the sort indicator for the receiver. + * The value will be one of UP, DOWN + * or NONE. + * + * @return the sort direction + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setSortDirection(int) + * + * @since 3.2 + */ +public int getSortDirection () { + checkWidget (); + return sortDirection; +} + +/** + * Returns the item which is currently at the top of the receiver. + * This item can change when items are expanded, collapsed, scrolled + * or new items are added or removed. + * + * @return the item at the top of the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.1 + */ +public TreeItem getTopItem () { + checkWidget (); + int index = ((CTree)handle).getTopIndex(); + if(index < 0) return null; + return ((CTreeItem)((CTree)handle).getPathForRow(index).getLastPathComponent()).getTreeItem(); +} + +//int imageIndex (Image image) { +// if (image == null) return OS.I_IMAGENONE; +// if (imageList == null) { +// int hOldList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); +// if (hOldList != 0) OS.ImageList_Destroy (hOldList); +// Rectangle bounds = image.getBounds (); +// imageList = display.getImageList (new Point (bounds.width, bounds.height)); +// int index = imageList.indexOf (image); +// if (index == -1) index = imageList.add (image); +// int hImageList = imageList.getHandle (); +// OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList); +// if (hwndHeader != 0) { +// OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList); +// } +// updateScrollBar (); +// return index; +// } +// int index = imageList.indexOf (image); +// if (index != -1) return index; +// return imageList.add (image); +//} + +//int indexOf (int hItem, int hChild) { +// int index = 0; +// while (hItem != 0 && hItem != hChild) { +// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); +// index++; +// } +// return hItem == hChild ? index : -1; +//} + +/** + * Searches the receiver's list starting at the first column + * (index 0) until a column is found that is equal to the + * argument, and returns the index of that column. If no column + * is found, returns -1. + * + * @param column the search column + * @return the index of the column + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public int indexOf (TreeColumn column) { + checkWidget (); + if (column == null) error (SWT.ERROR_NULL_ARGUMENT); + if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + return columnList.indexOf(column); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the tool item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the tool item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public int indexOf (TreeItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + return itemList.indexOf(item); +} + +//void register () { +// super.register (); +// if (hwndParent != 0) display.addControl (hwndParent, this); +//} +// +//boolean releaseItem (TreeItem item, TVITEM tvItem) { +// int hItem = item.handle; +// if (hItem == hAnchor) hAnchor = 0; +// if (item.isDisposed ()) return false; +// tvItem.hItem = hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// items [tvItem.lParam] = null; +// return true; +//} +// +//void releaseItems (TreeItem [] nodes, TVITEM tvItem) { +// for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void removeAll () { + checkWidget (); + for (int i=itemList.size()-1; i>=0; i--) { + TreeItem item = (TreeItem)itemList.get(i); + if (item != null && !item.isDisposed ()) { + item.dispose(); +// item.release (false); + } else { + itemList.remove(i); + } + } +// ((CTree)handle).getRoot().removeAllChildren(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's selection changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when items in the receiver are expanded or collapsed. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see TreeListener + * @see #addTreeListener + */ +public void removeTreeListener(TreeListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Expand, listener); + eventTable.unhook (SWT.Collapse, listener); +} + +/** + * Display a mark indicating the point at which an item will be inserted. + * The drop insert item has a visual hint to show where a dragged item + * will be inserted when dropped on the tree. + * + * @param item the insert item. Null will clear the insertion mark. + * @param before true places the insert mark above 'item'. false places + * the insert mark below 'item'. + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setInsertMark (TreeItem item, boolean before) { + checkWidget (); + Utils.notImplemented(); +// int hItem = 0; +// if (item != null) { +// if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); +// hItem = item.handle; +// } +// OS.SendMessage (handle, OS.TVM_SETINSERTMARK, (before) ? 0 : 1, hItem); +} + +/** + * Sets the number of root-level items contained in the receiver. + * + * @param count the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setItemCount (int count) { + checkWidget (); + count = Math.max (0, count); + setItemCount (null, itemList, count); + +// itemList.add(index, item); +// ((CTree)handle).getRoot().insert((MutableTreeNode)item.handle, index); + +// Utils.notImplemented(); +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); +// setItemCount (count, OS.TVGN_ROOT, hItem); +} + +void setItemCount (TreeItem treeItem, int count) { + if(treeItem.itemList == null) { + treeItem.itemList = new ArrayList(); + } + setItemCount (treeItem, treeItem.itemList, count); +} + +void setItemCount (TreeItem parentItem, ArrayList itemList, int count) { + count = Math.max (0, count); + for(int i=itemList.size()-1; i>= count; i--) { + TreeItem item = (TreeItem)itemList.get(i); + if (item != null && !item.isDisposed ()) { + item.release (false); + } + if(parentItem == null) { + ((CTree)handle).getRoot().remove(i); + } else { + ((DefaultMutableTreeTableNode)parentItem.handle).remove(i); + } + } + int itemCount = count - itemList.size(); + if(itemCount <= 0) { + return; + } + itemList.ensureCapacity(count); + for(int i=0; ione of the items in the tree. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +/*public*/ void setItemHeight (int itemHeight) { + checkWidget (); + if (itemHeight < -1) error (SWT.ERROR_INVALID_ARGUMENT); + ((CTree)handle).setRowHeight(itemHeight); +} + +/** + * Marks the receiver's lines as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param show the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setLinesVisible (boolean show) { + checkWidget (); + ((CTree)handle).setGridVisible(show); +} + +//int scrolledHandle () { +// if (hwndHeader == 0) return handle; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// return count == 0 ? handle : hwndParent; +//} + +/** + * Selects all of the items in the receiver. + *

    + * If the receiver is single-select, do nothing. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void selectAll () { + checkWidget (); + if ((style & SWT.SINGLE) != 0) return; + ((CTree)handle).selectAll(); +} + +//void setBounds (int x, int y, int width, int height, int flags) { +// /* +// * Ensure that the selection is visible when the tree is resized +// * from a zero size to a size that can show the selection. +// */ +// boolean fixSelection = false; +// if ((flags & OS.SWP_NOSIZE) == 0 && (width != 0 || height != 0)) { +// if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) == 0) { +// fixSelection = true; +// } +// } +// super.setBounds (x, y, width, height, flags); +// if (fixSelection) { +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) showItem (hItem); +// } +//} + +//void setCursor () { +// /* +// * Bug in Windows. Under certain circumstances, when WM_SETCURSOR +// * is sent from SendMessage(), Windows GP's in the window proc for +// * the tree. The fix is to avoid calling the tree window proc and +// * set the cursor for the tree outside of WM_SETCURSOR. +// * +// * NOTE: This code assumes that the default cursor for the tree +// * is IDC_ARROW. +// */ +// Cursor cursor = findCursor (); +// int hCursor = cursor == null ? OS.LoadCursor (0, OS.IDC_ARROW) : cursor.handle; +// OS.SetCursor (hCursor); +//} + +//void setCheckboxImageList () { +// if ((style & SWT.CHECK) == 0) return; +// int count = 5; +// int height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0), width = height; +// int flags = ImageList.COLOR_FLAGS; +// if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR; +// int hImageList = OS.ImageList_Create (width, height, flags, count, count); +// int hDC = OS.GetDC (handle); +// int memDC = OS.CreateCompatibleDC (hDC); +// int hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height); +// int hOldBitmap = OS.SelectObject (memDC, hBitmap); +// RECT rect = new RECT (); +// OS.SetRect (rect, 0, 0, width * count, height); +// int hBrush = OS.CreateSolidBrush (_getBackgroundPixel ()); +// OS.FillRect (memDC, rect, hBrush); +// OS.DeleteObject (hBrush); +// int oldFont = OS.SelectObject (hDC, defaultFont ()); +// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA (); +// OS.GetTextMetrics (hDC, tm); +// OS.SelectObject (hDC, oldFont); +// int itemWidth = Math.min (tm.tmHeight, width); +// int itemHeight = Math.min (tm.tmHeight, height); +// int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1; +// OS.SetRect (rect, left + width, top, left + width + itemWidth, top + itemHeight); +// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { +// int hTheme = OS.OpenThemeData (handle, BUTTON); +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); +// rect.left += width; rect.right += width; +// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDNORMAL, rect, null); +// OS.CloseThemeData (hTheme); +// } else { +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_INACTIVE | OS.DFCS_FLAT); +// rect.left += width; rect.right += width; +// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_INACTIVE | OS.DFCS_FLAT); +// } +// OS.SelectObject (memDC, hOldBitmap); +// OS.DeleteDC (memDC); +// OS.ReleaseDC (handle, hDC); +// OS.ImageList_Add (hImageList, hBitmap, 0); +// OS.DeleteObject (hBitmap); +// int hOldList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0); +// OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, hImageList); +// if (hOldList != 0) OS.ImageList_Destroy (hOldList); +//} + +/** + * Sets the order that the items in the receiver should + * be displayed in to the given argument which is described + * in terms of the zero-relative ordering of when the items + * were added. + * + * @param order the new order to display the items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item order is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
    • + *
    + * + * @see Tree#getColumnOrder() + * @see TreeColumn#getMoveable() + * @see TreeColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.2 + */ +public void setColumnOrder (int [] order) { + checkWidget (); + if (order == null) error (SWT.ERROR_NULL_ARGUMENT); + int columnCount = getColumnCount(); + if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT); + ((CTree)handle).setColumnOrder(order); +// int count = 0; +// if (hwndHeader != 0) { +// count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// } +// if (count == 0) { +// if (order.length != 0) error (SWT.ERROR_INVALID_ARGUMENT); +// return; +// } +// if (order.length != count) error (SWT.ERROR_INVALID_ARGUMENT); +// int [] oldOrder = new int [count]; +// OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder); +// boolean reorder = false; +// boolean [] seen = new boolean [count]; +// for (int i=0; i= count) error (SWT.ERROR_INVALID_RANGE); +// if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT); +// seen [index] = true; +// if (index != oldOrder [i]) reorder = true; +// } +// if (reorder) { +// RECT [] oldRects = new RECT [count]; +// for (int i=0; itrue, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param show the new visibility state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setHeaderVisible (boolean show) { + checkWidget (); + ((CTree)handle).setHeaderVisible(show); +} + +//void setScrollWidth () { +// if (hwndHeader == 0 || hwndParent == 0) return; +// int width = 0; +// HDITEM hdItem = new HDITEM (); +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// for (int i=0; i + * If the item is not in the receiver, then it is ignored. + *

    + * + * @param item the item to select + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSelection (TreeItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + setSelection (new TreeItem [] {item}); +} + +/** + * Sets the receiver's selection to be the given array of items. + * The current selection is cleared before the new items are selected. + *

    + * Items that are not in the receiver are ignored. + * If the receiver is single-select and multiple items are specified, + * then all items are ignored. + *

    + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of items is null
    • + *
    • ERROR_INVALID_ARGUMENT - if one of the items has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#deselectAll() + */ +public void setSelection (TreeItem [] items) { + checkWidget (); + if (items == null) error (SWT.ERROR_NULL_ARGUMENT); + int length = items.length; + if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) { + deselectAll(); + return; + } + TreePath[] paths = new TreePath[items.length]; + for (int i = 0; i < items.length; i++) { + paths[i] = new TreePath(items[i].handle.getPath()); + } + ((CTree)handle).getSelectionModel().setSelectionPaths(paths); +} + +/** + * Sets the column used by the sort indicator for the receiver. A null + * value will clear the sort indicator. The current sort column is cleared + * before the new column is set. + * + * @param column the column used by the sort indicator or null + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the column is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSortColumn (TreeColumn column) { + checkWidget (); + if (column != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + sortColumn = column; + handle.repaint(); +} + +/** + * Sets the direction of the sort indicator for the receiver. The value + * can be one of UP, DOWN or NONE. + * + * @param direction the direction of the sort indicator + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setSortDirection (int direction) { + checkWidget (); + if ((direction & (SWT.UP | SWT.DOWN)) == 0 && direction != SWT.NONE) return; + sortDirection = direction; + handle.repaint(); +} + +/** + * Sets the item which is currently at the top of the receiver. + * This item can change when items are expanded, collapsed, scrolled + * or new items are added or removed. + * + * @param item the item to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#getTopItem() + * + * @since 2.1 + */ +public void setTopItem (TreeItem item) { + checkWidget (); + if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT); + int row = ((CTree)handle).getRowForPath(new TreePath(item.handle.getPath())); + if(row < 0) { + return; + } + ((CTree)handle).setTopIndex(row); +} + +//void showItem (int hItem) { +// /* +// * Bug in Windows. When TVM_ENSUREVISIBLE is used to ensure +// * that an item is visible and the client area of the tree is +// * smaller that the size of one item, TVM_ENSUREVISIBLE makes +// * the next item in the tree visible by making it the top item +// * instead of making the desired item visible. The fix is to +// * detect the case when the client area is too small and make +// * the desired visible item be the top item in the tree. +// */ +// if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) == 0) { +// boolean fixScroll = checkScroll (hItem); +// if (fixScroll) { +// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); +// } +// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hItem); +// OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0); +// if (fixScroll) { +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); +// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// } +// } else { +// boolean scroll = true; +// RECT itemRect = new RECT (); +// itemRect.left = hItem; +// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, itemRect) != 0) { +// forceResize (); +// RECT rect = new RECT (); +// OS.GetClientRect (handle, rect); +// POINT pt = new POINT (); +// pt.x = itemRect.left; +// pt.y = itemRect.top; +// if (OS.PtInRect (rect, pt)) { +// pt.y = itemRect.bottom; +// if (OS.PtInRect (rect, pt)) scroll = false; +// } +// } +// if (scroll) { +// boolean fixScroll = checkScroll (hItem); +// if (fixScroll) { +// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); +// } +// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem); +// if (fixScroll) { +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); +// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// } +// } +// } +// if (hwndParent != 0) { +// RECT itemRect = new RECT (); +// itemRect.left = hItem; +// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, itemRect) != 0) { +// forceResize (); +// RECT rect = new RECT (); +// OS.GetClientRect (hwndParent, rect); +// OS.MapWindowPoints (hwndParent, handle, rect, 2); +// POINT pt = new POINT (); +// pt.x = itemRect.left; +// pt.y = itemRect.top; +// if (!OS.PtInRect (rect, pt)) { +// pt.y = itemRect.bottom; +// if (!OS.PtInRect (rect, pt)) { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// info.fMask = OS.SIF_POS; +// info.nPos = Math.max (0, pt.x - Tree.INSET / 2); +// OS.SetScrollInfo (hwndParent, OS.SB_HORZ, info, true); +// setScrollWidth (); +// } +// } +// } +// } +// updateScrollBar (); +//} + +/** + * Shows the column. If the column is already showing in the receiver, + * this method simply returns. Otherwise, the columns are scrolled until + * the column is visible. + * + * @param column the column to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void showColumn (TreeColumn column) { + checkWidget (); + if (column == null) error (SWT.ERROR_NULL_ARGUMENT); + if (column.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); + if (column.parent != this) return; + int index = indexOf (column); + if (index == -1) return; + ((CTree)handle).ensureColumnVisible(index); +} + +/** + * Shows the item. If the item is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled + * and expanded until the item is visible. + * + * @param item the item to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#showSelection() + */ +public void showItem (TreeItem item) { + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); + int row = ((CTree)handle).getRowForPath(new TreePath(item.handle.getPath())); + if(row < 0) { + return; + } + ((CTree)handle).ensureRowVisible(row); +} + +/** + * Shows the selection. If the selection is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the selection is visible. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#showItem(TreeItem) + */ +public void showSelection () { + checkWidget (); + int selectionRow = ((CTree)handle).getSelectionModel().getLeadSelectionRow(); + if(selectionRow == -1) { + return; + } + ((CTree)handle).ensureRowVisible(selectionRow); +} + +//void showWidget (boolean visible) { +// super.showWidget (visible); +// if (hwndParent != 0) { +// OS.ShowWindow (hwndParent, visible ? OS.SW_SHOW : OS.SW_HIDE); +// } +//} +// +//void updateScrollBar () { +// if (hwndParent != 0) { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count != 0) { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// info.fMask = OS.SIF_ALL; +// OS.GetScrollInfo (handle, OS.SB_VERT, info); +// OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true); +// } +// } +//} +// +//TCHAR windowClass () { +// return TreeClass; +//} +// +//int windowProc () { +// return TreeProc; +//} +// +//int windowProc (int hwnd, int msg, int wParam, int lParam) { +// if (hwndParent != 0 && hwnd == hwndParent) { +// switch (msg) { +// case OS.WM_MOVE: { +// sendEvent (SWT.Move); +// return 0; +// } +// case OS.WM_SIZE: { +// setScrollWidth (); +// if (ignoreResize) return 0; +// setResizeChildren (false); +// int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam); +// sendEvent (SWT.Resize); +// if (isDisposed ()) return 0; +// if (layout != null) { +// markLayout (false, false); +// updateLayout (false, false); +// } +// setResizeChildren (true); +// return code; +// } +// case OS.WM_COMMAND: +// case OS.WM_NOTIFY: +// case OS.WM_SYSCOLORCHANGE: { +// return OS.SendMessage (handle, msg, wParam, lParam); +// } +// case OS.WM_VSCROLL: { +// SCROLLINFO info = new SCROLLINFO (); +// info.cbSize = SCROLLINFO.sizeof; +// info.fMask = OS.SIF_ALL; +// OS.GetScrollInfo (hwndParent, OS.SB_VERT, info); +// OS.SetScrollInfo (handle, OS.SB_VERT, info, true); +// int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam); +// OS.GetScrollInfo (handle, OS.SB_VERT, info); +// OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true); +// return code; +// } +// case OS.WM_HSCROLL: { +// /* +// * Bug on WinCE. lParam should be NULL when the message is not sent +// * by a scroll bar control, but it contains the handle to the window. +// * When the message is sent by a scroll bar control, it correctly +// * contains the handle to the scroll bar. The fix is to check for +// * both. +// */ +// if (horizontalBar != null && (lParam == 0 || lParam == hwndParent)) { +// wmScroll (horizontalBar, true, hwndParent, OS.WM_HSCROLL, wParam, lParam); +// } +// setScrollWidth (); +// break; +// } +// } +// return callWindowProc (hwnd, msg, wParam, lParam); +// } +// int code = super.windowProc (handle, msg, wParam, lParam); +// switch (msg) { +// /* Keyboard messages */ +// case OS.WM_CHAR: +// case OS.WM_IME_CHAR: +// case OS.WM_KEYDOWN: +// case OS.WM_KEYUP: +// case OS.WM_SYSCHAR: +// case OS.WM_SYSKEYDOWN: +// case OS.WM_SYSKEYUP: +// +// /* Mouse messages */ +// case OS.WM_LBUTTONDBLCLK: +// case OS.WM_LBUTTONDOWN: +// case OS.WM_LBUTTONUP: +// case OS.WM_MBUTTONDBLCLK: +// case OS.WM_MBUTTONDOWN: +// case OS.WM_MBUTTONUP: +// case OS.WM_MOUSEHOVER: +// case OS.WM_MOUSELEAVE: +// case OS.WM_MOUSEMOVE: +// case OS.WM_MOUSEWHEEL: +// case OS.WM_RBUTTONDBLCLK: +// case OS.WM_RBUTTONDOWN: +// case OS.WM_RBUTTONUP: +// case OS.WM_XBUTTONDBLCLK: +// case OS.WM_XBUTTONDOWN: +// case OS.WM_XBUTTONUP: +// +// /* Other messages */ +// case OS.WM_SIZE: +// case OS.WM_SETFONT: +// case OS.WM_TIMER: { +// updateScrollBar (); +// } +// } +// return code; +//} +// +//LRESULT WM_CHAR (int wParam, int lParam) { +// LRESULT result = super.WM_CHAR (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. The tree control beeps +// * in WM_CHAR when the search for the item that +// * matches the key stroke fails. This is the +// * standard tree behavior but is unexpected when +// * the key that was typed was ESC, CR or SPACE. +// * The fix is to avoid calling the tree window +// * proc in these cases. +// */ +// switch (wParam) { +// case SWT.CR: +// /* +// * Feature in Windows. Windows sends NM_RETURN from WM_KEYDOWN +// * instead of using WM_CHAR. This means that application code +// * that expects to consume the key press and therefore avoid a +// * SWT.DefaultSelection event from WM_CHAR will fail. The fix +// * is to implement SWT.DefaultSelection in WM_CHAR instead of +// * using NM_RETURN. +// */ +// Event event = new Event (); +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.hItem = hItem; +// tvItem.mask = OS.TVIF_PARAM; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// event.item = items [tvItem.lParam]; +// } +// postEvent (SWT.DefaultSelection, event); +// //FALL THROUGH +// case SWT.ESC: +// case ' ': +// return LRESULT.ZERO; +// } +// return result; +//} +// +//LRESULT WM_GETOBJECT (int wParam, int lParam) { +// /* +// * Ensure that there is an accessible object created for this +// * control because support for checked item and tree column +// * accessibility is temporarily implemented in the accessibility +// * package. +// */ +// if ((style & SWT.CHECK) != 0 || hwndParent != 0) { +// if (accessible == null) accessible = new_Accessible (this); +// } +// return super.WM_GETOBJECT (wParam, lParam); +//} +// +//LRESULT WM_KEYDOWN (int wParam, int lParam) { +// LRESULT result = super.WM_KEYDOWN (wParam, lParam); +// if (result != null) return result; +// switch (wParam) { +// case OS.VK_SPACE: { +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) { +// hAnchor = hItem; +// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem); +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE | OS.TVIF_PARAM; +// tvItem.hItem = hItem; +// if ((style & SWT.CHECK) != 0) { +// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// int state = tvItem.state >> 12; +// if ((state & 0x1) != 0) { +// state++; +// } else { +// --state; +// } +// tvItem.state = state << 12; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// if (!OS.IsWinCE) { +// int id = hItem; +// if (OS.COMCTL32_MAJOR >= 6) { +// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, hItem, 0); +// } +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id); +// } +// } +// tvItem.stateMask = OS.TVIS_SELECTED; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((style & SWT.MULTI) != 0 && OS.GetKeyState (OS.VK_CONTROL) < 0) { +// if ((tvItem.state & OS.TVIS_SELECTED) != 0) { +// tvItem.state &= ~OS.TVIS_SELECTED; +// } else { +// tvItem.state |= OS.TVIS_SELECTED; +// } +// } else { +// tvItem.state |= OS.TVIS_SELECTED; +// } +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// postEvent (SWT.Selection, event); +// if ((style & SWT.CHECK) != 0) { +// event = new Event (); +// event.item = items [tvItem.lParam]; +// event.detail = SWT.CHECK; +// postEvent (SWT.Selection, event); +// } +// return LRESULT.ZERO; +// } +// break; +// } +// case OS.VK_UP: +// case OS.VK_DOWN: +// case OS.VK_PRIOR: +// case OS.VK_NEXT: +// case OS.VK_HOME: +// case OS.VK_END: { +// if ((style & SWT.SINGLE) != 0) break; +// OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); +// if (OS.GetKeyState (OS.VK_SHIFT) < 0) { +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) { +// if (hAnchor == 0) hAnchor = hItem; +// ignoreSelect = ignoreDeselect = true; +// int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); +// ignoreSelect = ignoreDeselect = false; +// int hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// int hDeselectItem = hItem; +// RECT rect1 = new RECT (); +// rect1.left = hAnchor; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect1); +// RECT rect2 = rect2 = new RECT (); +// rect2.left = hDeselectItem; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect2); +// int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE; +// while (hDeselectItem != hAnchor) { +// tvItem.hItem = hDeselectItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// hDeselectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem); +// } +// int hSelectItem = hAnchor; +// rect1.left = hNewItem; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect1); +// rect2.left = hSelectItem; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect2); +// tvItem.state = OS.TVIS_SELECTED; +// flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE; +// while (hSelectItem != hNewItem) { +// tvItem.hItem = hSelectItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// hSelectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hSelectItem); +// } +// tvItem.hItem = hNewItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// tvItem.mask = OS.TVIF_PARAM; +// tvItem.hItem = hNewItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// postEvent (SWT.Selection, event); +// return new LRESULT (code); +// } +// } +// if (OS.GetKeyState (OS.VK_CONTROL) < 0) { +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// tvItem.hItem = hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// boolean oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0; +// int hNewItem = 0; +// switch (wParam) { +// case OS.VK_UP: +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUSVISIBLE, hItem); +// break; +// case OS.VK_DOWN: +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem); +// break; +// case OS.VK_HOME: +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); +// break; +// case OS.VK_PRIOR: +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); +// if (hNewItem == hItem) { +// OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEUP, 0); +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); +// } +// break; +// case OS.VK_NEXT: +// RECT rect = new RECT (), clientRect = new RECT (); +// OS.GetClientRect (handle, clientRect); +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); +// do { +// int hVisible = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem); +// if (hVisible == 0) break; +// rect.left = hVisible; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect); +// if (rect.bottom > clientRect.bottom) break; +// if ((hNewItem = hVisible) == hItem) { +// OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0); +// } +// } while (hNewItem != 0); +// break; +// case OS.VK_END: +// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0); +// break; +// } +// if (hNewItem != 0) { +// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hNewItem); +// tvItem.hItem = hNewItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// boolean newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0; +// if (!newSelected && drawCount == 0) { +// OS.UpdateWindow (handle); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); +// /* +// * This code is intentionally commented. +// */ +//// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// } +// ignoreSelect = true; +// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem); +// ignoreSelect = false; +// if (oldSelected) { +// tvItem.state = OS.TVIS_SELECTED; +// tvItem.hItem = hItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// if (!newSelected) { +// tvItem.state = 0; +// tvItem.hItem = hNewItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// if (!newSelected && drawCount == 0) { +// RECT rect1 = new RECT (), rect2 = new RECT (); +// rect1.left = hItem; rect2.left = hNewItem; +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// int fItemRect = (bits & OS.TVS_FULLROWSELECT) != 0 ? 0 : 1; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect1); +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect2); +// /* +// * This code is intentionally commented. +// */ +//// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); +// if (OS.IsWinCE) { +// OS.InvalidateRect (handle, rect1, false); +// OS.InvalidateRect (handle, rect2, false); +// OS.UpdateWindow (handle); +// } else { +// int flags = OS.RDW_UPDATENOW | OS.RDW_INVALIDATE; +// OS.RedrawWindow (handle, rect1, 0, flags); +// OS.RedrawWindow (handle, rect2, 0, flags); +// } +// } +// return LRESULT.ZERO; +// } +// } +// } +// int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); +// hAnchor = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// return new LRESULT (code); +// } +// } +// return result; +//} +// +//LRESULT WM_KILLFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_KILLFOCUS (wParam, lParam); +// if ((style & SWT.SINGLE) != 0) return result; +// /* +// * Feature in Windows. When multiple item have +// * the TVIS_SELECTED state, Windows redraws only +// * the focused item in the color used to show the +// * selection when the tree loses or gains focus. +// * The fix is to force Windows to redraw all the +// * visible items when focus is gained or lost. +// */ +// OS.InvalidateRect (handle, null, false); +// return result; +//} +// +//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { +// if ((style & SWT.CHECK) != 0) { +// TVHITTESTINFO lpht = new TVHITTESTINFO (); +// lpht.x = (short) (lParam & 0xFFFF); +// lpht.y = (short) (lParam >> 16); +// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht); +// if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 0) { +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// TVITEM tvItem = new TVITEM (); +// tvItem.hItem = lpht.hItem; +// tvItem.mask = OS.TVIF_PARAM | OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// int state = tvItem.state >> 12; +// if ((state & 0x1) != 0) { +// state++; +// } else { +// --state; +// } +// tvItem.state = state << 12; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// if (!OS.IsWinCE) { +// int id = tvItem.hItem; +// if (OS.COMCTL32_MAJOR >= 6) { +// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0); +// } +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id); +// } +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// event.detail = SWT.CHECK; +// postEvent (SWT.Selection, event); +// return LRESULT.ZERO; +// } +// } +// return super.WM_LBUTTONDBLCLK (wParam, lParam); +//} +// +//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +// /* +// * In a multi-select tree, if the user is collapsing a subtree that +// * contains selected items, clear the selection from these items and +// * issue a selection event. Only items that are selected and visible +// * are cleared. This code also runs in the case when no item is selected. +// */ +// TVHITTESTINFO lpht = new TVHITTESTINFO (); +// lpht.x = (short) (lParam & 0xFFFF); +// lpht.y = (short) (lParam >> 16); +// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht); +// if (lpht.hItem == 0 || (lpht.flags & OS.TVHT_ONITEMBUTTON) != 0) { +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// boolean fixSelection = false, deselected = false; +// if (lpht.hItem != 0 && (style & SWT.MULTI) != 0) { +// int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hSelection != 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE | OS.TVIF_PARAM; +// tvItem.hItem = lpht.hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((tvItem.state & OS.TVIS_EXPANDED) != 0) { +// fixSelection = true; +// tvItem.stateMask = OS.TVIS_SELECTED; +// int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, lpht.hItem); +// int hLast = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, lpht.hItem); +// int hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem); +// while (hNext != 0 && hNext != hLast) { +// tvItem.hItem = hNext; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((tvItem.state & OS.TVIS_SELECTED) != 0) deselected = true; +// tvItem.state = 0; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// if ((hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNext)) == 0) break; +// if (hParent == OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNext)) break; +// } +// } +// } +// } +// dragStarted = gestureCompleted = false; +// if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true; +// int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false; +// if (dragStarted && OS.GetCapture () != handle) OS.SetCapture (handle); +// if (deselected) { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_PARAM; +// tvItem.hItem = lpht.hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// postEvent (SWT.Selection, event); +// } +// return new LRESULT (code); +// } +// +// /* Look for check/uncheck */ +// if ((style & SWT.CHECK) != 0) { +// if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 0) { +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// if (OS.GetCapture () != handle) OS.SetCapture (handle); +// TVITEM tvItem = new TVITEM (); +// tvItem.hItem = lpht.hItem; +// tvItem.mask = OS.TVIF_PARAM | OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// int state = tvItem.state >> 12; +// if ((state & 0x1) != 0) { +// state++; +// } else { +// --state; +// } +// tvItem.state = state << 12; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// if (!OS.IsWinCE) { +// int id = tvItem.hItem; +// if (OS.COMCTL32_MAJOR >= 6) { +// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0); +// } +// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id); +// } +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// event.detail = SWT.CHECK; +// postEvent (SWT.Selection, event); +// return LRESULT.ZERO; +// } +// } +// +// /* Get the selected state of the item under the mouse */ +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// boolean hittestSelected = false; +// if ((style & SWT.MULTI) != 0) { +// tvItem.hItem = lpht.hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// hittestSelected = (tvItem.state & OS.TVIS_SELECTED) != 0; +// } +// +// /* Get the selected state of the last selected item */ +// int hOldItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if ((style & SWT.MULTI) != 0) { +// tvItem.hItem = hOldItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// +// /* Check for CONTROL or drag selection */ +// if (hittestSelected || (wParam & OS.MK_CONTROL) != 0) { +// if (drawCount == 0) { +// OS.UpdateWindow (handle); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); +// /* +// * This code is intentionally commented. +// */ +//// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); +// } +// } else { +// deselectAll (); +// } +// } +// +// /* Do the selection */ +// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// dragStarted = gestureCompleted = false; +// ignoreDeselect = ignoreSelect = true; +// int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); +// ignoreDeselect = ignoreSelect = false; +// if (dragStarted && OS.GetCapture () != handle) OS.SetCapture (handle); +// int hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// +// /* +// * Feature in Windows. When the old and new focused item +// * are the same, Windows does not check to make sure that +// * the item is actually selected, not just focused. The +// * fix is to force the item to draw selected by setting +// * the state mask. This is only necessary when the tree +// * is single select. +// */ +// if ((style & SWT.SINGLE) != 0) { +// if (hOldItem == hNewItem) { +// tvItem.mask = OS.TVIF_STATE; +// tvItem.state = OS.TVIS_SELECTED; +// tvItem.stateMask = OS.TVIS_SELECTED; +// tvItem.hItem = hNewItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// } +// +// /* Reselect the last item that was unselected */ +// if ((style & SWT.MULTI) != 0) { +// +// /* Check for CONTROL and reselect the last item */ +// if (hittestSelected || (wParam & OS.MK_CONTROL) != 0) { +// if (hOldItem == hNewItem && hOldItem == lpht.hItem) { +// if ((wParam & OS.MK_CONTROL) != 0) { +// tvItem.state ^= OS.TVIS_SELECTED; +// if (dragStarted) tvItem.state = OS.TVIS_SELECTED; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// } else { +// if ((tvItem.state & OS.TVIS_SELECTED) != 0) { +// tvItem.state = OS.TVIS_SELECTED; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// if ((wParam & OS.MK_CONTROL) != 0 && !dragStarted) { +// if (hittestSelected) { +// tvItem.state = 0; +// tvItem.hItem = lpht.hItem; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// } +// } +// if (drawCount == 0) { +// RECT rect1 = new RECT (), rect2 = new RECT (); +// rect1.left = hOldItem; rect2.left = hNewItem; +// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); +// int fItemRect = (bits & OS.TVS_FULLROWSELECT) != 0 ? 0 : 1; +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect1); +// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect2); +// /* +// * This code is intentionally commented. +// */ +//// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0); +// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); +// if (OS.IsWinCE) { +// OS.InvalidateRect (handle, rect1, false); +// OS.InvalidateRect (handle, rect2, false); +// OS.UpdateWindow (handle); +// } else { +// int flags = OS.RDW_UPDATENOW | OS.RDW_INVALIDATE; +// OS.RedrawWindow (handle, rect1, 0, flags); +// OS.RedrawWindow (handle, rect2, 0, flags); +// } +// } +// } +// +// /* Check for SHIFT or normal select and delect/reselect items */ +// if ((wParam & OS.MK_CONTROL) == 0) { +// if (!hittestSelected || !dragStarted) { +// tvItem.state = 0; +// int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); +// OS.SetWindowLong (handle, OS.GWL_WNDPROC, TreeProc); +// for (int i=0; i> 16); +// postEvent (SWT.DragDetect, event); +// } else { +// sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam); +// } +// dragStarted = false; +// return new LRESULT (code); +//} +// +//LRESULT WM_MOVE (int wParam, int lParam) { +// if (ignoreResize) return null; +// return super.WM_MOVE (wParam, lParam); +//} +// +//LRESULT WM_NOTIFY (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// if (hwndHeader != 0 && hdr.hwndFrom == hwndHeader) { +// /* +// * Feature in Windows. On NT, the automatically created +// * header control is created as a UNICODE window, not an +// * ANSI window despite the fact that the parent is created +// * as an ANSI window. This means that it sends UNICODE +// * notification messages to the parent window on NT for +// * no good reason. The data and size in the NMHEADER and +// * HDITEM structs is identical between the platforms so no +// * different message is actually necessary. Despite this, +// * Windows sends different messages. The fix is to look +// * for both messages, despite the platform. This works +// * because only one will be sent on either platform, never +// * both. +// */ +// switch (hdr.code) { +// case OS.HDN_BEGINTRACKW: +// case OS.HDN_BEGINTRACKA: +// case OS.HDN_DIVIDERDBLCLICKW: +// case OS.HDN_DIVIDERDBLCLICKA: { +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// TreeColumn column = columns [phdn.iItem]; +// if (column != null && !column.getResizable ()) { +// return LRESULT.ONE; +// } +// break; +// } +// case OS.HDN_ITEMCHANGINGW: +// case OS.HDN_ITEMCHANGINGA: { +// NMHEADER phdn = new NMHEADER (); +// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); +// if (phdn.pitem != 0) { +// HDITEM newItem = new HDITEM (); +// OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof); +// if ((newItem.mask & OS.HDI_WIDTH) != 0) { +// HDITEM oldItem = new HDITEM (); +// oldItem.mask = OS.HDI_WIDTH; +// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, oldItem); +// int deltaX = newItem.cxy - oldItem.cxy; +// RECT rect = new RECT (), itemRect = new RECT (); +// OS.GetClientRect (handle, rect); +// OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, itemRect); +// int gridWidth = getLinesVisible () ? GRID_WIDTH : 0; +// rect.left = itemRect.right - gridWidth; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (phdn.iItem < count - 1) { +// for (int i=phdn.iItem; i> 16); +// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht); +// if (lpht.hItem != 0 && (lpht.flags & (OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL)) != 0) { +// if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) == 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// tvItem.hItem = lpht.hItem; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((tvItem.state & OS.TVIS_SELECTED) == 0) { +// ignoreSelect = true; +// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, 0); +// ignoreSelect = false; +// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem); +// } +// } +// } +// return LRESULT.ZERO; +//} +// +//LRESULT WM_PRINTCLIENT (int wParam, int lParam) { +// LRESULT result = super.WM_PRINTCLIENT (wParam, lParam); +// if (result != null) return result; +// /* +// * Feature in Windows. For some reason, when WM_PRINT is used +// * to capture an image of a hierarchy that contains a tree with +// * columns, the clipping that is used to stop the first column +// * from drawing on top of subsequent columns stops the first +// * column and the tree lines from drawing. This does not happen +// * during WM_PAINT. The fix is to draw without clipping and +// * then draw the rest of the columns on top. Since the drawing +// * is happening in WM_PRINTCLIENT, the redrawing is not visible. +// */ +// printClient = true; +// int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); +// printClient = false; +// return new LRESULT (code); +//} +// +//LRESULT WM_SETFOCUS (int wParam, int lParam) { +// LRESULT result = super.WM_SETFOCUS (wParam, lParam); +// if ((style & SWT.SINGLE) != 0) return result; +// /* +// * Feature in Windows. When multiple item have +// * the TVIS_SELECTED state, Windows redraws only +// * the focused item in the color used to show the +// * selection when the tree loses or gains focus. +// * The fix is to force Windows to redraw all the +// * visible items when focus is gained or lost. +// */ +// OS.InvalidateRect (handle, null, false); +// return result; +//} +// +//LRESULT WM_SETFONT (int wParam, int lParam) { +// LRESULT result = super.WM_SETFONT (wParam, lParam); +// if (result != null) return result; +// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETFONT, wParam, lParam); +// return result; +//} +// +//LRESULT WM_SIZE (int wParam, int lParam) { +// if (ignoreResize) return null; +// return super.WM_SIZE (wParam, lParam); +//} +// +//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) { +// LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam); +// if (result != null) return result; +// if ((style & SWT.CHECK) != 0) setCheckboxImageList (); +// return result; +//} +// +//LRESULT wmColorChild (int wParam, int lParam) { +// /* +// * Feature in Windows. Tree controls send WM_CTLCOLOREDIT +// * to allow application code to change the default colors. +// * This is undocumented and conflicts with TVM_SETTEXTCOLOR +// * and TVM_SETBKCOLOR, the documented way to do this. The +// * fix is to ignore WM_CTLCOLOREDIT messages from trees. +// */ +// return null; +//} +// +//LRESULT wmNotifyChild (int wParam, int lParam) { +// NMHDR hdr = new NMHDR (); +// OS.MoveMemory (hdr, lParam, NMHDR.sizeof); +// switch (hdr.code) { +// case OS.TVN_GETDISPINFOA: +// case OS.TVN_GETDISPINFOW: { +// NMTVDISPINFO lptvdi = new NMTVDISPINFO (); +// OS.MoveMemory (lptvdi, lParam, NMTVDISPINFO.sizeof); +// /* +// * Feature in Windows. When a new tree item is inserted +// * using TVM_INSERTITEM, a TVN_GETDISPINFO is sent before +// * TVM_INSERTITEM returns and before the item is added to +// * the items array. The fix is to check for null. +// * +// * NOTE: This only happens on XP with the version 6.00 of +// * COMCTL32.DLL, +// */ +// if (items == null) break; +// TreeItem item = items [lptvdi.lParam]; +// if (item == null) break; +// if ((lptvdi.mask & OS.TVIF_TEXT) != 0) { +// String string = item.text; +// TCHAR buffer = new TCHAR (getCodePage (), string, false); +// int byteCount = Math.min (buffer.length (), lptvdi.cchTextMax - 1) * TCHAR.sizeof; +// OS.MoveMemory (lptvdi.pszText, buffer, byteCount); +// OS.MoveMemory (lptvdi.pszText + byteCount, new byte [TCHAR.sizeof], TCHAR.sizeof); +// lptvdi.cchTextMax = Math.min (lptvdi.cchTextMax, string.length () + 1); +// } +// if ((lptvdi.mask & (OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE)) != 0) { +// Image image = item.image; +// lptvdi.iImage = OS.I_IMAGENONE; +// if (image != null) { +// lptvdi.iImage = lptvdi.iSelectedImage = imageIndex (image); +// } +// } +// OS.MoveMemory (lParam, lptvdi, NMTVDISPINFO.sizeof); +// break; +// } +// case OS.NM_CUSTOMDRAW: { +// if (!customDraw) break; +// NMTVCUSTOMDRAW nmcd = new NMTVCUSTOMDRAW (); +// OS.MoveMemory (nmcd, lParam, NMTVCUSTOMDRAW.sizeof); +// switch (nmcd.dwDrawStage) { +// case OS.CDDS_PREPAINT: { +// return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT); +// } +// case OS.CDDS_POSTPAINT: { +// if (linesVisible) { +// int hDC = nmcd.hdc; +// if (hwndHeader != 0) { +// int x = 0; +// RECT rect = new RECT (); +// HDITEM hdItem = new HDITEM (); +// hdItem.mask = OS.HDI_WIDTH; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// for (int i=0; i= nmcd.right || nmcd.top >= nmcd.bottom) { +// break; +// } +// int hDC = nmcd.hdc; +// OS.SaveDC (hDC); +// if (linesVisible) { +// RECT rect = new RECT (); +// OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom); +// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); +// } +// if (!printClient && (style & SWT.FULL_SELECTION) == 0) { +// if (hwndHeader != 0) { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count != 0) { +// HDITEM hdItem = new HDITEM (); +// hdItem.mask = OS.HDI_WIDTH; +// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, hdItem); +// int hRgn = OS.CreateRectRgn (nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom); +// OS.SelectClipRgn (hDC, hRgn); +// OS.DeleteObject (hRgn); +// } +// } +// } +// if (item.font == -1 && item.foreground == -1 && item.background == -1) { +// if (item.cellForeground == null && item.cellBackground == null && item.cellFont == null) { +// return new LRESULT (OS.CDRF_DODEFAULT | OS.CDRF_NOTIFYPOSTPAINT); +// } +// } +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.hItem = item.handle; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// int hFont = item.cellFont != null ? item.cellFont [0] : item.font; +// if (hFont != -1) OS.SelectObject (hDC, hFont); +// if ((tvItem.state & (OS.TVIS_SELECTED | OS.TVIS_DROPHILITED)) == 0) { +// if (OS.IsWindowEnabled (handle)) { +// int clrText = item.cellForeground != null ? item.cellForeground [0] : item.foreground; +// nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText; +// int clrTextBk = item.cellBackground != null ? item.cellBackground [0] : item.background; +// nmcd.clrTextBk = clrTextBk == -1 ? getBackgroundPixel () : clrTextBk; +// OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof); +// } +// } +// return new LRESULT (OS.CDRF_NEWFONT | OS.CDRF_NOTIFYPOSTPAINT); +// } +// case OS.CDDS_ITEMPOSTPAINT: { +// TreeItem item = items [nmcd.lItemlParam]; +// if (item == null) break; +// /* +// * Feature in Windows. Under certain circumstances, Windows +// * sends CDDS_ITEMPOSTPAINT for an empty rectangle. This is +// * not a problem providing that graphics do not occur outside +// * the rectangle. The fix is to test for the rectangle and +// * draw nothing. +// * +// * NOTE: This seems to happen when both I_IMAGECALLBACK +// * and LPSTR_TEXTCALLBACK are used at the same time with +// * TVM_SETITEM. +// */ +// if (nmcd.left >= nmcd.right || nmcd.top >= nmcd.bottom) { +// break; +// } +// int hDC = nmcd.hdc; +// OS.RestoreDC (hDC, -1); +// OS.SetBkMode (hDC, OS.TRANSPARENT); +// boolean useColor = OS.IsWindowEnabled (handle); +// if (useColor) { +// if ((style & SWT.FULL_SELECTION) != 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.hItem = item.handle; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((tvItem.state & OS.TVIS_SELECTED) != 0) { +// useColor = false; +// } else { +// /* +// * Feature in Windows. When the mouse is pressed and the +// * selection is first drawn for a tree, the item is drawn +// * selected, but the TVIS_SELECTED bits for the item are +// * not set. When the user moves the mouse slightly and +// * a drag and drop operation is not started, the item is +// * drawn again and this time TVIS_SELECTED is set. This +// * means that an item that is in a tree that has the style +// * TVS_FULLROWSELECT and that also contains colored cells +// * will not draw the entire row selected until the user +// * moves the mouse. The fix is to test for the selection +// * colors and guess that the item is selected. +// * +// * NOTE: This code doesn't work when the foreground and +// * background of the tree are set to the selection colors +// * but this does not happen in a regular application. +// */ +// int clrForeground = OS.GetTextColor (hDC); +// if (clrForeground == OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) { +// int clrBackground = OS.GetBkColor (hDC); +// if (clrBackground == OS.GetSysColor (OS.COLOR_HIGHLIGHT)) { +// useColor = false; +// } +// } +// } +// } else { +// OS.SetTextColor (hDC, getForegroundPixel ()); +// } +// } +// if (hwndHeader != 0) { +// GCData data = new GCData(); +// data.device = display; +// GC gc = GC.win32_new (hDC, data); +// int x = 0; +// Point size = null; +// RECT rect = new RECT (); +// HDITEM hdItem = new HDITEM (); +// hdItem.mask = OS.HDI_WIDTH; +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// for (int i=0; i 0) { +// OS.SetRect (rect, x, nmcd.top, x + hdItem.cxy, nmcd.bottom - GRID_WIDTH); +// if (printClient || (style & SWT.FULL_SELECTION) != 0) { +// drawBackground (hDC, OS.GetBkColor (hDC), rect); +// } +// if (useColor) { +// int clrTextBk = item.cellBackground != null ? item.cellBackground [i] : item.background; +// if (clrTextBk != -1) drawBackground (hDC, clrTextBk, rect); +// } +// Image image = item.images != null ? item.images [i] : null; +// if (image != null) { +// Rectangle bounds = image.getBounds (); +// if (size == null) size = getImageSize (); +// gc.drawImage (image, 0, 0, bounds.width, bounds.height, rect.left, rect.top, size.x, size.y); +// OS.SetRect (rect, rect.left + size.x + INSET, rect.top, rect.right - INSET, rect.bottom); +// } else { +// OS.SetRect (rect, rect.left + INSET, rect.top, rect.right - INSET, rect.bottom); +// } +// /* +// * Bug in Windows. When DrawText() is used with DT_VCENTER +// * and DT_ENDELLIPSIS, the ellipsis can draw outside of the +// * rectangle when the rectangle is empty. The fix is avoid +// * all text drawing for empty rectangles. +// */ +// if (rect.left < rect.right) { +// if (item.strings != null && item.strings [i] != null) { +// int hFont = item.cellFont != null ? item.cellFont [i] : item.font; +// hFont = hFont != -1 ? OS.SelectObject (hDC, hFont) : -1; +// int clrText = -1; +// if (useColor) { +// clrText = item.cellForeground != null ? item.cellForeground [i] : item.foreground; +// clrText = clrText != -1? OS.SetTextColor (hDC, clrText) : -1; +// } +// int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER | OS.DT_ENDELLIPSIS; +// TreeColumn column = columns [i]; +// if ((column.style & SWT.LEFT) != 0) flags |= OS.DT_LEFT; +// if ((column.style & SWT.CENTER) != 0) flags |= OS.DT_CENTER; +// if ((column.style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT; +// TCHAR buffer = new TCHAR (getCodePage (), item.strings [i], false); +// OS.DrawText (hDC, buffer, buffer.length (), rect, flags); +// if (hFont != -1) OS.SelectObject (hDC, hFont); +// if (clrText != -1) OS.SetTextColor (hDC, clrText); +// } +// } +// } +// x += hdItem.cxy; +// } +// gc.dispose (); +// } +// if (linesVisible) { +// if (printClient && (style & SWT.FULL_SELECTION) == 0) { +// if (hwndHeader != 0) { +// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); +// if (count != 0 && printClient) { +// HDITEM hdItem = new HDITEM (); +// hdItem.mask = OS.HDI_WIDTH; +// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, hdItem); +// RECT rect = new RECT (); +// OS.SetRect (rect, nmcd.left + hdItem.cxy, nmcd.top, nmcd.right, nmcd.bottom); +// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); +// } +// } +// } +// RECT rect = new RECT (); +// if (OS.COMCTL32_MAJOR < 6 || (style & SWT.FULL_SELECTION) != 0) { +// OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom); +// } else { +// rect.left = item.handle; +// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect) != 0) { +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem == item.handle) { +// OS.SetRect (rect, rect.right, nmcd.top, nmcd.right, nmcd.bottom); +// } else { +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.hItem = item.handle; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// if ((tvItem.state & OS.TVIS_SELECTED) != 0) { +// OS.SetRect (rect, rect.right, nmcd.top, nmcd.right, nmcd.bottom); +// } else { +// OS.SetRect (rect, rect.left, nmcd.top, nmcd.right, nmcd.bottom); +// } +// } +// } else { +// rect.left = 0; +// } +// } +// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); +// } +// return new LRESULT (OS.CDRF_DODEFAULT); +// } +// } +// break; +// } +// case OS.NM_DBLCLK: { +// if (!ignoreSelect) { +// int pos = OS.GetMessagePos (); +// POINT pt = new POINT (); +// pt.x = (short) (pos & 0xFFFF); +// pt.y = (short) (pos >> 16); +// OS.ScreenToClient (handle, pt); +// TVHITTESTINFO lpht = new TVHITTESTINFO (); +// lpht.x = pt.x; +// lpht.y = pt.y; +// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht); +// if ((lpht.flags & OS.TVHT_ONITEM) == 0) break; +// Event event = new Event (); +// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); +// if (hItem != 0) { +// TVITEM tvItem = new TVITEM (); +// tvItem.hItem = hItem; +// tvItem.mask = OS.TVIF_PARAM; +// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem); +// event.item = items [tvItem.lParam]; +// } +// postEvent (SWT.DefaultSelection, event); +// } +// if (hooks (SWT.DefaultSelection)) return LRESULT.ONE; +// break; +// } +// case OS.TVN_SELCHANGEDA: +// case OS.TVN_SELCHANGEDW: { +// if ((style & SWT.MULTI) != 0) { +// if (lockSelection) { +// /* Restore the old selection state of both items */ +// if (oldSelected) { +// TVITEM tvItem = new TVITEM (); +// int offset = NMHDR.sizeof + 4; +// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// tvItem.state = OS.TVIS_SELECTED; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// if (!newSelected && ignoreSelect) { +// TVITEM tvItem = new TVITEM (); +// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; +// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof); +// tvItem.mask = OS.TVIF_STATE; +// tvItem.stateMask = OS.TVIS_SELECTED; +// tvItem.state = 0; +// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); +// } +// } +// } +// if (!ignoreSelect) { +// TVITEM tvItem = new TVITEM (); +// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; +// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof); +// hAnchor = tvItem.hItem; +// Event event = new Event (); +// event.item = items [tvItem.lParam]; +// postEvent (SWT.Selection, event); +// } +// updateScrollBar (); +// break; +// } +// case OS.TVN_SELCHANGINGA: +// case OS.TVN_SELCHANGINGW: { +// if ((style & SWT.MULTI) != 0) { +// if (lockSelection) { +// /* Save the old selection state for both items */ +// TVITEM tvItem = new TVITEM (); +// int offset1 = NMHDR.sizeof + 4; +// OS.MoveMemory (tvItem, lParam + offset1, TVITEM.sizeof); +// oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0; +// int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof; +// OS.MoveMemory (tvItem, lParam + offset2, TVITEM.sizeof); +// newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0; +// } +// } +// if (!ignoreSelect && !ignoreDeselect) { +// hAnchor = 0; +// if ((style & SWT.MULTI) != 0) deselectAll (); +// } +// break; +// } +// case OS.TVN_ITEMEXPANDEDA: +// case OS.TVN_ITEMEXPANDEDW: { +// updateScrollBar (); +// break; +// } +// case OS.TVN_ITEMEXPANDINGA: +// case OS.TVN_ITEMEXPANDINGW: { +// if (!ignoreExpand) { +// TVITEM tvItem = new TVITEM (); +// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; +// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof); +// /* +// * Feature in Windows. In some cases, TVM_ITEMEXPANDING +// * is sent from within TVM_DELETEITEM for the tree item +// * being destroyed. By the time the message is sent, +// * the item has already been removed from the list of +// * items. The fix is to check for null. +// */ +// if (items == null) break; +// TreeItem item = items [tvItem.lParam]; +// if (item == null) break; +// Event event = new Event (); +// event.item = item; +// int [] action = new int [1]; +// OS.MoveMemory (action, lParam + NMHDR.sizeof, 4); +// switch (action [0]) { +// case OS.TVE_EXPAND: +// /* +// * Bug in Windows. When the numeric keypad asterisk +// * key is used to expand every item in the tree, Windows +// * sends TVN_ITEMEXPANDING to items in the tree that +// * have already been expanded. The fix is to detect +// * that the item is already expanded and ignore the +// * notification. +// */ +// if ((tvItem.state & OS.TVIS_EXPANDED) == 0) { +// sendEvent (SWT.Expand, event); +// if (isDisposed ()) return LRESULT.ZERO; +// } +// break; +// case OS.TVE_COLLAPSE: +// sendEvent (SWT.Collapse, event); +// if (isDisposed ()) return LRESULT.ZERO; +// break; +// } +// } +// break; +// } +// case OS.TVN_BEGINDRAGA: +// case OS.TVN_BEGINDRAGW: +// case OS.TVN_BEGINRDRAGA: +// case OS.TVN_BEGINRDRAGW: { +// TVITEM tvItem = new TVITEM (); +// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; +// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof); +// if (tvItem.hItem != 0 && (tvItem.state & OS.TVIS_SELECTED) == 0) { +// ignoreSelect = ignoreDeselect = true; +// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem); +// ignoreSelect = ignoreDeselect = false; +// } +// dragStarted = true; +// break; +// } +// case OS.NM_RECOGNIZEGESTURE: { +// /* +// * Feature in Pocket PC. The tree and table controls detect the tap +// * and hold gesture by default. They send a GN_CONTEXTMENU message to show +// * the popup menu. This default behaviour is unwanted on Pocket PC 2002 +// * when no menu has been set, as it still draws a red circle. The fix +// * is to disable this default behaviour when no menu is set by returning +// * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE +// * message. +// */ +// if (OS.IsPPC) { +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE; +// } +// break; +// } +// case OS.GN_CONTEXTMENU: { +// if (OS.IsPPC) { +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (hasMenu || hooks (SWT.MenuDetect)) { +// NMRGINFO nmrg = new NMRGINFO (); +// OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof); +// showMenu (nmrg.x, nmrg.y); +// gestureCompleted = true; +// return LRESULT.ONE; +// } +// } +// break; +// } +// } +// return super.wmNotifyChild (wParam, lParam); +//} + +Point minimumSize (int wHint, int hHint, boolean changed) { + java.awt.Dimension size = handle.getPreferredSize(); + return new Point(size.width, size.height); +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case MouseEvent.MOUSE_CLICKED: if(!hooks(SWT.DefaultSelection) || ((MouseEvent)e).getClickCount() != 2) { super.processEvent(e); return; } break; + case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break; + default: { super.processEvent(e); return; } + } + if(isDisposed()) { + super.processEvent(e); + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + try { + switch(id) { + case MouseEvent.MOUSE_CLICKED: + MouseEvent me = (MouseEvent)e; + if(me.getClickCount() == 2) { + java.awt.Point location = me.getPoint(); + TreePath path = ((CTree)handle).getPathForLocation(location.x, location.y); + if(path != null) { + Event event = new Event(); + event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem(); + sendEvent(SWT.DefaultSelection, event); + } + } + break; + case ItemEvent.ITEM_STATE_CHANGED: + Event event = new Event(); + event.detail = SWT.CHECK; + event.item = ((CTreeItem)((ItemEvent)e).getItem()).getTreeItem(); + sendEvent(SWT.Selection, event); + break; + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(EventObject e) { + if(e instanceof TreeExpansionEvent) { + TreePath path = ((TreeExpansionEvent)e).getPath(); + if(!(path.getLastPathComponent() instanceof CTreeItem)) { + super.processEvent(e); + return; + } + boolean isExpanded = ((CTree)handle).isExpanded(path); + if(isExpanded) { + if(!hooks(SWT.Expand)) { super.processEvent(e); return; } + } else { + if(!hooks(SWT.Collapse)) { super.processEvent(e); return; } + } + } else if(e instanceof TreeSelectionEvent) { + TreePath path = ((TreeSelectionEvent)e).getPath(); + if(!(path.getLastPathComponent() instanceof CTreeItem)) { + super.processEvent(e); + return; + } + if(!hooks(SWT.Selection)) { super.processEvent(e); return; } + } else if(e instanceof CellPaintEvent) { + switch(((CellPaintEvent)e).getType()) { + case CellPaintEvent.ERASE_TYPE: if(!hooks(SWT.EraseItem)) { super.processEvent(e); return; } break; + case CellPaintEvent.PAINT_TYPE: if(!hooks(SWT.PaintItem)) { super.processEvent(e); return; } break; + case CellPaintEvent.MEASURE_TYPE: if(!hooks(SWT.MeasureItem)) { super.processEvent(e); return; } break; + default: super.processEvent(e); return; + } + } else { + super.processEvent(e); + return; + } + if(isDisposed()) { + super.processEvent(e); + return; + } + try { + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + super.processEvent(e); + return; + } + if(e instanceof TreeExpansionEvent) { + TreePath path = ((TreeExpansionEvent)e).getPath(); + boolean isExpanded = ((CTree)handle).isExpanded(path); + Event event = new Event(); + event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem(); + if(isExpanded) { + sendEvent(SWT.Expand, event); + ((CTree)handle).expandPath(path); + } else { + sendEvent(SWT.Collapse, event); + ((CTree)handle).collapsePath(path); + } + } else if(e instanceof TreeSelectionEvent) { + TreePath path = ((TreeSelectionEvent)e).getPath(); + Event event = new Event(); + event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem(); + sendEvent(SWT.Selection, event); + } else if(e instanceof CellPaintEvent) { + CellPaintEvent cellPaintEvent = (CellPaintEvent)e; + switch(cellPaintEvent.getType()) { + case CellPaintEvent.ERASE_TYPE: { + TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem(); + Rectangle cellBounds = treeItem.getBounds(cellPaintEvent.column); + Event event = new Event(); + event.x = cellBounds.x; + event.y = cellBounds.y; + event.width = cellBounds.width; + event.height = cellBounds.height; + event.item = treeItem; + event.index = cellPaintEvent.column; + if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND; + if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND; + if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED; + if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED; + event.gc = new GC(this); + event.gc.handle.setUserClip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); +// event.gc.isSwingPainting = true; + sendEvent(SWT.EraseItem, event); + if(event.doit) { + cellPaintEvent.ignoreDrawForeground = (event.detail & SWT.FOREGROUND) == 0; + cellPaintEvent.ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0; + cellPaintEvent.ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0; + cellPaintEvent.ignoreDrawFocused = (event.detail & SWT.FOCUSED) == 0; + } else { + cellPaintEvent.ignoreDrawForeground = true; + cellPaintEvent.ignoreDrawBackground = true; + cellPaintEvent.ignoreDrawSelection = true; + cellPaintEvent.ignoreDrawFocused = true; + } +// event.gc.isSwingPainting = false; + break; + } + case CellPaintEvent.PAINT_TYPE: { + TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem(); + Rectangle cellBounds = treeItem.getBounds(cellPaintEvent.column); + Event event = new Event(); + event.x = cellBounds.x; + event.y = cellBounds.y; + event.width = cellBounds.width; + event.height = cellBounds.height; + event.item = treeItem; + event.index = cellPaintEvent.column; + if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND; + if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND; + if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED; + if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED; + event.gc = new GC(this); + event.gc.handle.setUserClip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); + sendEvent(SWT.PaintItem, event); + break; + } + case CellPaintEvent.MEASURE_TYPE: + TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem(); +// Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column); + Event event = new Event(); +// event.x = cellBounds.x; +// event.y = cellBounds.y; +// event.width = cellBounds.width; +// event.height = cellBounds.height; + event.height = cellPaintEvent.rowHeight; + event.item = treeItem; + event.index = cellPaintEvent.column; + event.gc = new GC(this); +// event.gc.handle.clip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false)); + sendEvent(SWT.MeasureItem, event); +// cellPaintEvent.rowHeight -= event.height - cellBounds.height; + cellPaintEvent.rowHeight = event.height; + break; + } + } + super.processEvent(e); + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java new file mode 100644 index 00000000000..8924944b4fe --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java @@ -0,0 +1,649 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.awt.AWTEvent; +import java.beans.PropertyChangeEvent; +import java.util.EventObject; + +import javax.swing.ImageIcon; +import javax.swing.SwingConstants; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.table.TableColumn; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.internal.swing.CTree; +import org.eclipse.swt.internal.swing.CTreeColumn; +import org.eclipse.swt.internal.swing.UIThreadUtils; +import org.eclipse.swt.internal.swing.Utils; + +/** + * Instances of this class represent a column in a tree widget. + *

    + *
    Styles:
    + *
    LEFT, RIGHT, CENTER
    + *
    Events:
    + *
    Move, Resize, Selection
    + *
    + *

    + * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + * + * @since 3.1 + */ +public class TreeColumn extends Item { + Tree parent; + CTreeColumn handle; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#CENTER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeColumn (Tree parent, int style) { + super (parent, checkStyle (style)); + handle = createHandle(); + this.parent = parent; + parent.createItem (this, parent.getColumnCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#LEFT + * @see SWT#RIGHT + * @see SWT#CENTER + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeColumn (Tree parent, int style, int index) { + super (parent, checkStyle (style)); + handle = createHandle(); + this.parent = parent; + parent.createItem (this, index); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is moved or resized, by sending + * it one of the messages defined in the ControlListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #removeControlListener + */ +public void addControlListener(ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Resize,typedListener); + addListener (SWT.Move,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the control is selected, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the column header is selected. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +CTreeColumn createHandle () { + return CTreeColumn.Factory.newInstance(this, style); +} + +void destroyWidget () { + parent.destroyItem (this); + releaseHandle (); +} + +/** + * Returns a value which describes the position of the + * text or image in the receiver. The value will be one of + * LEFT, RIGHT or CENTER. + * + * @return the alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAlignment () { + checkWidget (); + if ((style & SWT.LEFT) != 0) return SWT.LEFT; + if ((style & SWT.CENTER) != 0) return SWT.CENTER; + if ((style & SWT.RIGHT) != 0) return SWT.RIGHT; + return SWT.LEFT; +} + +boolean moveable; + +/** + * Gets the moveable attribute. A column that is + * not moveable cannot be reordered by the user + * by dragging the header but may be reordered + * by the programmer. + * + * @return the moveable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#getColumnOrder() + * @see Tree#setColumnOrder(int[]) + * @see TreeColumn#setMoveable(boolean) + * @see SWT#Move + * + * @since 3.2 + */ +public boolean getMoveable () { + checkWidget (); + return moveable; +} + +String getNameText () { + return getText (); +} + +/** + * Returns the receiver's parent, which must be a Tree. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Tree getParent () { + checkWidget (); + return parent; +} + +/** + * Gets the resizable attribute. A column that is + * not resizable cannot be dragged by the user but + * may be resized by the programmer. + * + * @return the resizable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getResizable () { + checkWidget (); + return ((TableColumn)handle).getResizable(); +} + +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public String getToolTipText () { + checkWidget(); + return handle.getToolTipText(); +} + +/** + * Gets the width of the receiver. + * + * @return the width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getWidth () { + checkWidget (); + return ((TableColumn)handle).getWidth(); +} + +/** + * Causes the receiver to be resized to its preferred size. + * For a composite, this involves computing the preferred size + * from its layout, if there is one. + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + */ +public void pack () { + checkWidget (); + int index = parent.indexOf (this); + if (index == -1) return; +// int oldWidth = getWidth(); + CTree cTree = (CTree)parent.handle; + int newWidth = cTree.getPreferredColumnWidth(index); + // TODO: check why in the old SWTSwing, +2 is added. + cTree.getColumnModel().getColumn(index).setPreferredWidth(newWidth + 2); +// checkWidget (); +// int columnWidth = 0; +// int hwnd = parent.handle; +// int hDC = OS.GetDC (hwnd); +// int oldFont = 0, newFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); +// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont); +// int cp = parent.getCodePage (); +// RECT rect = new RECT (); +// int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX; +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_PARAM; +// int hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); +// while (hItem != 0) { +// hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem); +// tvItem.hItem = hItem; +// OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem); +// TreeItem item = parent.items [tvItem.lParam]; +// if (index == 0) { +// rect.left = item.handle; +// if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, rect) != 0) { +// columnWidth = Math.max (columnWidth, rect.right); +// } +// } else { +// int imageWidth = 0, textWidth = 0; +// Image image = item.images != null ? item.images [index] : null; +// if (image != null) { +// Rectangle bounds = image.getBounds (); +// imageWidth = bounds.width; +// } +// String string = item.strings != null ? item.strings [index] : null; +// if (string != null) { +// TCHAR buffer = new TCHAR (cp, string, false); +// OS.DrawText (hDC, buffer, buffer.length (), rect, flags); +// textWidth = rect.right - rect.left; +// } +// columnWidth = Math.max (columnWidth, imageWidth + textWidth + Tree.INSET * 3); +// } +// } +// TCHAR buffer = new TCHAR (cp, text, true); +// OS.DrawText (hDC, buffer, buffer.length (), rect, flags); +// int headerWidth = rect.right - rect.left + Tree.HEADER_MARGIN; +// if (image != null) { +// int margin = 0, hwndHeader = parent.hwndHeader; +// if (hwndHeader != 0 && OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) { +// margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0); +// } else { +// margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3; +// } +// Rectangle bounds = image.getBounds (); +// headerWidth += bounds.width + margin * 2; +// } +// if (newFont != 0) OS.SelectObject (hDC, oldFont); +// OS.ReleaseDC (hwnd, hDC); +// setWidth (Math.max (headerWidth, columnWidth)); +} + +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is moved or resized. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ControlListener + * @see #addControlListener + */ +public void removeControlListener (ControlListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Move, listener); + eventTable.unhook (SWT.Resize, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget (); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} + +/** + * Controls how text and images will be displayed in the receiver. + * The argument should be one of LEFT, RIGHT + * or CENTER. + * + * @param alignment the new alignment + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAlignment (int alignment) { + checkWidget (); + if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return; + int index = parent.indexOf (this); + if (index == -1 || index == 0) return; + style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); + style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); + if ((style & SWT.LEFT) == SWT.LEFT) handle.setAlignment(SwingConstants.LEFT); + if ((style & SWT.CENTER) == SWT.CENTER) handle.setAlignment(SwingConstants.CENTER); + if ((style & SWT.RIGHT) == SWT.RIGHT) handle.setAlignment(SwingConstants.RIGHT); + // TODO: notify change +} + +public void setImage (Image image) { + checkWidget(); + if (image != null && image.isDisposed ()) { + error (SWT.ERROR_INVALID_ARGUMENT); + } + int index = parent.indexOf (this); + if (index == -1) return; + super.setImage (image); + handle.setIcon(image == null? null: new ImageIcon(image.handle)); + // TODO: notify repaint +} + +/** + * Sets the moveable attribute. A column that is + * moveable can be reordered by the user by dragging + * the header. A column that is not moveable cannot be + * dragged by the user but may be reordered + * by the programmer. + * + * @param moveable the moveable attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Tree#setColumnOrder(int[]) + * @see Tree#getColumnOrder() + * @see TreeColumn#getMoveable() + * @see SWT#Move + * + * @since 3.2 + */ +public void setMoveable (boolean moveable) { + checkWidget (); + this.moveable = moveable; +} + +/** + * Sets the resizable attribute. A column that is + * not resizable cannot be dragged by the user but + * may be resized by the programmer. + * + * @param resizable the resize attribute + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setResizable (boolean resizable) { + checkWidget (); + ((TableColumn)handle).setResizable(resizable); +} + +public void setText (String string) { + checkWidget (); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + if (string.equals (text)) return; + super.setText (string); + // TODO: check what happens with mnemonics + ((TableColumn)handle).setHeaderValue(string); +} + +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setToolTipText (String string) { + checkWidget(); + handle.setToolTipText(string); +// toolTipText = string; +// int hwndHeaderToolTip = parent.headerToolTipHandle; +// if (hwndHeaderToolTip == 0) { +// parent.createHeaderToolTips (); +// parent.updateHeaderToolTips (); +// } +} + +/** + * Sets the width of the receiver. + * + * @param width the new width + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setWidth (int width) { + checkWidget (); +// ((TableColumn)handle).setWidth(width); + ((TableColumn)handle).setPreferredWidth(width); +} + +public void processEvent(AWTEvent e) { + int id = e.getID(); + switch(id) { + case java.awt.event.MouseEvent.MOUSE_CLICKED: if(!hooks(SWT.Selection)) return; break; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + switch(id) { + case java.awt.event.MouseEvent.MOUSE_CLICKED: { + sendEvent(SWT.Selection); + break; + } + } + } catch(Throwable t) { + UIThreadUtils.storeException(t); + } finally { + UIThreadUtils.stopExclusiveSection(); + } +} + +public void processEvent(EventObject e) { + if(e instanceof PropertyChangeEvent) { + if(!hooks(SWT.Resize) && !hooks(SWT.Move) || !"width".equals(((PropertyChangeEvent)e).getPropertyName())) { return; } + } else if(e instanceof TableColumnModelEvent) { + if(!hooks(SWT.Move)) { return; } + } else { + return; + } + if(isDisposed()) { + return; + } + UIThreadUtils.startExclusiveSection(getDisplay()); + if(isDisposed()) { + UIThreadUtils.stopExclusiveSection(); + return; + } + try { + if(e instanceof PropertyChangeEvent) { + String propertyName = ((PropertyChangeEvent)e).getPropertyName(); + if("width".equals(propertyName)) { + sendEvent(SWT.Resize); + int columnCount = parent.getColumnCount(); + for(int i=parent.indexOf(this) + 1; i + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + * + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ + +public class TreeItem extends Item { + /** + * the handle to the OS resource + * (Warning: This field is platform dependent) + *

    + * IMPORTANT: This field is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It is not available on all + * platforms and should never be accessed from application code. + *

    + */ + CTreeItem handle; + Tree parent; + TreeItem parentItem; + ArrayList itemList; +// String [] strings; + Image [] images; + boolean cached; +// int background = -1, foreground = -1, font = -1; +// int [] cellBackground, cellForeground, cellFont; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree or a TreeItem) + * and a style value describing its behavior and appearance. + * The item is added to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a tree control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeItem (Tree parent, int style) { + super (parent, style); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, ((CTree)parent.handle).getRoot().getChildCount()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree or a TreeItem), + * a style value describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a tree control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeItem (Tree parent, int style, int index) { + super (parent, style); + if (index < 0) error (SWT.ERROR_INVALID_RANGE); + this.parent = parent; + handle = createHandle(); + parent.createItem (this, index); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree or a TreeItem) + * and a style value describing its behavior and appearance. + * The item is added to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parentItem a tree control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeItem (TreeItem parentItem, int style) { + super (checkNull (parentItem).parent, style); + parent = parentItem.parent; + this.parentItem = parentItem; + handle = createHandle(); + parent.createItem (this, parentItem, parentItem.handle.getChildCount()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Tree or a TreeItem), + * a style value describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parentItem a tree control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public TreeItem (TreeItem parentItem, int style, int index) { + super (checkNull (parentItem).parent, style); + if (index < 0) error (SWT.ERROR_INVALID_RANGE); + parent = parentItem.parent; + this.parentItem = parentItem; + handle = createHandle(); + parent.createItem (this, parentItem, index); +} + +static TreeItem checkNull (TreeItem item) { + if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return item; +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +CTreeItem createHandle () { + return CTreeItem.Factory.newInstance(this, style); +} + +/** + * Clears the item at the given zero-relative index in the receiver. + * The text, icon and other attributes of the item are set to the default + * value. If the tree was created with the SWT.VIRTUAL style, + * these attributes are requested again as needed. + * + * @param index the index of the item to clear + * @param all true if all child items of the indexed item should be + * cleared recursively, and false otherwise + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.2 + */ +public void clear (int index, boolean all) { + checkWidget (); + TreeItemObject treeItemObject = handle.getTreeItemObject(index); + treeItemObject.setText(null); + treeItemObject.setBackground(null); + treeItemObject.setForeground(null); + treeItemObject.setFont(null); + treeItemObject.setIcon(null); + if ((parent.style & SWT.VIRTUAL) != 0) cached = false; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + if(all) { + TreeItem[] items = getItems(); + for(int i=0; iSWT.VIRTUAL style, these + * attributes are requested again as needed. + * + * @param all true if all child items should be cleared + * recursively, and false otherwise + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.2 + */ +public void clearAll (boolean all) { + checkWidget (); + text = ""; + image = null; + images = null; + handle.setBackground(null); + handle.setForeground(null); + handle.setFont(null); + handle.setChecked(false); + handle.setGrayed(false); + int count = parent.getColumnCount(); + for(int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + * + * @since 2.0 + * + */ +public Color getBackground () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + java.awt.Color color = handle.getBackground(); + if(color == null) return parent.getBackground(); + return Color.swing_new(display, color); +} + +/** + * Returns the background color at the given column index in the receiver. + * + * @param index the column index + * @return the background color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Color getBackground (int index) { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return getBackground (); + java.awt.Color color = handle.getTreeItemObject(index).getBackground(); + if(color == null) { + if(index != 0) { + return getBackground(); + } + return Color.swing_new(display, parent.handle.getBackground()); + } + return Color.swing_new(display, color); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Rectangle getBounds () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return getBounds(0); +} + +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent at a column in the tree. + * + * @param index the index that specifies the column + * @return the receiver's bounding column rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Rectangle getBounds (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + CTree tree = (CTree)parent.handle; + int row = tree.getRowForPath(new TreePath(handle.getPath())); + if(row == -1) return new Rectangle(0, 0, 0, 0); + java.awt.Rectangle rect = tree.getCellRect(row, index, false); + return new Rectangle(rect.x, rect.y, rect.width, rect.height); +} + +/** + * Returns true if the receiver is checked, + * and false otherwise. When the parent does not have + * the CHECK style, return false. + *

    + * + * @return the checked state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getChecked () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + if ((parent.style & SWT.CHECK) == 0) return false; + return handle.isChecked(); +} + +/** + * Returns true if the receiver is expanded, + * and false otherwise. + *

    + * + * @return the expanded state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getExpanded () { + checkWidget (); + return ((CTree)parent.handle).isExpanded(new TreePath(handle.getPath())); +} + +/** + * Returns the font that the receiver will use to paint textual information for this item. + * + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public Font getFont () { + return getFont(0); +} + +/** + * Returns the font that the receiver will use to paint textual information + * for the specified cell in this item. + * + * @param index the column index + * @return the receiver's font + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Font getFont (int index) { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count -1) return getFont (); + java.awt.Font font = handle.getTreeItemObject(index).getFont(); + if(font == null) { + if(index != 0) { + return getFont(); + } + return Font.swing_new(display, parent.handle.getFont()); + } + return Font.swing_new(display, font); +} + +/** + * Returns the foreground color that the receiver will use to draw. + * + * @return the receiver's foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + * + */ +public Color getForeground () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + java.awt.Color color = handle.getForeground(); + if(color == null) return parent.getForeground(); + return Color.swing_new(display, color); +} + +/** + * + * Returns the foreground color at the given column index in the receiver. + * + * @param index the column index + * @return the foreground color + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Color getForeground (int index) { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count -1) return getForeground (); + java.awt.Color color = handle.getTreeItemObject(index).getForeground(); + if(color == null) { + if(index != 0) { + return getBackground(); + } + return Color.swing_new(display, parent.handle.getForeground()); + } + return Color.swing_new(display, color); +} + +/** + * Returns true if the receiver is grayed, + * and false otherwise. When the parent does not have + * the CHECK style, return false. + *

    + * + * @return the grayed state of the checkbox + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public boolean getGrayed () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + if ((parent.style & SWT.CHECK) == 0) return false; + return handle.isGrayed(); +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public TreeItem getItem (int index) { + checkWidget (); + if (index < 0) error (SWT.ERROR_INVALID_RANGE); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + if(index < 0 || index >= getItemCount()) error (SWT.ERROR_INVALID_RANGE); + return (TreeItem)itemList.get(index); +// int hwnd = parent.handle; +// int hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle); +// if (hFirstItem == 0) error (SWT.ERROR_INVALID_RANGE); +// int hItem = parent.findItem (hFirstItem, index); +// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE); +// return parent._getItem (hItem); +} + +/** + * Returns the number of items contained in the receiver + * that are direct item children of the receiver. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return itemList == null? 0: itemList.size(); +} + +/** + * Returns a (possibly empty) array of TreeItems which + * are the direct item children of the receiver. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the receiver's items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem [] getItems () { + checkWidget (); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return itemList == null? new TreeItem [0]: (TreeItem [])itemList.toArray(new TreeItem [0]); +} + +public Image getImage () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return super.getImage (); +} + +/** + * Returns the image stored at the given column index in the receiver, + * or null if the image has not been set or if the column does not exist. + * + * @param index the column index + * @return the image stored at the given column index in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Image getImage (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + if (index == 0) return getImage (); + if (images != null) { + if (0 <= index && index < images.length) return images [index]; + } + return null; +} + +/** + * Returns a rectangle describing the size and location + * relative to its parent of an image at a column in the + * tree. + * + * @param index the index that specifies the column + * @return the receiver's bounding image rectangle + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public Rectangle getImageBounds (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count -1) return new Rectangle(0, 0, 0, 0); + CTree cTree = ((CTree)parent.handle); + int row = cTree.getRowForPath(new TreePath(handle.getPath())); + java.awt.Rectangle imageBounds = ((CTree)parent.handle).getImageBounds(row, index); + return new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height); + +// java.awt.Color color = handle.getTreeItemObject(index).getForeground(); +// RECT rect = getBounds (index, false, true, false); +// int width = rect.right - rect.left, height = rect.bottom - rect.top; +// return new Rectangle (rect.left, rect.top, width, height); +} + +/** + * Returns the receiver's parent, which must be a Tree. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Tree getParent () { + checkWidget (); + return parent; +} + +/** + * Returns the receiver's parent item, which must be a + * TreeItem or null when the receiver is a + * root. + * + * @return the receiver's parent item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TreeItem getParentItem () { + checkWidget (); + return parentItem; +} + +public String getText () { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + return super.getText (); +} + +/** + * Returns the text stored at the given column index in the receiver, + * or empty string if the text has not been set. + * + * @param index the column index + * @return the text stored at the given column index in the receiver + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public String getText (int index) { + checkWidget(); + if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return ""; + return handle.getTreeItemObject(index).getText(); +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the tool item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the tool item has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public int indexOf (TreeItem item) { + //TODO - make public and add Tree.indexOf(TreeItem) and TreeItem.indexOf(TreeItem)? + checkWidget (); + if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + return itemList == null? -1: itemList.indexOf(item); +} + +void releaseChildren (boolean destroy) { + if (destroy) { + parent.destroyItem (this); + } + super.releaseChildren (destroy); +} + +void releaseHandle () { + super.releaseHandle (); + handle = null; + parent = null; +} + +void releaseWidget() { + super.releaseWidget(); + images = null; +} + +/** + * Removes all of the items from the receiver. + *

    + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void removeAll () { + checkWidget (); + if(itemList != null) { + for (int i=itemList.size()-1; i>=0; i--) { + TreeItem item = (TreeItem)itemList.get(i); + if (item != null && !item.isDisposed ()) { + item.dispose(); +// item.release(false); + } else { + itemList.remove(i); + } + } + } +// int hwnd = parent.handle; +// TVITEM tvItem = new TVITEM (); +// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; +// tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle); +// while (tvItem.hItem != 0) { +// OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem); +// TreeItem item = tvItem.lParam != -1 ? parent.items [tvItem.lParam] : null; +// if (item != null && !item.isDisposed ()) { +// item.dispose (); +// } else { +// parent.releaseItem (tvItem.hItem, tvItem, false); +// parent.destroyItem (null, tvItem.hItem); +// } +// tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle); +// } +} + +/** + * Sets the receiver's background color to the color specified + * by the argument, or to the default system color for the item + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + * + */ +public void setBackground (Color color) { + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setBackground(color == null? null: color.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + +/** + * Sets the background color at the given column index in the receiver + * to the color specified by the argument, or to the default system color for the item + * if the argument is null. + * + * @param index the column index + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + * + */ +public void setBackground (int index, Color color) { + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTreeItemObject(index).setBackground(color == null? null: color.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + +/** + * Sets the checked state of the receiver. + *

    + * + * @param checked the new checked state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setChecked (boolean checked) { + checkWidget (); + if ((parent.style & SWT.CHECK) == 0) return; + handle.setChecked(checked); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); +} + +/** + * Sets the expanded state of the receiver. + *

    + * + * @param expanded the new expanded state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setExpanded (boolean expanded) { + checkWidget (); + + CTree tree = ((CTree)parent.handle); + if(expanded) { + tree.expandPath(new TreePath(handle.getPath())); + } else { + tree.collapsePath(new TreePath(handle.getPath())); + } +} + +/** + * Sets the font that the receiver will use to paint textual information + * for this item to the font specified by the argument, or to the default font + * for that kind of control if the argument is null. + * + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setFont (Font font){ + checkWidget (); + if (font != null && font.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setFont(font == null? null: font.handle); + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + + +/** + * Sets the font that the receiver will use to paint textual information + * for the specified cell in this item to the font specified by the + * argument, or to the default font for that kind of control if the + * argument is null. + * + * @param index the column index + * @param font the new font (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setFont (int index, Font font) { + checkWidget (); + if (font != null && font.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTreeItemObject(index).setFont(font == null? null: font.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + +/** + * Sets the receiver's foreground color to the color specified + * by the argument, or to the default system color for the item + * if the argument is null. + * + * @param color the new color (or null) + * + * @since 2.0 + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 2.0 + * + */ +public void setForeground (Color color) { + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + handle.setForeground(color == null? null: color.handle); + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + +/** + * Sets the foreground color at the given column index in the receiver + * to the color specified by the argument, or to the default system color for the item + * if the argument is null. + * + * @param index the column index + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + * + */ +public void setForeground (int index, Color color){ + checkWidget (); + if (color != null && color.isDisposed ()) { + SWT.error (SWT.ERROR_INVALID_ARGUMENT); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + handle.getTreeItemObject(index).setForeground(color == null? null: color.handle); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.handle.repaint(); +} + +/** + * Sets the grayed state of the checkbox for this item. This state change + * only applies if the Tree was created with the SWT.CHECK style. + * + * @param grayed the new grayed state of the checkbox + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setGrayed (boolean grayed) { + checkWidget (); + if ((parent.style & SWT.CHECK) == 0) return; + handle.setGrayed(grayed); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); +} + +/** + * Sets the image for multiple columns in the tree. + * + * @param images the array of new images + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the array of images is null
    • + *
    • ERROR_INVALID_ARGUMENT - if one of the images has been disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setImage (Image [] images) { + checkWidget(); + if (images == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; i + *
  • ERROR_INVALID_ARGUMENT - if the image has been disposed
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setImage (int index, Image image) { + checkWidget(); + if (image != null && image.isDisposed ()) { + error(SWT.ERROR_INVALID_ARGUMENT); + } + if (index == 0) { + if (image != null && image.type == SWT.ICON) { + if (image.equals (this.image)) return; + } + super.setImage (image); + } + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + if (images == null && index != 0) { + images = new Image [count]; + images [0] = image; + } + if (images != null) { + if (image != null && image.type == SWT.ICON) { + if (image.equals (images [index])) return; + } + images [index] = image; + } + handle.getTreeItemObject(index).setIcon(image != null? new ImageIcon(image.handle): null); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); +} + +public void setImage (Image image) { + checkWidget (); + setImage (0, image); +} + +/** + * Sets the number of child items contained in the receiver. + * + * @param count the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.2 + */ +public void setItemCount (int count) { + checkWidget (); + count = Math.max (0, count); + parent.setItemCount (this, count); +} + +/** + * Sets the text for multiple columns in the tree. + * + * @param strings the array of new strings + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setText (String [] strings) { + checkWidget(); + if (strings == null) error (SWT.ERROR_NULL_ARGUMENT); + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the text is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.1 + */ +public void setText (int index, String string) { + checkWidget(); + if (string == null) error (SWT.ERROR_NULL_ARGUMENT); + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return; + if(index == 0) { + super.setText(string); + } + handle.getTreeItemObject(index).setText(string); + if ((parent.style & SWT.VIRTUAL) != 0) cached = true; + ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle); + parent.adjustColumnWidth(); +} + +public void setText (String string) { + checkWidget(); + setText (0, string); +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java new file mode 100644 index 00000000000..4884c655822 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java @@ -0,0 +1,2208 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import java.util.*; + +import javax.swing.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.swing.*; + +/** + * This class is the abstract superclass of all user interface objects. + * Widgets are created, disposed and issue notification to listeners + * when events occur which affect them. + *
    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    Dispose
    + *
    + *

    + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. However, it has not been marked + * final to allow those outside of the SWT development team to implement + * patched versions of the class in order to get around specific + * limitations in advance of when those limitations can be addressed + * by the team. Any class built using subclassing to access the internals + * of this class will likely fail to compile or run between releases and + * may be strongly platform specific. Subclassing should not be attempted + * without an intimate and detailed understanding of the workings of the + * hierarchy. No support is provided for user-written classes which are + * implemented as subclasses of this class. + *

    + * + * @see #checkSubclass + */ + +public abstract class Widget { + int style, state; + Display display; + EventTable eventTable; + Object data; + + /* Global state flags */ + static final int DISPOSED = 1<<0; + static final int CANVAS = 1<<1; + static final int KEYED_DATA = 1<<2; +// static final int DISABLED = 1<<3; +// static final int HIDDEN = 1<<4; + + /* A layout was requested on this widget */ + static final int LAYOUT_NEEDED = 1<<5; + + /* The preferred size of a child has changed */ + static final int LAYOUT_CHANGED = 1<<6; + + /* A layout was requested in this widget hierachy */ + static final int LAYOUT_CHILD = 1<<7; + + /* Background flags */ + static final int THEME_BACKGROUND = 1<<8; + static final int DRAW_BACKGROUND = 1<<9; + static final int PARENT_BACKGROUND = 1<<10; + + /* Dispose and release flags */ + static final int RELEASED = 1<<11; + static final int DISPOSE_SENT = 1<<12; + + /* Default size for widgets */ + static final int DEFAULT_WIDTH = 64; + static final int DEFAULT_HEIGHT = 64; + +// /* Check and initialize the Common Controls DLL */ +// static final int MAJOR = 5, MINOR = 80; +// static { +// if (!OS.IsWinCE) { +// if (OS.COMCTL32_VERSION < OS.VERSION (MAJOR, MINOR)) { +// System.out.println ("***WARNING: SWT requires comctl32.dll version " + MAJOR + "." + MINOR + " or greater"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ +// System.out.println ("***WARNING: Detected: " + OS.COMCTL32_MAJOR + "." + OS.COMCTL32_MINOR); //$NON-NLS-1$ //$NON-NLS-2$ +// } +// } +// OS.InitCommonControls (); +// } + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Widget () { +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parent is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT + * @see #checkSubclass + * @see #getStyle + */ +public Widget (Widget parent, int style) { + checkSubclass (); + checkParent (parent); + this.style = style; + display = parent.display; +} + +/** + * Adds the listener to the collection of listeners who will + * be notifed when an event of the given type occurs. When the + * event does occur in the widget, the listener is notified by + * sending it the handleEvent() message. The event + * type is one of the event constants defined in class SWT. + * + * @param eventType the type of event to listen for + * @param listener the listener which should be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Listener + * @see SWT + * @see #removeListener + * @see #notifyListeners + */ +public void addListener (int eventType, Listener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) eventTable = new EventTable (); + eventTable.hook (eventType, listener); +} + +protected void addTypedListener (EventListener listener, int... eventTypes) { + throw new UnsupportedOperationException("Not implemented yet"); +} +protected void removeTypedListener (int eventType, EventListener listener) { + throw new UnsupportedOperationException("Not implemented yet"); +} + +/** + * Adds the listener to the collection of listeners who will + * be notifed when the widget is disposed. When the widget is + * disposed, the listener is notified by sending it the + * widgetDisposed() message. + * + * @param listener the listener which should be notified when the receiver is disposed + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DisposeListener + * @see #removeDisposeListener + */ +public void addDisposeListener (DisposeListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Dispose, typedListener); +} + +//int callWindowProc (int hwnd, int msg, int wParam, int lParam) { +// return 0; +//} + +/** + * Returns a style with exactly one style bit set out of + * the specified set of exclusive style bits. All other + * possible bits are cleared when the first matching bit + * is found. Bits that are not part of the possible set + * are untouched. + * + * @param style the original style bits + * @param int0 the 0th possible style bit + * @param int1 the 1st possible style bit + * @param int2 the 2nd possible style bit + * @param int3 the 3rd possible style bit + * @param int4 the 4th possible style bit + * @param int5 the 5th possible style bit + * + * @return the new style bits + */ +static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) { + int mask = int0 | int1 | int2 | int3 | int4 | int5; + if ((style & mask) == 0) style |= int0; + if ((style & int0) != 0) style = (style & ~mask) | int0; + if ((style & int1) != 0) style = (style & ~mask) | int1; + if ((style & int2) != 0) style = (style & ~mask) | int2; + if ((style & int3) != 0) style = (style & ~mask) | int3; + if ((style & int4) != 0) style = (style & ~mask) | int4; + if ((style & int5) != 0) style = (style & ~mask) | int5; + return style; +} + +void checkOrientation (Widget parent) { + style &= ~SWT.MIRRORED; + if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) { + if (parent != null) { + if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT; + if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) style |= SWT.RIGHT_TO_LEFT; + } + } + style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0); +} + +void checkOpened () { + /* Do nothing */ +} + +/** + * Throws an exception if the specified widget can not be + * used as a parent for the receiver. + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the parent is disposed
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + */ +void checkParent (Widget parent) { + if (parent == null) error (SWT.ERROR_NULL_ARGUMENT); + if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); + parent.checkWidget (); + parent.checkOpened (); +} + +/** + * Checks that this class can be subclassed. + *

    + * The SWT class library is intended to be subclassed + * only at specific, controlled points (most notably, + * Composite and Canvas when + * implementing new widgets). This method enforces this + * rule unless it is overridden. + *

    + * IMPORTANT: By providing an implementation of this + * method that allows a subclass of a class which does not + * normally allow subclassing to be created, the implementer + * agrees to be fully responsible for the fact that any such + * subclass will likely fail between SWT releases and will be + * strongly platform specific. No support is provided for + * user-written classes which are implemented in this fashion. + *

    + * The ability to subclass outside of the allowed SWT classes + * is intended purely to enable those not on the SWT development + * team to implement patches in order to get around specific + * limitations in advance of when those limitations can be + * addressed by the team. Subclassing should not be attempted + * without an intimate and detailed understanding of the hierarchy. + *

    + * + * @exception SWTException
      + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + */ +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +/** + * Throws an SWTException if the receiver can not + * be accessed by the caller. This may include both checks on + * the state of the receiver and more generally on the entire + * execution context. This method should be called by + * widget implementors to enforce the standard SWT invariants. + *

    + * Currently, it is an error to invoke any method (other than + * isDisposed()) on a widget that has had its + * dispose() method called. It is also an error + * to call widget methods from any thread that is different + * from the thread that created the widget. + *

    + * In future releases of SWT, there may be more or fewer error + * checks and exceptions may be thrown for different reasons. + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void checkWidget () { + Display display = this.display; + if (display == null) error (SWT.ERROR_WIDGET_DISPOSED); + Thread currentThread = Thread.currentThread (); + if (display.thread != currentThread && !SwingUtilities.isEventDispatchThread()) { + String name = currentThread.getName(); + if(name == null /*|| !name.startsWith(Utils.getSWTSwingUIThreadsNamePrefix())*/) { + error (SWT.ERROR_THREAD_INVALID_ACCESS); + } + } + if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED); +} + +/** + * Destroys the widget in the operating system and releases + * the widget's handle. If the widget does not have a handle, + * this method may hide the widget, mark the widget as destroyed + * or do nothing, depending on the widget. + *

    + * When a widget is destroyed in the operating system, its + * descendents are also destroyed by the operating system. + * This means that it is only necessary to call destroyWidget + * on the root of the widget tree. + *

    + * This method is called after releaseWidget(). + *

    + * See also releaseChild(), releaseWidget() + * and releaseHandle(). + *

    + * + * @see #dispose + */ +void destroyWidget () { + releaseHandle (); +} + +//int DeferWindowPos(int hWinPosInfo, int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags){ +// if (OS.IsWinCE) { +// /* +// * Feature in Windows. On Windows CE, DeferWindowPos always causes +// * a WM_SIZE message, even when the new size is the same as the old +// * size. The fix is to detect that the size has not changed and set +// * SWP_NOSIZE. +// */ +// if ((uFlags & OS.SWP_NOSIZE) == 0) { +// RECT lpRect = new RECT (); +// OS.GetWindowRect (hWnd, lpRect); +// if (cy == lpRect.bottom - lpRect.top && cx == lpRect.right - lpRect.left) { +// /* +// * Feature in Windows. On Windows CE, DeferWindowPos when called +// * with SWP_DRAWFRAME always causes a WM_SIZE message, even +// * when SWP_NOSIZE is set and when the new size is the same as the +// * old size. The fix is to clear SWP_DRAWFRAME when the size is +// * the same. +// */ +// uFlags &= ~OS.SWP_DRAWFRAME; +// uFlags |= OS.SWP_NOSIZE; +// } +// } +// } +// return OS.DeferWindowPos (hWinPosInfo, hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); +//} + +/** + * Disposes of the operating system resources associated with + * the receiver and all its descendents. After this method has + * been invoked, the receiver and all descendents will answer + * true when sent the message isDisposed(). + * Any internal connections between the widgets in the tree will + * have been removed to facilitate garbage collection. + *

    + * NOTE: This method is not called recursively on the descendents + * of the receiver. This means that, widget implementers can not + * detect when a widget is being disposed of by re-implementing + * this method, but should instead listen for the Dispose + * event. + *

    + * + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #addDisposeListener + * @see #removeDisposeListener + * @see #checkWidget + */ +public void dispose () { + /* + * Note: It is valid to attempt to dispose a widget + * more than once. If this happens, fail silently. + */ + if (isDisposed ()) return; + if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); + release (true); +} + +/** + * Does whatever widget specific cleanup is required, and then + * uses the code in SWTError.error to handle the error. + * + * @param code the descriptive error code + * + * @see SWT#error(int) + */ +void error (int code) { + SWT.error(code); +} + +boolean filters (int eventType) { + return display.filters (eventType); +} + +//Widget findItem (int id) { +// return null; +//} + +//char [] fixMnemonic (String string) { +// char [] buffer = new char [string.length ()]; +// string.getChars (0, string.length (), buffer, 0); +// int i = 0, j = 0; +// while (i < buffer.length) { +// if (buffer [i] == '&') { +// if (i + 1 < buffer.length && buffer [i + 1] == '&') { +// buffer [j++] = ' '; +// i++; +// } +// i++; +// } else { +// buffer [j++] = buffer [i++]; +// } +// } +// while (j < buffer.length) buffer [j++] = 0; +// return buffer; +//} + +int findMnemonicIndex (String string) { + int index = 0; + int length = string.length (); + do { + while (index < length && string.charAt (index) != '&') index++; + if (++index >= length) return -1; + if (string.charAt (index) != '&') return index; + index++; + } while (index < length); + return -1; +} + +String fixMnemonic (String string) { + char [] buffer = new char [string.length ()]; + string.getChars (0, string.length (), buffer, 0); + int i = 0, j = 0; + while (i < buffer.length) { + if (buffer [i] == '&') { + if (i + 1 < buffer.length && buffer [i + 1] == '&') { + buffer [j++] = ' '; + i++; + } + i++; + } else { + buffer [j++] = buffer [i++]; + } + } + while (j < buffer.length) buffer [j++] = 0; + return new String(buffer, 0, j); +} + +/** + * Returns the application defined widget data associated + * with the receiver, or null if it has not been set. The + * widget data is a single, unnamed field that is + * stored with every widget. + *

    + * Applications may put arbitrary objects in this field. If + * the object stored in the widget data needs to be notified + * when the widget is disposed of, it is the application's + * responsibility to hook the Dispose event on the widget and + * do so. + *

    + * + * @return the widget data + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - when the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread
    • + *
    + * + * @see #setData(Object) + */ +public Object getData () { + checkWidget(); + return (state & KEYED_DATA) != 0 ? ((Object []) data) [0] : data; +} + +/** + * Returns the application defined property of the receiver + * with the specified name, or null if it has not been set. + *

    + * Applications may have associated arbitrary objects with the + * receiver in this fashion. If the objects stored in the + * properties need to be notified when the widget is disposed + * of, it is the application's responsibility to hook the + * Dispose event on the widget and do so. + *

    + * + * @param key the name of the property + * @return the value of the property or null if it has not been set + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the key is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setData(String, Object) + */ +public Object getData (String key) { + checkWidget(); + if (key == null) error (SWT.ERROR_NULL_ARGUMENT); + if ((state & KEYED_DATA) != 0) { + Object [] table = (Object []) data; + for (int i=1; iDisplay
    that is associated with + * the receiver. + *

    + * A widget's display is either provided when it is created + * (for example, top level Shells) or is the + * same as its parent's display. + *

    + * + * @return the receiver's display + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    + */ +public Display getDisplay () { + Display display = this.display; + if (display == null) error (SWT.ERROR_WIDGET_DISPOSED); + return display; +} + +Menu getMenu () { + return null; +} + +/** + * Returns the name of the widget. This is the name of + * the class without the package name. + * + * @return the name of the widget + */ +String getName () { + String string = getClass ().getName (); + int index = string.lastIndexOf ('.'); + if (index == -1) return string; + return string.substring (index + 1, string.length ()); +} + +/* + * Returns a short printable representation for the contents + * of a widget. For example, a button may answer the label + * text. This is used by toString to provide a + * more meaningful description of the widget. + * + * @return the contents string for the widget + * + * @see #toString + */ +String getNameText () { + return ""; //$NON-NLS-1$ +} + +/** + * Returns the receiver's style information. + *

    + * Note that the value which is returned by this method may + * not match the value which was provided to the constructor + * when the receiver was created. This can occur when the underlying + * operating system does not support a particular combination of + * requested styles. For example, if the platform widget used to + * implement a particular SWT widget always has scroll bars, the + * result of calling this method would always have the + * SWT.H_SCROLL and SWT.V_SCROLL bits set. + *

    + * + * @return the style bits + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getStyle () { + checkWidget(); + return style; +} + +/* + * Returns true if the specified eventType is + * hooked, and false otherwise. Implementations + * of SWT can avoid creating objects and sending events + * when an event happens in the operating system but + * there are no listeners hooked for the event. + * + * @param eventType the event to be checked + * + * @return true when the eventType is hooked and false otherwise + * + * @see #isListening + */ +boolean hooks (int eventType) { + if (eventTable == null) return false; + return eventTable.hooks (eventType); +} + +/** + * Returns true if the widget has been disposed, + * and false otherwise. + *

    + * This method gets the dispose state for the widget. + * When a widget has been disposed, it is an error to + * invoke any other method using the widget. + *

    + * + * @return true when the widget is disposed and false otherwise + */ +public boolean isDisposed () { + return (state & DISPOSED) != 0; +} + +/** + * Returns true if there are any listeners + * for the specified event type associated with the receiver, + * and false otherwise. The event type is one of + * the event constants defined in class SWT. + * + * @param eventType the type of event + * @return true if the event is hooked + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + */ +public boolean isListening (int eventType) { + checkWidget(); + return hooks (eventType); +} + +/* + * Returns true when subclassing is + * allowed and false otherwise + * + * @return true when subclassing is allowed and false otherwise + */ +boolean isValidSubclass () { + return Display.isValidClass (getClass ()); +} + +/* + * Returns true when the current thread is + * the thread that created the widget and false + * otherwise. + * + * @return true when the current thread is the thread that created the widget and false otherwise + */ +boolean isValidThread () { + return getDisplay ().isValidThread (); +} + +void mapEvent (int hwnd, Event event) { +} + +GC new_GC (GCData data) { + return null; +} + +/** + * Notifies all of the receiver's listeners for events + * of the given type that one such event has occurred by + * invoking their handleEvent() method. The + * event type is one of the event constants defined in class + * SWT. + * + * @param eventType the type of event which has occurred + * @param event the event data + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SWT + * @see #addListener + * @see #removeListener + */ +public void notifyListeners (int eventType, Event event) { + checkWidget(); + if (event == null) event = new Event (); + sendEvent (eventType, event); +} + +void postEvent (int eventType) { + sendEvent (eventType, null, false); +} + +void postEvent (int eventType, Event event) { + sendEvent (eventType, event, false); +} + +/* + * Releases the widget hiearchy and optionally destroys + * the receiver. + *

    + * Typically, a widget with children will broadcast this + * message to all children so that they too can release their + * resources. The releaseHandle method is used + * as part of this broadcast to zero the handle fields of the + * children without calling destroyWidget. In + * this scenario, the children are actually destroyed later, + * when the operating system destroys the widget tree. + *

    + * + * @param destroy indicates that the receiver should be destroyed + * + * @see #dispose + * @see #releaseHandle + * @see #releaseParent + * @see #releaseWidget +*/ +void release (boolean destroy) { + if ((state & DISPOSE_SENT) == 0) { + state |= DISPOSE_SENT; + sendEvent (SWT.Dispose); + } + if ((state & DISPOSED) == 0) { + releaseChildren (destroy); + } + if ((state & RELEASED) == 0) { + state |= RELEASED; + if (destroy) { + releaseParent (); + releaseWidget (); + destroyWidget (); + } else { + releaseWidget (); + releaseHandle (); + } + } +} + +void releaseChildren (boolean destroy) { +} + +/* + * Releases the widget's handle by zero'ing it out. + * Does not destroy or release any operating system + * resources. + *

    + * This method is called after releaseWidget + * or from destroyWidget when a widget is being + * destroyed to ensure that the widget is marked as destroyed + * in case the act of destroying the widget in the operating + * system causes application code to run in callback that + * could access the widget. + *

    + * + * @see #dispose + * @see #releaseChildren + * @see #releaseParent + * @see #releaseWidget + */ +void releaseHandle () { + state |= DISPOSED; + display = null; +} + +/* + * Releases the receiver, a child in a widget hierarchy, + * from its parent. + *

    + * When a widget is destroyed, it may be necessary to remove + * it from an internal data structure of the parent. When + * a widget has no handle, it may also be necessary for the + * parent to hide the widget or otherwise indicate that the + * widget has been disposed. For example, disposing a menu + * bar requires that the menu bar first be released from the + * shell when the menu bar is active. This could not be done + * in destroyWidget for the menu bar because the + * parent shell as well as other fields have been null'd out + * already by releaseWidget. + *

    + * This method is called first when a widget is disposed. + * + * @see #dispose + * @see #releaseChild + * @see #releaseWidget + * @see #releaseHandle + */ +void releaseParent () { +} + +/* + * Releases any internal resources back to the operating + * system and clears all fields except the widget handle. + *

    + * When a widget is destroyed, resources that were acquired + * on behalf of the programmer need to be returned to the + * operating system. For example, if the widget made a + * copy of an icon, supplied by the programmer, this copy + * would be freed in releaseWidget. Also, + * to assist the garbage collector and minimize the amount + * of memory that is not reclaimed when the programmer keeps + * a reference to a disposed widget, all fields except the + * handle are zero'd. The handle is needed by destroyWidget. + *

    + * + * @see #dispose + * @see #releaseChildren + * @see #releaseHandle + * @see #releaseParent + */ +void releaseWidget () { + eventTable = null; + data = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notifed when an event of the given type occurs. The event + * type is one of the event constants defined in class SWT. + * + * @param eventType the type of event to listen for + * @param listener the listener which should no longer be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Listener + * @see SWT + * @see #addListener + * @see #notifyListeners + */ +public void removeListener (int eventType, Listener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (eventType, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notifed when an event of the given type occurs. + *

    + * IMPORTANT: This method is not part of the SWT + * public API. It is marked public only so that it can be shared + * within the packages provided by SWT. It should never be + * referenced from application code. + *

    + * + * @param eventType the type of event to listen for + * @param listener the listener which should no longer be notified when the event occurs + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see Listener + * @see #addListener + */ +protected void removeListener (int eventType, SWTEventListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (eventType, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notifed when the widget is disposed. + * + * @param listener the listener which should no longer be notified when the receiver is disposed + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see DisposeListener + * @see #addDisposeListener + */ +public void removeDisposeListener (DisposeListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Dispose, listener); +} + +void sendEvent (Event event) { + Display display = event.display; + if (!display.filterEvent (event)) { + if (eventTable != null) eventTable.sendEvent (event); + } +} + +void sendEvent (int eventType) { + sendEvent (eventType, null, true); +} + +void sendEvent (int eventType, Event event) { + sendEvent (eventType, event, true); +} + +void sendEvent (int eventType, Event event, boolean send) { + if (eventTable == null && !display.filters (eventType)) { + return; + } + if (event == null) event = new Event (); + event.type = eventType; + event.display = display; + event.widget = this; + if (event.time == 0) { + event.time = Utils.getCurrentTime (); + } + if (send) { + sendEvent (event); + } else { + display.postEvent (event); + } +} + +//boolean sendKeyEvent (int type, int msg, int wParam, int lParam) { +// Event event = new Event (); +// if (!setKeyState (event, type, wParam, lParam)) return true; +// return sendKeyEvent (type, msg, wParam, lParam, event); +//} +// +//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) { +// sendEvent (type, event); +// if (isDisposed ()) return false; +// return event.doit; +//} +// +//boolean sendMouseEvent (int type, int button, int hwnd, int msg, int wParam, int lParam) { +// return sendMouseEvent (type, button, 0, 0, false, hwnd, msg, wParam, lParam); +//} +// +//boolean sendMouseEvent (int type, int button, int count, int detail, boolean send, int hwnd, int msg, int wParam, int lParam) { +// if (!hooks (type) && !filters (type)) return true; +// Event event = new Event (); +// event.button = button; +// event.detail = detail; +// event.count = count; +// event.x = (short) (lParam & 0xFFFF); +// event.y = (short) (lParam >> 16); +// setInputState (event, type); +// mapEvent (hwnd, event); +// if (send) { +// sendEvent (type, event); +// if (isDisposed ()) return false; +// } else { +// postEvent (type, event); +// } +// return event.doit; +//} + +/** + * Sets the application defined widget data associated + * with the receiver to be the argument. The widget + * data is a single, unnamed field that is stored + * with every widget. + *

    + * Applications may put arbitrary objects in this field. If + * the object stored in the widget data needs to be notified + * when the widget is disposed of, it is the application's + * responsibility to hook the Dispose event on the widget and + * do so. + *

    + * + * @param data the widget data + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - when the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread
    • + *
    + * + * @see #getData() + */ +public void setData (Object data) { + checkWidget(); + if ((state & KEYED_DATA) != 0) { + ((Object []) this.data) [0] = data; + } else { + this.data = data; + } +} + +/** + * Sets the application defined property of the receiver + * with the specified name to the given value. + *

    + * Applications may associate arbitrary objects with the + * receiver in this fashion. If the objects stored in the + * properties need to be notified when the widget is disposed + * of, it is the application's responsibility to hook the + * Dispose event on the widget and do so. + *

    + * + * @param key the name of the property + * @param value the new value for the property + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the key is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getData(String) + */ +public void setData (String key, Object value) { + checkWidget(); + if (key == null) error (SWT.ERROR_NULL_ARGUMENT); + int index = 1; + Object [] table = null; + if ((state & KEYED_DATA) != 0) { + table = (Object []) data; + while (index < table.length) { + if (key.equals (table [index])) break; + index += 2; + } + } + if (value != null) { + if ((state & KEYED_DATA) != 0) { + if (index == table.length) { + Object [] newTable = new Object [table.length + 2]; + System.arraycopy (table, 0, newTable, 0, table.length); + data = table = newTable; + } + } else { + table = new Object [3]; + table [0] = data; + data = table; + state |= KEYED_DATA; + } + table [index] = key; + table [index + 1] = value; + } else { + if ((state & KEYED_DATA) != 0) { + if (index != table.length) { + int length = table.length - 2; + if (length == 1) { + data = table [0]; + state &= ~KEYED_DATA; + } else { + Object [] newTable = new Object [length]; + System.arraycopy (table, 0, newTable, 0, index); + System.arraycopy (table, index + 2, newTable, index, length - index); + data = newTable; + } + } + } + } +} + +boolean sendFocusEvent (int type) { + sendEvent (type); + // widget could be disposed at this point + return true; +} + +boolean setInputState (Event event, int type) { + event.stateMask |= Display.getInputState(); + switch (type) { + case SWT.MouseDown: + case SWT.MouseDoubleClick: + if (event.button == 1) event.stateMask &= ~SWT.BUTTON1; + if (event.button == 2) event.stateMask &= ~SWT.BUTTON2; + if (event.button == 3) event.stateMask &= ~SWT.BUTTON3; + if (event.button == 4) event.stateMask &= ~SWT.BUTTON4; + if (event.button == 5) event.stateMask &= ~SWT.BUTTON5; + break; + case SWT.MouseUp: + if (event.button == 1) event.stateMask |= SWT.BUTTON1; + if (event.button == 2) event.stateMask |= SWT.BUTTON2; + if (event.button == 3) event.stateMask |= SWT.BUTTON3; + if (event.button == 4) event.stateMask |= SWT.BUTTON4; + if (event.button == 5) event.stateMask |= SWT.BUTTON5; + break; + case SWT.KeyDown: + case SWT.Traverse: + if (event.keyCode == SWT.ALT) event.stateMask &= ~SWT.ALT; + if (event.keyCode == SWT.SHIFT) event.stateMask &= ~SWT.SHIFT; + if (event.keyCode == SWT.CONTROL) event.stateMask &= ~SWT.CONTROL; + break; + case SWT.KeyUp: + if (event.keyCode == SWT.ALT) event.stateMask |= SWT.ALT; + if (event.keyCode == SWT.SHIFT) event.stateMask |= SWT.SHIFT; + if (event.keyCode == SWT.CONTROL) event.stateMask |= SWT.CONTROL; + break; + } + return true; +} + +//boolean setKeyState (Event event, int type, int wParam, int lParam) { +// +// /* +// * Feature in Windows. When the user presses Ctrl+Backspace +// * or Ctrl+Enter, Windows sends a WM_CHAR with Delete (0x7F) +// * and '\n' instead of '\b' and '\r'. This is the correct +// * platform behavior but is not portable. The fix is to detect +// * these cases and convert the character. +// */ +// switch (display.lastAscii) { +// case SWT.DEL: +// if (display.lastKey == SWT.BS) display.lastAscii = SWT.BS; +// break; +// case SWT.LF: +// if (display.lastKey == SWT.CR) display.lastAscii = SWT.CR; +// break; +// } +// +// /* +// * Feature in Windows. When the user presses either the Enter +// * key or the numeric keypad Enter key, Windows sends a WM_KEYDOWN +// * with wParam=VK_RETURN in both cases. In order to distinguish +// * between the keys, the extended key bit is tested. If the bit +// * is set, assume that the numeric keypad Enter was pressed. +// */ +// if (display.lastKey == SWT.CR && display.lastAscii == SWT.CR) { +// if ((lParam & 0x1000000) != 0) display.lastKey = SWT.KEYPAD_CR; +// } +// +// if (display.lastVirtual) { +// /* +// * Feature in Windows. The virtual key VK_DELETE is not +// * treated as both a virtual key and an ASCII key by Windows. +// * Therefore, we will not receive a WM_CHAR for this key. +// * The fix is to treat VK_DELETE as a special case and map +// * the ASCII value explictly (Delete is 0x7F). +// */ +// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F; +// +// /* +// * Feature in Windows. When the user presses Ctrl+Pause, the +// * VK_CANCEL key is generated and a WM_CHAR is sent with 0x03, +// * possibly to allow an application to look for Ctrl+C and the +// * the Break key at the same time. This is unexpected and +// * unwanted. The fix is to detect the case and set the character +// * to zero. +// */ +// if (display.lastKey == OS.VK_CANCEL) display.lastAscii = 0x0; +// +// event.keyCode = Display.translateKey (display.lastKey); +// } else { +// event.keyCode = display.lastKey; +// } +// if (display.lastAscii != 0 || display.lastNull) { +// event.character = Display.mbcsToWcs ((char) display.lastAscii); +// } +// if (event.keyCode == 0 && event.character == 0) { +// if (!display.lastNull) return false; +// } +// return setInputState (event, type); +//} +// +//boolean SetWindowPos (int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags) { +// if (OS.IsWinCE) { +// /* +// * Feature in Windows. On Windows CE, SetWindowPos() always causes +// * a WM_SIZE message, even when the new size is the same as the old +// * size. The fix is to detect that the size has not changed and set +// * SWP_NOSIZE. +// */ +// if ((uFlags & OS.SWP_NOSIZE) == 0) { +// RECT lpRect = new RECT (); +// OS.GetWindowRect (hWnd, lpRect); +// if (cy == lpRect.bottom - lpRect.top && cx == lpRect.right - lpRect.left) { +// /* +// * Feature in Windows. On Windows CE, SetWindowPos() when called +// * with SWP_DRAWFRAME always causes a WM_SIZE message, even +// * when SWP_NOSIZE is set and when the new size is the same as the +// * old size. The fix is to clear SWP_DRAWFRAME when the size is +// * the same. +// */ +// uFlags &= ~OS.SWP_DRAWFRAME; +// uFlags |= OS.SWP_NOSIZE; +// } +// } +// } +// return OS.SetWindowPos (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); +//} + +boolean showMenu (int x, int y) { + Event event = new Event (); + event.x = x; + event.y = y; + sendEvent (SWT.MenuDetect, event); + if (!event.doit) return true; + Menu menu = getMenu (); + if (menu != null && !menu.isDisposed ()) { + if (x != event.x || y != event.y) { + menu.setLocation (event.x, event.y); + } + menu.setVisible (true); + return true; + } + return false; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +@Override +public String toString () { + String string = "*Disposed*"; //$NON-NLS-1$ + if (!isDisposed ()) { + string = "*Wrong Thread*"; //$NON-NLS-1$ + if (isValidThread ()) string = getNameText (); + } + return getName () + " {" + string + "}"; //$NON-NLS-1$ //$NON-NLS-2$ +} + +//LRESULT wmChar (int hwnd, int wParam, int lParam) { +// /* +// * Do not report a lead byte as a key pressed. +// */ +// if (!OS.IsUnicode && OS.IsDBLocale) { +// byte lead = (byte) (wParam & 0xFF); +// if (OS.IsDBCSLeadByte (lead)) return null; +// } +// display.lastAscii = wParam; +// display.lastNull = wParam == 0; +// if (!sendKeyEvent (SWT.KeyDown, OS.WM_CHAR, wParam, lParam)) { +// return LRESULT.ONE; +// } +// // widget could be disposed at this point +// return null; +//} +// +//LRESULT wmContextMenu (int hwnd, int wParam, int lParam) { +// if (wParam != hwnd) return null; +// +// /* +// * Feature in Windows. SHRecognizeGesture() sends an undocumented +// * WM_CONTEXTMENU notification when the flag SHRG_NOTIFY_PARENT is +// * not set. This causes the context menu to be displayed twice, +// * once by the caller of SHRecognizeGesture() and once from this +// * method. The fix is to ignore WM_CONTEXTMENU notifications on +// * all WinCE platforms. +// * +// * NOTE: This only happens on WM2003. Previous WinCE versions did +// * not support WM_CONTEXTMENU. +// */ +// if (OS.IsWinCE) return null; +// +// /* +// * Feature in Windows. When the user presses WM_NCRBUTTONUP, +// * a WM_CONTEXTMENU message is generated. This happens when +// * the user releases the mouse over a scroll bar. Normally, +// * window displays the default scrolling menu but applications +// * can process WM_CONTEXTMENU to display a different menu. +// * Typically, an application does not want to supply a special +// * scroll menu. The fix is to look for a WM_CONTEXTMENU that +// * originated from a mouse event and display the menu when the +// * mouse was released in the client area. +// */ +// int x = 0, y = 0; +// if (lParam != -1) { +// POINT pt = new POINT (); +// x = pt.x = (short) (lParam & 0xFFFF); +// y = pt.y = (short) (lParam >> 16); +// OS.ScreenToClient (hwnd, pt); +// RECT rect = new RECT (); +// OS.GetClientRect (hwnd, rect); +// if (!OS.PtInRect (rect, pt)) return null; +// } else { +// int pos = OS.GetMessagePos (); +// x = (short) (pos & 0xFFFF); +// y = (short) (pos >> 16); +// } +// +// /* Show the menu */ +// return showMenu (x, y) ? LRESULT.ZERO : null; +//} +// +//LRESULT wmIMEChar (int hwnd, int wParam, int lParam) { +// Display display = this.display; +// display.lastKey = 0; +// display.lastAscii = wParam; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) { +// return LRESULT.ONE; +// } +// sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam); +// // widget could be disposed at this point +// display.lastKey = display.lastAscii = 0; +// return LRESULT.ONE; +//} +// +//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) { +// +// /* Ignore repeating modifier keys by testing key down state */ +// switch (wParam) { +// case OS.VK_SHIFT: +// case OS.VK_MENU: +// case OS.VK_CONTROL: +// case OS.VK_CAPITAL: +// case OS.VK_NUMLOCK: +// case OS.VK_SCROLL: +// if ((lParam & 0x40000000) != 0) return null; +// } +// +// /* Clear last key and last ascii because a new key has been typed */ +// display.lastAscii = display.lastKey = 0; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// +// /* +// * Do not report a lead byte as a key pressed. +// */ +// if (!OS.IsUnicode && OS.IsDBLocale) { +// byte lead = (byte) (wParam & 0xFF); +// if (OS.IsDBCSLeadByte (lead)) return null; +// } +// +// /* Map the virtual key */ +// /* +// * Bug in WinCE. MapVirtualKey() returns incorrect values. +// * The fix is to rely on a key mappings table to determine +// * whether the key event must be sent now or if a WM_CHAR +// * event will follow. The key mappings table maps virtual +// * keys to SWT key codes and does not contain mappings for +// * Windows virtual keys like VK_A. Virtual keys that are +// * both virtual and ASCII are a special case. +// */ +// int mapKey = 0; +// if (OS.IsWinCE) { +// switch (wParam) { +// case OS.VK_BACK: mapKey = SWT.BS; break; +// case OS.VK_RETURN: mapKey = SWT.CR; break; +// case OS.VK_DELETE: mapKey = SWT.DEL; break; +// case OS.VK_ESCAPE: mapKey = SWT.ESC; break; +// case OS.VK_TAB: mapKey = SWT.TAB; break; +// } +// } else { +// mapKey = OS.MapVirtualKey (wParam, 2); +// } +// +// /* +// * Bug in Windows 95 and NT. When the user types an accent key such +// * as ^ to get an accented character on a German keyboard, the accent +// * key should be ignored and the next key that the user types is the +// * accented key. The fix is to detect the accent key stroke (called +// * a dead key) by testing the high bit of the value returned by +// * MapVirtualKey(). A further problem is that the high bit on +// * Windows NT is bit 32 while the high bit on Windows 95 is bit 16. +// * They should both be bit 32. +// * +// * When the user types an accent key that does not correspond to a +// * virtual key, MapVirtualKey() won't set the high bit to indicate +// * a dead key. This happens when an accent key, such as '^' is the +// * result of a modifier such as Shift key and MapVirtualKey() always +// * returns the unshifted key. The fix is to peek for a WM_DEADCHAR +// * and avoid issuing the event. +// */ +// if (OS.IsWinNT) { +// if ((mapKey & 0x80000000) != 0) return null; +// } else { +// if ((mapKey & 0x8000) != 0) return null; +// } +// MSG msg = new MSG (); +// int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; +// if (OS.PeekMessage (msg, hwnd, OS.WM_DEADCHAR, OS.WM_DEADCHAR, flags)) { +// display.lastDead = true; +// display.lastVirtual = mapKey == 0; +// display.lastKey = display.lastVirtual ? wParam : mapKey; +// return null; +// } +// +// /* +// * If we are going to get a WM_CHAR, ensure that last key has +// * the correct character value for the key down and key up +// * events. It is not sufficient to ignore the WM_KEYDOWN +// * (when we know we are going to get a WM_CHAR) and compute +// * the key in WM_CHAR because there is not enough information +// * by the time we get the WM_CHAR. For example, when the user +// * types Ctrl+Shift+6 on a US keyboard, we get a WM_CHAR with +// * wParam=30. When the user types Ctrl+Shift+6 on a German +// * keyboard, we also get a WM_CHAR with wParam=30. On the US +// * keyboard Shift+6 is ^, on the German keyboard Shift+6 is &. +// * There is no way to map wParam=30 in WM_CHAR to the correct +// * value. Also, on international keyboards, the control key +// * may be down when the user has not entered a control character. +// * +// * NOTE: On Windows 98, keypad keys are virtual despite the +// * fact that a WM_CHAR is issued. On Windows 2000 and XP, +// * they are not virtual. Therefore it is necessary to force +// * numeric keypad keys to be virtual. +// */ +// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0; +// if (display.lastVirtual) { +// display.lastKey = wParam; +// /* +// * Feature in Windows. The virtual key VK_DELETE is not +// * treated as both a virtual key and an ASCII key by Windows. +// * Therefore, we will not receive a WM_CHAR for this key. +// * The fix is to treat VK_DELETE as a special case and map +// * the ASCII value explictly (Delete is 0x7F). +// */ +// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F; +// +// /* +// * It is possible to get a WM_CHAR for a virtual key when +// * Num Lock is on. If the user types Home while Num Lock +// * is down, a WM_CHAR is issued with WPARM=55 (for the +// * character 7). If we are going to get a WM_CHAR we need +// * to ensure that the last key has the correct value. Note +// * that Ctrl+Home does not issue a WM_CHAR when Num Lock is +// * down. +// */ +// if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) { +// /* +// * Feature in Windows. Calling to ToAscii() or ToUnicode(), clears +// * the accented state such that the next WM_CHAR loses the accent. +// * This makes is critical that the accent key is detected. Also, +// * these functions clear the character that is entered using the +// * special Windows keypad sequence when NumLock is down (ie. typing +// * ALT+0231 should gives 'c' with a cedilla when NumLock is down). +// */ +// if (display.asciiKey (display.lastKey) != 0) return null; +// display.lastAscii = display.numpadKey (display.lastKey); +// } +// } else { +// /* +// * Convert LastKey to lower case because Windows non-virtual +// * keys that are also ASCII keys, such as like VK_A, are have +// * upper case values in WM_KEYDOWN despite the fact that the +// * Shift was not pressed. +// */ +// display.lastKey = OS.CharLower ((short) mapKey); +// +// /* +// * Feature in Windows. The virtual key VK_CANCEL is treated +// * as both a virtual key and ASCII key by Windows. This +// * means that a WM_CHAR with WPARAM=3 will be issued for +// * this key. In order to distinguish between this key and +// * Ctrl+C, mark the key as virtual. +// */ +// if (wParam == OS.VK_CANCEL) display.lastVirtual = true; +// +// /* +// * Some key combinations map to Windows ASCII keys depending +// * on the keyboard. For example, Ctrl+Alt+Q maps to @ on a +// * German keyboard. If the current key combination is special, +// * the correct character is placed in wParam for processing in +// * WM_CHAR. If this is the case, issue the key down event from +// * inside WM_CHAR. +// */ +// int asciiKey = display.asciiKey (wParam); +// if (asciiKey != 0) { +// /* +// * When the user types Ctrl+Space, ToAscii () maps this to +// * Space. Normally, ToAscii () maps a key to a different +// * key if both a WM_KEYDOWN and a WM_CHAR will be issued. +// * To avoid the extra SWT.KeyDown, look for a space and +// * issue the event from WM_CHAR. +// */ +// if (asciiKey == ' ') return null; +// if (asciiKey != wParam) return null; +// /* +// * Feature in Windows. The virtual key VK_CANCEL is treated +// * as both a virtual key and ASCII key by Windows. This +// * means that a WM_CHAR with WPARAM=3 will be issued for +// * this key. To avoid the extra SWT.KeyDown, look for +// * VK_CANCEL and issue the event from WM_CHAR. +// */ +// if (wParam == OS.VK_CANCEL) return null; +// } +// +// /* +// * If the control key is not down at this point, then +// * the key that was pressed was an accent key or a regular +// * key such as 'A' or Shift+A. In that case, issue the +// * key event from WM_CHAR. +// */ +// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return null; +// +// /* +// * Get the shifted state or convert to lower case if necessary. +// * If the user types Ctrl+A, LastAscii should be 'a', not 'A'. +// * If the user types Ctrl+Shift+A, LastAscii should be 'A'. +// * If the user types Ctrl+Shift+6, the value of LastAscii will +// * depend on the international keyboard. +// */ +// if (OS.GetKeyState (OS.VK_SHIFT) < 0) { +// display.lastAscii = display.shiftedKey (wParam); +// if (display.lastAscii == 0) display.lastAscii = mapKey; +// } else { +// display.lastAscii = OS.CharLower ((short) mapKey); +// } +// +// /* Note that Ctrl+'@' is ASCII NUL and is delivered in WM_CHAR */ +// if (display.lastAscii == '@') return null; +// display.lastAscii = display.controlKey (display.lastAscii); +// } +// if (!sendKeyEvent (SWT.KeyDown, OS.WM_KEYDOWN, wParam, lParam)) { +// return LRESULT.ONE; +// } +// // widget could be disposed at this point +// return null; +//} +// +//LRESULT wmKeyUp (int hwnd, int wParam, int lParam) { +// Display display = this.display; +// +// /* Check for hardware keys */ +// if (OS.IsWinCE) { +// if (OS.VK_APP1 <= wParam && wParam <= OS.VK_APP6) { +// display.lastKey = display.lastAscii = 0; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// Event event = new Event (); +// event.detail = wParam - OS.VK_APP1 + 1; +// /* Check the bit 30 to get the key state */ +// int type = (lParam & 0x40000000) != 0 ? SWT.HardKeyUp : SWT.HardKeyDown; +// if (setInputState (event, type)) sendEvent (type, event); +// // widget could be disposed at this point +// return null; +// } +// } +// +// /* +// * If the key up is not hooked, reset last key +// * and last ascii in case the key down is hooked. +// */ +// if (!hooks (SWT.KeyUp) && !display.filters (SWT.KeyUp)) { +// display.lastKey = display.lastAscii = 0; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// return null; +// } +// +// /* Map the virtual key. */ +// /* +// * Bug in WinCE. MapVirtualKey() returns incorrect values. +// * The fix is to rely on a key mappings table to determine +// * whether the key event must be sent now or if a WM_CHAR +// * event will follow. The key mappings table maps virtual +// * keys to SWT key codes and does not contain mappings for +// * Windows virtual keys like VK_A. Virtual keys that are +// * both virtual and ASCII are a special case. +// */ +// int mapKey = 0; +// if (OS.IsWinCE) { +// switch (wParam) { +// case OS.VK_BACK: mapKey = SWT.BS; break; +// case OS.VK_RETURN: mapKey = SWT.CR; break; +// case OS.VK_DELETE: mapKey = SWT.DEL; break; +// case OS.VK_ESCAPE: mapKey = SWT.ESC; break; +// case OS.VK_TAB: mapKey = SWT.TAB; break; +// } +// } else { +// mapKey = OS.MapVirtualKey (wParam, 2); +// } +// +// /* +// * Bug in Windows 95 and NT. When the user types an accent key such +// * as ^ to get an accented character on a German keyboard, the accent +// * key should be ignored and the next key that the user types is the +// * accented key. The fix is to detect the accent key stroke (called +// * a dead key) by testing the high bit of the value returned by +// * MapVirtualKey (). A further problem is that the high bit on +// * Windows NT is bit 32 while the high bit on Windows 95 is bit 16. +// * They should both be bit 32. +// */ +// if (OS.IsWinNT) { +// if ((mapKey & 0x80000000) != 0) return null; +// } else { +// if ((mapKey & 0x8000) != 0) return null; +// } +// if (display.lastDead) return null; +// +// /* +// * NOTE: On Windows 98, keypad keys are virtual despite the +// * fact that a WM_CHAR is issued. On Windows 2000 and XP, +// * they are not virtual. Therefore it is necessary to force +// * numeric keypad keys to be virtual. +// */ +// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0; +// if (display.lastVirtual) { +// display.lastKey = wParam; +// } else { +// /* +// * Feature in Windows. The virtual key VK_CANCEL is treated +// * as both a virtual key and ASCII key by Windows. This +// * means that a WM_CHAR with WPARAM=3 will be issued for +// * this key. In order to distingush between this key and +// * Ctrl+C, mark the key as virtual. +// */ +// if (wParam == OS.VK_CANCEL) display.lastVirtual = true; +// if (display.lastKey == 0) { +// display.lastAscii = 0; +// display.lastNull = display.lastDead = false; +// return null; +// } +// } +// LRESULT result = null; +// if (!sendKeyEvent (SWT.KeyUp, OS.WM_KEYUP, wParam, lParam)) { +// result = LRESULT.ONE; +// } +// // widget could be disposed at this point +// display.lastKey = display.lastAscii = 0; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// return result; +//} +// +//LRESULT wmKillFocus (int hwnd, int wParam, int lParam) { +// int code = callWindowProc (hwnd, OS.WM_KILLFOCUS, wParam, lParam); +// sendFocusEvent (SWT.FocusOut); +// // widget could be disposed at this point +// +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the focus +// * or deactivate events. If this happens, end the +// * processing of the Windows message by returning +// * zero as the result of the window proc. +// */ +// if (isDisposed ()) return LRESULT.ZERO; +// if (code == 0) return LRESULT.ZERO; +// return new LRESULT (code); +//} +// +//LRESULT wmLButtonDblClk (int hwnd, int wParam, int lParam) { +// /* +// * Feature in Windows. Windows sends the following +// * messages when the user double clicks the mouse: +// * +// * WM_LBUTTONDOWN - mouse down +// * WM_LBUTTONUP - mouse up +// * WM_LBUTTONDBLCLK - double click +// * WM_LBUTTONUP - mouse up +// * +// * Applications that expect matching mouse down/up +// * pairs will not see the second mouse down. The +// * fix is to send a mouse down event. +// */ +// sendMouseEvent (SWT.MouseDown, 1, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 1, hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmLButtonDown (int hwnd, int wParam, int lParam) { +// boolean dragging = false, mouseDown = true; +// boolean dragDetect = hooks (SWT.DragDetect); +// if (dragDetect) { +// if (!OS.IsWinCE) { +// /* +// * Feature in Windows. It's possible that the drag +// * operation will not be started while the mouse is +// * down, meaning that the mouse should be captured. +// * This can happen when the user types the ESC key +// * to cancel the drag. The fix is to query the state +// * of the mouse and capture the mouse accordingly. +// */ +// POINT pt = new POINT (); +// pt.x = (short) (lParam & 0xFFFF); +// pt.y = (short) (lParam >> 16); +// OS.ClientToScreen (hwnd, pt); +// dragging = OS.DragDetect (hwnd, pt); +// mouseDown = OS.GetKeyState (OS.VK_LBUTTON) < 0; +// } +// } +// sendMouseEvent (SWT.MouseDown, 1, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_LBUTTONDOWN, wParam, lParam); +// if (OS.IsPPC) { +// /* +// * Note: On WinCE PPC, only attempt to recognize the gesture for +// * a context menu when the control contains a valid menu or there +// * are listeners for the MenuDetect event. +// */ +// Menu menu = getMenu (); +// boolean hasMenu = menu != null && !menu.isDisposed (); +// if (hasMenu || hooks (SWT.MenuDetect)) { +// int x = (short) (lParam & 0xFFFF); +// int y = (short) (lParam >> 16); +// SHRGINFO shrg = new SHRGINFO (); +// shrg.cbSize = SHRGINFO.sizeof; +// shrg.hwndClient = hwnd; +// shrg.ptDown_x = x; +// shrg.ptDown_y = y; +// shrg.dwFlags = OS.SHRG_RETURNCMD; +// int type = OS.SHRecognizeGesture (shrg); +// if (type == OS.GN_CONTEXTMENU) showMenu (x, y); +// } +// } +// if (mouseDown) { +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// } +// if (dragging) { +// Event event = new Event (); +// event.x = (short) (lParam & 0xFFFF); +// event.y = (short) (lParam >> 16); +// postEvent (SWT.DragDetect, event); +// } else { +// if (dragDetect) { +// /* +// * Feature in Windows. DragDetect() captures the mouse +// * and tracks its movement until the user releases the +// * left mouse button, presses the ESC key, or moves the +// * mouse outside the drag rectangle. If the user moves +// * the mouse outside of the drag rectangle, DragDetect() +// * returns true and a drag and drop operation can be +// * started. When the left mouse button is released or +// * the ESC key is pressed, these events are consumed by +// * DragDetect() so that application code that matches +// * mouse down/up pairs or looks for the ESC key will not +// * function properly. The fix is to send the missing +// * events when the drag has not started. +// * +// * NOTE: For now, don't send a fake WM_KEYDOWN/WM_KEYUP +// * events for the ESC key. This would require computing +// * wParam (the key) and lParam (the repeat count, scan code, +// * extended-key flag, context code, previous key-state flag, +// * and transition-state flag) which is non-trivial. +// */ +// if (OS.GetKeyState (OS.VK_ESCAPE) >= 0) { +// OS.SendMessage (hwnd, OS.WM_LBUTTONUP, wParam, lParam); +// } +// } +// } +// return new LRESULT (result); +//} +// +//LRESULT wmLButtonUp (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseUp, 1, hwnd, OS.WM_LBUTTONUP, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_LBUTTONUP, wParam, lParam); +// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2; +// if (((wParam & 0xFFFF) & mask) == 0) { +// if (OS.GetCapture () == hwnd) OS.ReleaseCapture (); +// } +// return new LRESULT (result); +//} +// +//LRESULT wmMButtonDblClk (int hwnd, int wParam, int lParam) { +// /* +// * Feature in Windows. Windows sends the following +// * messages when the user double clicks the mouse: +// * +// * WM_MBUTTONDOWN - mouse down +// * WM_MBUTTONUP - mouse up +// * WM_MLBUTTONDBLCLK - double click +// * WM_MBUTTONUP - mouse up +// * +// * Applications that expect matching mouse down/up +// * pairs will not see the second mouse down. The +// * fix is to send a mouse down event. +// */ +// sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 2, hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmMButtonDown (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_MBUTTONDOWN, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmMButtonUp (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseUp, 2, hwnd, OS.WM_MBUTTONUP, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_MBUTTONUP, wParam, lParam); +// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2; +// if (((wParam & 0xFFFF) & mask) == 0) { +// if (OS.GetCapture () == hwnd) OS.ReleaseCapture (); +// } +// return new LRESULT (result); +//} +// +//LRESULT wmMouseHover (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseHover, 0, hwnd, OS.WM_MOUSEHOVER, wParam, lParam); +// return null; +//} +// +//LRESULT wmMouseLeave (int hwnd, int wParam, int lParam) { +// if (!hooks (SWT.MouseExit) && !filters (SWT.MouseExit)) return null; +// int pos = OS.GetMessagePos (); +// POINT pt = new POINT (); +// pt.x = (short) (pos & 0xFFFF); +// pt.y = (short) (pos >> 16); +// OS.ScreenToClient (hwnd, pt); +// lParam = pt.x | (pt.y << 16); +// sendMouseEvent (SWT.MouseExit, 0, hwnd, OS.WM_MOUSELEAVE, wParam, lParam); +// return null; +//} +// +//LRESULT wmMouseMove (int hwnd, int wParam, int lParam) { +// int pos = OS.GetMessagePos (); +// if (pos != display.lastMouse) { +// if (!OS.IsWinCE) { +// boolean mouseEnter = hooks (SWT.MouseEnter) || display.filters (SWT.MouseEnter); +// boolean mouseExit = hooks (SWT.MouseExit) || display.filters (SWT.MouseExit); +// boolean mouseHover = hooks (SWT.MouseHover) || display.filters (SWT.MouseHover); +// if (mouseEnter || mouseExit || mouseHover) { +// TRACKMOUSEEVENT lpEventTrack = new TRACKMOUSEEVENT (); +// lpEventTrack.cbSize = TRACKMOUSEEVENT.sizeof; +// lpEventTrack.dwFlags = OS.TME_QUERY; +// lpEventTrack.hwndTrack = hwnd; +// OS.TrackMouseEvent (lpEventTrack); +// if (lpEventTrack.dwFlags == 0) { +// lpEventTrack.dwFlags = OS.TME_LEAVE | OS.TME_HOVER; +// lpEventTrack.hwndTrack = hwnd; +// OS.TrackMouseEvent (lpEventTrack); +// if (mouseEnter) { +// /* +// * Force all outstanding WM_MOUSELEAVE messages to be dispatched before +// * issuing a mouse enter. This causes mouse exit events to be processed +// * before mouse enter events. Note that WM_MOUSELEAVE is posted to the +// * event queue by TrackMouseEvent(). +// */ +// MSG msg = new MSG (); +// int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; +// while (OS.PeekMessage (msg, 0, OS.WM_MOUSELEAVE, OS.WM_MOUSELEAVE, flags)) { +// OS.TranslateMessage (msg); +// OS.DispatchMessage (msg); +// } +// sendMouseEvent (SWT.MouseEnter, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam); +// } +// } else { +// lpEventTrack.dwFlags = OS.TME_HOVER; +// OS.TrackMouseEvent (lpEventTrack); +// } +// } +// } +// display.lastMouse = pos; +// sendMouseEvent (SWT.MouseMove, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam); +// } +// return null; +//} +// +//LRESULT wmMouseWheel (int hwnd, int wParam, int lParam) { +// if (!hooks (SWT.MouseWheel) && !filters (SWT.MouseWheel)) return null; +// int delta = wParam >> 16; +// int [] value = new int [1]; +// int count, detail; +// OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, value, 0); +// if (value [0] == OS.WHEEL_PAGESCROLL) { +// detail = SWT.SCROLL_PAGE; +// count = delta / OS.WHEEL_DELTA; +// } else { +// detail = SWT.SCROLL_LINE; +// count = value [0] * delta / OS.WHEEL_DELTA; +// } +// POINT pt = new POINT (); +// pt.x = (short) (lParam & 0xFFFF); +// pt.y = (short) (lParam >> 16); +// OS.ScreenToClient (hwnd, pt); +// lParam = pt.x | (pt.y << 16); +// if (!sendMouseEvent (SWT.MouseWheel, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam)) { +// return LRESULT.ZERO; +// } +// return null; +//} +// +//LRESULT wmPaint (int hwnd, int wParam, int lParam) { +// +// /* Exit early - don't draw the background */ +// if (!hooks (SWT.Paint) && !filters (SWT.Paint)) { +// return null; +// } +// +// /* Get the damage */ +// int result = 0; +// if (OS.IsWinCE) { +// RECT rect = new RECT (); +// OS.GetUpdateRect (hwnd, rect, false); +// result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam); +// OS.InvalidateRect (hwnd, rect, false); +// } else { +// int rgn = OS.CreateRectRgn (0, 0, 0, 0); +// OS.GetUpdateRgn (hwnd, rgn, false); +// result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam); +// /* +// * Bug in Windows. When InvalidateRgn(), InvalidateRect() +// * or RedrawWindow() with RDW_INVALIDATE is called from +// * within WM_PAINT to invalidate a region for a further +// * BeginPaint(), the caret is not properly erased causing +// * pixel corruption. The fix is to hide and show the +// * caret. +// */ +// OS.HideCaret (hwnd); +// OS.InvalidateRgn (hwnd, rgn, false); +// OS.ShowCaret (hwnd); +// OS.DeleteObject (rgn); +// } +// +// /* Send the paint event */ +// PAINTSTRUCT ps = new PAINTSTRUCT (); +// GCData data = new GCData (); +// data.ps = ps; +// data.hwnd = hwnd; +// GC gc = new_GC (data); +// if (gc != null) { +// int width = ps.right - ps.left; +// int height = ps.bottom - ps.top; +// if (width != 0 && height != 0) { +// Event event = new Event (); +// event.gc = gc; +// event.x = ps.left; +// event.y = ps.top; +// event.width = width; +// event.height = height; +// sendEvent (SWT.Paint, event); +// // widget could be disposed at this point +// event.gc = null; +// } +// gc.dispose (); +// } +// if (result == 0) return LRESULT.ZERO; +// return new LRESULT (result); +//} +// +//LRESULT wmRButtonDblClk (int hwnd, int wParam, int lParam) { +// /* +// * Feature in Windows. Windows sends the following +// * messages when the user double clicks the mouse: +// * +// * WM_RBUTTONDOWN - mouse down +// * WM_RBUTTONUP - mouse up +// * WM_RBUTTONDBLCLK - double click +// * WM_LBUTTONUP - mouse up +// * +// * Applications that expect matching mouse down/up +// * pairs will not see the second mouse down. The +// * fix is to send a mouse down event. +// */ +// sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, 3, hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmRButtonDown (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_RBUTTONDOWN, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmRButtonUp (int hwnd, int wParam, int lParam) { +// sendMouseEvent (SWT.MouseUp, 3, hwnd, OS.WM_RBUTTONUP, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_RBUTTONUP, wParam, lParam); +// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2; +// if (((wParam & 0xFFFF) & mask) == 0) { +// if (OS.GetCapture () == hwnd) OS.ReleaseCapture (); +// } +// return new LRESULT (result); +//} +// +//LRESULT wmSetFocus (int hwnd, int wParam, int lParam) { +// int code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam); +// sendFocusEvent (SWT.FocusIn); +// // widget could be disposed at this point +// +// /* +// * It is possible (but unlikely), that application +// * code could have disposed the widget in the focus +// * or activate events. If this happens, end the +// * processing of the Windows message by returning +// * zero as the result of the window proc. +// */ +// if (isDisposed ()) return LRESULT.ZERO; +// if (code == 0) return LRESULT.ZERO; +// return new LRESULT (code); +//} +// +//LRESULT wmSysChar (int hwnd, int wParam, int lParam) { +// Display display = this.display; +// display.lastAscii = wParam; +// display.lastNull = wParam == 0; +// +// /* Do not issue a key down if a menu bar mnemonic was invoked */ +// if (!hooks (SWT.KeyDown) && !display.filters (SWT.KeyDown)) { +// return null; +// } +// +// /* Call the window proc to determine whether it is a system key or mnemonic */ +// boolean oldKeyHit = display.mnemonicKeyHit; +// display.mnemonicKeyHit = true; +// int result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam); +// boolean consumed = false; +// if (!display.mnemonicKeyHit) { +// consumed = !sendKeyEvent (SWT.KeyDown, OS.WM_SYSCHAR, wParam, lParam); +// // widget could be disposed at this point +// } +// consumed |= display.mnemonicKeyHit; +// display.mnemonicKeyHit = oldKeyHit; +// return consumed ? LRESULT.ONE : new LRESULT (result); +//} +// +//LRESULT wmSysKeyDown (int hwnd, int wParam, int lParam) { +// /* +// * Feature in Windows. When WM_SYSKEYDOWN is sent, +// * the user pressed ALT+ or F10 to get to the +// * menu bar. In order to issue events for F10 but +// * ignore other key presses when the ALT is not down, +// * make sure that either F10 was pressed or that ALT +// * is pressed. +// */ +// if (wParam != OS.VK_F10) { +// /* Make sure WM_SYSKEYDOWN was sent by ALT-. */ +// if ((lParam & 0x20000000) == 0) return null; +// } +// +// /* Ignore well known system keys */ +// switch (wParam) { +// case OS.VK_F4: return null; +// } +// +// /* Ignore repeating modifier keys by testing key down state */ +// switch (wParam) { +// case OS.VK_SHIFT: +// case OS.VK_MENU: +// case OS.VK_CONTROL: +// case OS.VK_CAPITAL: +// case OS.VK_NUMLOCK: +// case OS.VK_SCROLL: +// if ((lParam & 0x40000000) != 0) return null; +// } +// +// /* Clear last key and last ascii because a new key has been typed */ +// display.lastAscii = display.lastKey = 0; +// display.lastVirtual = display.lastNull = display.lastDead = false; +// +// /* If are going to get a WM_SYSCHAR, ignore this message. */ +// /* +// * Bug in WinCE. MapVirtualKey() returns incorrect values. +// * The fix is to rely on a key mappings table to determine +// * whether the key event must be sent now or if a WM_CHAR +// * event will follow. The key mappings table maps virtual +// * keys to SWT key codes and does not contain mappings for +// * Windows virtual keys like VK_A. Virtual keys that are +// * both virtual and ASCII are a special case. +// */ +// int mapKey = 0; +// if (OS.IsWinCE) { +// switch (wParam) { +// case OS.VK_BACK: mapKey = SWT.BS; break; +// case OS.VK_RETURN: mapKey = SWT.CR; break; +// case OS.VK_DELETE: mapKey = SWT.DEL; break; +// case OS.VK_ESCAPE: mapKey = SWT.ESC; break; +// case OS.VK_TAB: mapKey = SWT.TAB; break; +// } +// } else { +// mapKey = OS.MapVirtualKey (wParam, 2); +// } +// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0; +// if (display.lastVirtual) { +// display.lastKey = wParam; +// /* +// * Feature in Windows. The virtual key VK_DELETE is not +// * treated as both a virtual key and an ASCII key by Windows. +// * Therefore, we will not receive a WM_SYSCHAR for this key. +// * The fix is to treat VK_DELETE as a special case and map +// * the ASCII value explictly (Delete is 0x7F). +// */ +// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F; +// +// /* When a keypad key is typed, a WM_SYSCHAR is not issued */ +// if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) { +// display.lastAscii = display.numpadKey (display.lastKey); +// } +// } else { +// /* +// * Convert LastKey to lower case because Windows non-virtual +// * keys that are also ASCII keys, such as like VK_A, are have +// * upper case values in WM_SYSKEYDOWN despite the fact that the +// * Shift was not pressed. +// */ +// display.lastKey = OS.CharLower ((short) mapKey); +// +// /* +// * Feature in Windows 98. MapVirtualKey() indicates that +// * a WM_SYSCHAR message will occur for Alt+Enter but +// * this message never happens. The fix is to issue the +// * event from WM_SYSKEYDOWN and map VK_RETURN to '\r'. +// */ +// if (OS.IsWinNT) return null; +// if (wParam != OS.VK_RETURN) return null; +// display.lastAscii = '\r'; +// } +// +// if (!sendKeyEvent (SWT.KeyDown, OS.WM_SYSKEYDOWN, wParam, lParam)) { +// return LRESULT.ONE; +// } +// // widget could be disposed at this point +// return null; +//} +// +//LRESULT wmSysKeyUp (int hwnd, int wParam, int lParam) { +// return wmKeyUp (hwnd, wParam, lParam); +//} +// +//LRESULT wmXButtonDblClk (int hwnd, int wParam, int lParam) { +// /* +// * Feature in Windows. Windows sends the following +// * messages when the user double clicks the mouse: +// * +// * WM_XBUTTONDOWN - mouse down +// * WM_XBUTTONUP - mouse up +// * WM_XLBUTTONDBLCLK - double click +// * WM_XBUTTONUP - mouse up +// * +// * Applications that expect matching mouse down/up +// * pairs will not see the second mouse down. The +// * fix is to send a mouse down event. +// */ +// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5; +// sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam); +// sendMouseEvent (SWT.MouseDoubleClick, button, hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmXButtonDown (int hwnd, int wParam, int lParam) { +// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5; +// sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_XBUTTONDOWN, wParam, lParam); +// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd); +// return new LRESULT (result); +//} +// +//LRESULT wmXButtonUp (int hwnd, int wParam, int lParam) { +// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5; +// sendMouseEvent (SWT.MouseUp, button, hwnd, OS.WM_XBUTTONUP, wParam, lParam); +// int result = callWindowProc (hwnd, OS.WM_XBUTTONUP, wParam, lParam); +// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2; +// if (((wParam & 0xFFFF) & mask) == 0) { +// if (OS.GetCapture () == hwnd) OS.ReleaseCapture (); +// } +// return new LRESULT (result); +// +public void reskin(int flags) { + throw new UnsupportedOperationException("Not implemented yet"); +} +void reskinChildren (int flags) { + throw new UnsupportedOperationException("Not implemented yet"); +} +void reskinWidget() { + throw new UnsupportedOperationException("Not implemented yet"); +} +} diff --git a/examples/org.eclipse.swt.snippets/.classpath_swing b/examples/org.eclipse.swt.snippets/.classpath_swing new file mode 100644 index 00000000000..327658cb814 --- /dev/null +++ b/examples/org.eclipse.swt.snippets/.classpath_swing @@ -0,0 +1,7 @@ + + + + + + + diff --git a/examples/org.eclipse.swt.snippets/.project b/examples/org.eclipse.swt.snippets/.project index e84855c94e0..0883ce95177 100644 --- a/examples/org.eclipse.swt.snippets/.project +++ b/examples/org.eclipse.swt.snippets/.project @@ -26,6 +26,11 @@ org.eclipse.pde.PluginNature + + .classpath + 1 + PROJECT_LOC/.classpath_swing + .settings/org.eclipse.jdt.core.prefs 1